annotate style/ThornStyle.cpp @ 668:dac3781826da thorn-cpp

Experimental branch based on Thorn C++ code from RG
author Chris Cannam
date Tue, 30 Apr 2019 11:36:38 +0100
parents
children
rev   line source
Chris@668 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@668 2
Chris@668 3 /*
Chris@668 4 Vect
Chris@668 5 An experimental audio player for plural recordings of a work
Chris@668 6 Centre for Digital Music, Queen Mary, University of London.
Chris@668 7
Chris@668 8 This file is based on Rosegarden, a MIDI and audio sequencer and
Chris@668 9 musical notation editor. Copyright 2000-2018 the Rosegarden
Chris@668 10 development team. Thorn style developed in stylesheet form by
Chris@668 11 D. Michael McIntyre and reimplemented as a class by David Faure.
Chris@668 12
Chris@668 13 This program is free software; you can redistribute it and/or
Chris@668 14 modify it under the terms of the GNU General Public License as
Chris@668 15 published by the Free Software Foundation; either version 2 of the
Chris@668 16 License, or (at your option) any later version. See the file
Chris@668 17 COPYING included with this distribution for more information.
Chris@668 18 */
Chris@668 19
Chris@668 20 #include "ThornStyle.h"
Chris@668 21 #include "AppEventFilter.h"
Chris@668 22
Chris@668 23 #include "base/ResourceFinder.h"
Chris@668 24 #include "widgets/IconLoader.h"
Chris@668 25
Chris@668 26 #include <QApplication>
Chris@668 27 #include <QAbstractItemView>
Chris@668 28 #include <QCheckBox>
Chris@668 29 #include <QDebug>
Chris@668 30 #include <qdrawutil.h>
Chris@668 31 #include <QEvent>
Chris@668 32 #include <QFile>
Chris@668 33 #include <QFileDialog>
Chris@668 34 #include <QLabel>
Chris@668 35 #include <QLayout>
Chris@668 36 #include <QPainter>
Chris@668 37 #include <QRadioButton>
Chris@668 38 #include <QStyleFactory>
Chris@668 39 #include <QStyleOption>
Chris@668 40 #include <QToolBar>
Chris@668 41 #include <QWidget>
Chris@668 42 #include <QDialogButtonBox>
Chris@668 43 #include <QPushButton>
Chris@668 44 #include <QComboBox>
Chris@668 45 #include <QSpinBox>
Chris@668 46 #include <QScrollBar>
Chris@668 47 #include <QAbstractScrollArea>
Chris@668 48
Chris@668 49 // Silence gcc compiler warnings due to the switches below not covering all cases, on purpose
Chris@668 50 #pragma GCC diagnostic push
Chris@668 51 #pragma GCC diagnostic ignored "-Wswitch-enum"
Chris@668 52
Chris@668 53 static QPixmap loadPix(const QString &name)
Chris@668 54 {
Chris@668 55 QPixmap pix(name);
Chris@668 56 if (pix.isNull()) {
Chris@668 57 qWarning() << "Pixmap not found:" << name;
Chris@668 58 Q_ASSERT(0);
Chris@668 59 }
Chris@668 60 return pix;
Chris@668 61 }
Chris@668 62
Chris@668 63 Q_GLOBAL_STATIC(AppEventFilter, s_eventFilter) // created on demand in setEnabled
Chris@668 64
Chris@668 65 ////////////////////////////////////////////////////////////////////////////////////////////////////////
Chris@668 66
Chris@668 67 ThornStyle::ThornStyle()
Chris@668 68 // We could load these on demand, but the mainwindow needs most of them already anyway
Chris@668 69 : m_horizontalToolbarSeparatorPixmap(loadPix(":/icons/style/htoolbar-separator.png")),
Chris@668 70 m_verticalToolbarSeparatorPixmap(loadPix(":/icons/style/vtoolbar-separator.png")),
Chris@668 71 m_checkboxUncheckedPixmap(loadPix(":/icons/style/checkbox_unchecked.png")),
Chris@668 72 m_checkboxUncheckedHoverPixmap(loadPix(":/icons/style/checkbox_unchecked_hover.png")),
Chris@668 73 m_checkboxUncheckedDisabledPixmap(loadPix(":/icons/style/checkbox_disabled.png")),
Chris@668 74 m_checkboxUncheckedPressedPixmap(loadPix(":/icons/style/checkbox_unchecked_pressed.png")),
Chris@668 75 m_checkboxCheckedPixmap(loadPix(":/icons/style/checkbox_checked.png")),
Chris@668 76 m_checkboxCheckedHoverPixmap(loadPix(":/icons/style/checkbox_checked_hover.png")),
Chris@668 77 m_checkboxCheckedDisabledPixmap(loadPix(":/icons/style/checkbox_checked_disabled.png")),
Chris@668 78 m_checkboxCheckedPressedPixmap(loadPix(":/icons/style/checkbox_checked_pressed.png")),
Chris@668 79 m_checkboxIndeterminatePixmap(loadPix(":/icons/style/checkbox_indeterminate.png")),
Chris@668 80 m_checkboxIndeterminateHoverPixmap(loadPix(":/icons/style/checkbox_indeterminate_hover.png")),
Chris@668 81 //m_checkboxIndeterminateDisabledPixmap(loadPix(":/icons/style/checkbox_indeterminate_disabled.png")),
Chris@668 82 m_checkboxIndeterminatePressedPixmap(loadPix(":/icons/style/checkbox_indeterminate_pressed.png")),
Chris@668 83 m_radiobuttonUncheckedPixmap(loadPix(":/icons/style/radiobutton_unchecked.png")),
Chris@668 84 m_radiobuttonUncheckedHoverPixmap(loadPix(":/icons/style/radiobutton_unchecked_hover.png")),
Chris@668 85 m_radiobuttonUncheckedDisabledPixmap(loadPix(":/icons/style/radiobutton_unchecked_disabled.png")),
Chris@668 86 m_radiobuttonUncheckedPressedPixmap(loadPix(":/icons/style/radiobutton_unchecked_pressed.png")),
Chris@668 87 m_radiobuttonCheckedPixmap(loadPix(":/icons/style/radiobutton_checked.png")),
Chris@668 88 m_radiobuttonCheckedHoverPixmap(loadPix(":/icons/style/radiobutton_checked_hover.png")),
Chris@668 89 m_radiobuttonCheckedDisabledPixmap(loadPix(":/icons/style/radiobutton_checked_disabled.png")),
Chris@668 90 m_radiobuttonCheckedPressedPixmap(loadPix(":/icons/style/radiobutton_checked_pressed.png")),
Chris@668 91 m_arrowDownSmallPixmap(loadPix(":/icons/style/arrow-down-small.png")),
Chris@668 92 m_arrowDownSmallInvertedPixmap(loadPix(":/icons/style/arrow-down-small-inverted.png")),
Chris@668 93 m_arrowUpSmallPixmap(loadPix(":/icons/style/arrow-up-small.png")),
Chris@668 94 m_arrowUpSmallInvertedPixmap(loadPix(":/icons/style/arrow-up-small-inverted.png")),
Chris@668 95 m_arrowLeftPixmap(":/icons/style/arrow-left.png"),
Chris@668 96 m_arrowRightPixmap(":/icons/style/arrow-right.png"),
Chris@668 97 m_arrowUpPixmap(":/icons/style/arrow-up.png"),
Chris@668 98 m_arrowDownPixmap(":/icons/style/arrow-down.png"),
Chris@668 99 m_spinupPixmap(":/icons/style/spinup.png"),
Chris@668 100 m_spinupHoverPixmap(":/icons/style/spinup_hover.png"),
Chris@668 101 m_spinupOffPixmap(":/icons/style/spinup_off.png"),
Chris@668 102 m_spinupPressedPixmap(":/icons/style/spinup_pressed.png"),
Chris@668 103 m_spindownPixmap(":/icons/style/spindown.png"),
Chris@668 104 m_spindownHoverPixmap(":/icons/style/spindown_hover.png"),
Chris@668 105 m_spindownOffPixmap(":/icons/style/spindown_off.png"),
Chris@668 106 m_spindownPressedPixmap(":/icons/style/spindown_pressed.png"),
Chris@668 107 m_titleClosePixmap(":/icons/style/title-close.png"),
Chris@668 108 m_titleUndockPixmap(":/icons/style/title-undock.png")
Chris@668 109 {
Chris@668 110 // Qt 5 removes QPlastiqueStyle and defaults to a new style called "Fusion."
Chris@668 111 // This style forces combo boxes to do bad things.
Chris@668 112 // I concluded that using "windows" as a base style causes an acceptable amount
Chris@668 113 // of damage while leaving things largely intact.
Chris@668 114 setBaseStyle(QStyleFactory::create("windows"));
Chris@668 115
Chris@668 116 m_standardPalette.setColor(QPalette::Window, QColor(0x30, 0x30, 0x30));
Chris@668 117
Chris@668 118 // QLabel { color: white }
Chris@668 119 m_standardPalette.setColor(QPalette::WindowText, Qt::white);
Chris@668 120
Chris@668 121 // QListView, QTableView, QTreeView, QLineEdit... :
Chris@668 122 // background-color: #FFFFFF;
Chris@668 123 // color: #000000;
Chris@668 124 // selection-background-color: #80AFFF;
Chris@668 125 // selection-color: #FFFFFF;
Chris@668 126 m_standardPalette.setColor(QPalette::Base, Qt::white);
Chris@668 127 m_standardPalette.setColor(QPalette::Text, Qt::black);
Chris@668 128 m_standardPalette.setColor(QPalette::Highlight, QColor(0x80, 0xAF, 0xFF));
Chris@668 129 m_standardPalette.setColor(QPalette::HighlightedText, Qt::white);
Chris@668 130
Chris@668 131 // for QPushButton but also QMenu
Chris@668 132 const QColor buttonColor = QColor(0xEE, 0xEE, 0xEE);
Chris@668 133 m_standardPalette.setColor(QPalette::Button, buttonColor);
Chris@668 134 m_standardPalette.setColor(QPalette::ButtonText, Qt::black); // enabled button texts and menu items
Chris@668 135
Chris@668 136 // alternate-background-color: #EEEEFF;
Chris@668 137 m_standardPalette.setColor(QPalette::AlternateBase, QColor(0xEE, 0xEE, 0xFF));
Chris@668 138
Chris@668 139 // QToolTip { background-color: #fffbd4; color: #000000; + some awful pixmap hack }
Chris@668 140 m_standardPalette.setColor(QPalette::ToolTipBase, QColor(0xFF, 0xFB, 0xD4));
Chris@668 141 m_standardPalette.setColor(QPalette::ToolTipText, Qt::black);
Chris@668 142 }
Chris@668 143
Chris@668 144 ThornStyle::~ThornStyle()
Chris@668 145 {
Chris@668 146 }
Chris@668 147
Chris@668 148 QIcon ThornStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *parent) const
Chris@668 149 {
Chris@668 150 IconLoader loader;
Chris@668 151
Chris@668 152 // NOTE: see src/gui/styles/qcommonstyle.cpp in the Qt source for examples
Chris@668 153 // of how to extend this whenever more custom icons are called for
Chris@668 154 switch (standardIcon) {
Chris@668 155
Chris@668 156 // custom icons for QMessageBox
Chris@668 157 case SP_MessageBoxInformation:
Chris@668 158 return loader.load("style/messagebox-information");
Chris@668 159
Chris@668 160 case SP_MessageBoxWarning:
Chris@668 161 return loader.load("style/warning");
Chris@668 162
Chris@668 163 case SP_MessageBoxCritical:
Chris@668 164 return loader.load("style/messagebox-critical");
Chris@668 165
Chris@668 166 case SP_MessageBoxQuestion:
Chris@668 167 return loader.load("style/messagebox-question");
Chris@668 168
Chris@668 169 case SP_TitleBarNormalButton:
Chris@668 170 return m_titleUndockPixmap;
Chris@668 171
Chris@668 172 case SP_DockWidgetCloseButton:
Chris@668 173 case SP_TitleBarCloseButton:
Chris@668 174 return m_titleClosePixmap;
Chris@668 175
Chris@668 176 default:
Chris@668 177 // let the base class handle the rest
Chris@668 178 return QProxyStyle::standardPixmap(standardIcon, option, parent);
Chris@668 179 }
Chris@668 180 }
Chris@668 181
Chris@668 182 QSize ThornStyle::pixmapSize(const QPixmap &pixmap) const
Chris@668 183 {
Chris@668 184 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Chris@668 185 return QSize(int(round(pixmap.width() / pixmap.devicePixelRatio())),
Chris@668 186 int(round(pixmap.height() / pixmap.devicePixelRatio())));
Chris@668 187 #else
Chris@668 188 return pixmap.size();
Chris@668 189 #endif
Chris@668 190 }
Chris@668 191
Chris@668 192 static bool s_thornStyleEnabled = false;
Chris@668 193
Chris@668 194 // This method currently only supports being called once
Chris@668 195 void ThornStyle::setEnabled(bool b)
Chris@668 196 {
Chris@668 197 s_thornStyleEnabled = b;
Chris@668 198 if (b) {
Chris@668 199 qApp->installEventFilter(s_eventFilter());
Chris@668 200 }
Chris@668 201 }
Chris@668 202
Chris@668 203 bool ThornStyle::isEnabled()
Chris@668 204 {
Chris@668 205 return s_thornStyleEnabled;
Chris@668 206 }
Chris@668 207
Chris@668 208 QPalette ThornStyle::standardPalette() const
Chris@668 209 {
Chris@668 210 return m_standardPalette;
Chris@668 211 }
Chris@668 212
Chris@668 213 int ThornStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
Chris@668 214 {
Chris@668 215 switch (hint) {
Chris@668 216 case SH_EtchDisabledText:
Chris@668 217 return 0;
Chris@668 218 case SH_Table_GridLineColor:
Chris@668 219 // QTableView { gridline-color: #202020; }
Chris@668 220 return qRgb(0x20, 0x20, 0x20);
Chris@668 221 case SH_GroupBox_TextLabelColor:
Chris@668 222 // QGroupBox::title { color: #FFFFFF; }
Chris@668 223 // QGroupBox::title:!enabled { color: #000000; }
Chris@668 224 // but it was etched; plain black is unreadable, so let's use another color now
Chris@668 225 return option->state & State_Enabled ? qRgb(0xFF, 0xFF, 0xFF) : qRgb(0xAA, 0xAA, 0xAA);
Chris@668 226 case SH_DialogButtonBox_ButtonsHaveIcons:
Chris@668 227 return 0;
Chris@668 228 case SH_DockWidget_ButtonsHaveFrame:
Chris@668 229 return 1;
Chris@668 230 default:
Chris@668 231 break;
Chris@668 232 }
Chris@668 233 return QProxyStyle::styleHint(hint, option, widget, returnData);
Chris@668 234 }
Chris@668 235
Chris@668 236 int ThornStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
Chris@668 237 {
Chris@668 238 switch (metric) {
Chris@668 239 case PM_SplitterWidth: //fall-through
Chris@668 240 case PM_DockWidgetSeparatorExtent:
Chris@668 241 // QMainWindow::separator { height: 5px; }
Chris@668 242 return 5;
Chris@668 243 case PM_TabBarScrollButtonWidth:
Chris@668 244 // QTabBar::scroller { /* the width of the scroll buttons */ width: 13px; }
Chris@668 245 return 13;
Chris@668 246 case PM_TabBarBaseOverlap:
Chris@668 247 return 0;
Chris@668 248 case PM_ToolBarHandleExtent: // Horizontal toolbar: width of the handle. Vertical toolbar: height of the handle
Chris@668 249 if (option->state & State_Horizontal)
Chris@668 250 return m_horizontalToolbarSeparatorPixmap.width();
Chris@668 251 else
Chris@668 252 return m_verticalToolbarSeparatorPixmap.height();
Chris@668 253 case PM_ExclusiveIndicatorWidth:
Chris@668 254 return m_radiobuttonUncheckedPixmap.width();
Chris@668 255 case PM_ExclusiveIndicatorHeight:
Chris@668 256 return m_radiobuttonUncheckedPixmap.height();
Chris@668 257 case PM_IndicatorWidth:
Chris@668 258 return m_checkboxUncheckedPixmap.width();
Chris@668 259 case PM_IndicatorHeight:
Chris@668 260 return m_checkboxUncheckedPixmap.height();
Chris@668 261 case PM_MenuPanelWidth:
Chris@668 262 return 1;
Chris@668 263 case PM_MenuBarHMargin:
Chris@668 264 // QMenuBar { padding: 4px; }
Chris@668 265 return 4;
Chris@668 266 case PM_MenuBarItemSpacing:
Chris@668 267 // QMenuBar::item { spacing: 3px; padding: 1px 4px; }
Chris@668 268 return 4;
Chris@668 269 case PM_ScrollBarExtent: {
Chris@668 270 QWidget *parent = widget ? widget->parentWidget() : nullptr;
Chris@668 271 QWidget *combo = parent ? parent->parentWidget() : nullptr;
Chris@668 272 if (qobject_cast<QComboBox *>(combo)) {
Chris@668 273 // QComboBox QAbstractItemView QScrollBar:vertical { width: 12px; }
Chris@668 274 return 12;
Chris@668 275 }
Chris@668 276 // QScrollBar:horizontal { height: 16px; }
Chris@668 277 // QScrollBar:vertical { width: 16px; }
Chris@668 278 return 16;
Chris@668 279 }
Chris@668 280 case PM_ToolBarItemSpacing:
Chris@668 281 return 0;
Chris@668 282 case PM_ToolBarItemMargin:
Chris@668 283 case PM_ToolBarFrameWidth:
Chris@668 284 return 0;
Chris@668 285 case PM_DefaultFrameWidth:
Chris@668 286 return 2;
Chris@668 287 case PM_SpinBoxFrameWidth:
Chris@668 288 return 2;
Chris@668 289 case PM_DockWidgetTitleBarButtonMargin:
Chris@668 290 // icon size is 16x16 but somehow the buttons ended up 13x13
Chris@668 291 return -1;
Chris@668 292 case PM_DockWidgetTitleMargin: // space above and below the title
Chris@668 293 return 0;
Chris@668 294 case PM_DockWidgetFrameWidth:
Chris@668 295 // QDockWidget { border: none; }
Chris@668 296 return 0;
Chris@668 297 case PM_SmallIconSize:
Chris@668 298 return 16;
Chris@668 299 default:
Chris@668 300 return QProxyStyle::pixelMetric(metric, option, widget);
Chris@668 301 }
Chris@668 302 }
Chris@668 303
Chris@668 304 void ThornStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
Chris@668 305 {
Chris@668 306 switch (element) {
Chris@668 307 case PE_IndicatorDockWidgetResizeHandle:
Chris@668 308 // QMainWindow::separator:hover { background-color: #CCDFFF; }
Chris@668 309 if (option->state & QStyle::State_MouseOver) {
Chris@668 310 painter->fillRect(option->rect, QColor(0xCC, 0xDF, 0xFF));
Chris@668 311 return;
Chris@668 312 }
Chris@668 313 break;
Chris@668 314 case PE_FrameTabWidget: // The tab widget frame
Chris@668 315 // QTabWidget::pane { border: 2px solid #BBBBBB; border-radius: 4px; padding: 2px; // and background: #404040;
Chris@668 316 painter->save();
Chris@668 317 painter->setPen(QPen(QColor(0xBB, 0xBB, 0xBB), 2));
Chris@668 318 painter->setBrush(QColor(0x40, 0x40, 0x40));
Chris@668 319 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 320 painter->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), 4, 4);
Chris@668 321 painter->restore();
Chris@668 322 return;
Chris@668 323 case PE_FrameGroupBox: // same as above but not the background, already done
Chris@668 324 // QGroupBox { background: #404040; color: #FFFFFF; border: 2px solid #BBBBBB; border-radius: 4px; }
Chris@668 325 painter->save();
Chris@668 326 painter->setPen(QPen(QColor(0xBB, 0xBB, 0xBB), 2));
Chris@668 327 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 328 painter->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), 4, 4);
Chris@668 329 painter->restore();
Chris@668 330 return;
Chris@668 331 case PE_IndicatorToolBarHandle: {
Chris@668 332 // top or bottom: image: url(:/icons/style/htoolbar-separator.png);
Chris@668 333 // left or right: image: url(:icons/style/vtoolbar-separator.png);
Chris@668 334 QPixmap pixmap = option->state & State_Horizontal ? m_horizontalToolbarSeparatorPixmap : m_verticalToolbarSeparatorPixmap;
Chris@668 335 const QRect rect = alignedRect(Qt::LayoutDirectionAuto, Qt::AlignCenter, option->rect.size(), option->rect);
Chris@668 336 painter->drawPixmap(rect, pixmap);
Chris@668 337 return;
Chris@668 338 }
Chris@668 339 case PE_PanelMenu:
Chris@668 340 // QMenu { background-color: #EEEEEE; border: 1px solid black; }
Chris@668 341 painter->fillRect(option->rect, QColor(0xEE, 0xEE, 0xEE));
Chris@668 342 return;
Chris@668 343 case PE_FrameMenu:
Chris@668 344 painter->setPen(Qt::black);
Chris@668 345 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
Chris@668 346 return;
Chris@668 347 case PE_FrameDockWidget: // only called when the dockwidget is floating
Chris@668 348 // QDockWidget { border: none; }
Chris@668 349 return;
Chris@668 350 case PE_PanelStatusBar: // no frame around the statusbar
Chris@668 351 case PE_FrameStatusBarItem: // no frame around the statusbar items
Chris@668 352 return;
Chris@668 353 case PE_PanelLineEdit:
Chris@668 354 // QLineEdit { border: 1px solid #AAAAAA; background-color: #FFFFFF; }
Chris@668 355 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
Chris@668 356 if (frame->lineWidth > 0) // i.e. not inside QSpinBox
Chris@668 357 painter->setPen(QColor(0xAA, 0xAA, 0xAA));
Chris@668 358 else
Chris@668 359 painter->setPen(Qt::NoPen);
Chris@668 360 painter->setBrush(Qt::white);
Chris@668 361 painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
Chris@668 362 }
Chris@668 363 return;
Chris@668 364 case PE_IndicatorMenuCheckMark:
Chris@668 365 return; // done in CE_MenuItem
Chris@668 366 case PE_IndicatorCheckBox:
Chris@668 367 case PE_IndicatorRadioButton: {
Chris@668 368 const bool checked = !(option->state & State_Off);
Chris@668 369 const bool disabled = !(option->state & State_Enabled);
Chris@668 370 const bool pressed = option->state & State_Sunken;
Chris@668 371 const bool hover = option->state & State_MouseOver;
Chris@668 372 QPixmap pixmap;
Chris@668 373 if (element == PE_IndicatorCheckBox) {
Chris@668 374 if (option->state & State_NoChange) {
Chris@668 375 // missing icon for disabled
Chris@668 376 if (pressed)
Chris@668 377 pixmap = m_checkboxIndeterminatePressedPixmap;
Chris@668 378 else if (hover)
Chris@668 379 pixmap = m_checkboxIndeterminateHoverPixmap;
Chris@668 380 else
Chris@668 381 pixmap = m_checkboxIndeterminatePixmap;
Chris@668 382 } else {
Chris@668 383 if (disabled) {
Chris@668 384 pixmap = checked ? m_checkboxCheckedDisabledPixmap : m_checkboxUncheckedDisabledPixmap;
Chris@668 385 } else {
Chris@668 386 if (pressed)
Chris@668 387 pixmap = checked ? m_checkboxCheckedPressedPixmap : m_checkboxUncheckedPressedPixmap;
Chris@668 388 else if (hover)
Chris@668 389 pixmap = checked ? m_checkboxCheckedHoverPixmap : m_checkboxUncheckedHoverPixmap;
Chris@668 390 else
Chris@668 391 pixmap = checked ? m_checkboxCheckedPixmap : m_checkboxUncheckedPixmap;
Chris@668 392 }
Chris@668 393 }
Chris@668 394 } else {
Chris@668 395 if (disabled) {
Chris@668 396 pixmap = checked ? m_radiobuttonCheckedDisabledPixmap : m_radiobuttonUncheckedDisabledPixmap;
Chris@668 397 } else {
Chris@668 398 if (pressed)
Chris@668 399 pixmap = checked ? m_radiobuttonCheckedPressedPixmap : m_radiobuttonUncheckedPressedPixmap;
Chris@668 400 else if (hover)
Chris@668 401 pixmap = checked ? m_radiobuttonCheckedHoverPixmap : m_radiobuttonUncheckedHoverPixmap;
Chris@668 402 else
Chris@668 403 pixmap = checked ? m_radiobuttonCheckedPixmap : m_radiobuttonUncheckedPixmap;
Chris@668 404 }
Chris@668 405 }
Chris@668 406 QRect pmr(QPoint(0, 0), pixmapSize(pixmap));
Chris@668 407 pmr.moveCenter(option->rect.center());
Chris@668 408 painter->drawPixmap(pmr.topLeft(), pixmap);
Chris@668 409 return;
Chris@668 410 }
Chris@668 411 case PE_IndicatorHeaderArrow:
Chris@668 412 // QHeaderView::down-arrow / QHeaderView::up-arrow
Chris@668 413 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
Chris@668 414 const bool up = (header->sortIndicator & QStyleOptionHeader::SortUp);
Chris@668 415 const QPixmap pixmap = up ? m_arrowUpSmallInvertedPixmap : m_arrowDownSmallInvertedPixmap;
Chris@668 416 painter->drawPixmap(option->rect.topLeft(), pixmap);
Chris@668 417 }
Chris@668 418 return;
Chris@668 419 case PE_IndicatorArrowUp:
Chris@668 420 case PE_IndicatorArrowDown:
Chris@668 421 case PE_IndicatorArrowLeft:
Chris@668 422 case PE_IndicatorArrowRight: {
Chris@668 423 QPixmap pixmap;
Chris@668 424 if (element == PE_IndicatorArrowLeft)
Chris@668 425 pixmap = m_arrowLeftPixmap;
Chris@668 426 else if (element == PE_IndicatorArrowRight)
Chris@668 427 pixmap = m_arrowRightPixmap;
Chris@668 428 else if (element == PE_IndicatorArrowUp)
Chris@668 429 pixmap = m_arrowUpPixmap;
Chris@668 430 else if (element == PE_IndicatorArrowDown)
Chris@668 431 pixmap = m_arrowDownPixmap;
Chris@668 432 // Scale the pixmap to the desired rect (for scrollbars the pixmap is 12x12 but the rect is 8x8)
Chris@668 433 pixmap = pixmap.scaled(option->rect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
Chris@668 434 // In case the scaling didn't occupy the full height (due to aspect ratio), center the resulting pixmap (eg: toolbutton menu indicator)
Chris@668 435 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), option->rect);
Chris@668 436 painter->drawPixmap(drawRect.topLeft(), pixmap);
Chris@668 437 }
Chris@668 438 return;
Chris@668 439 case PE_PanelButtonTool:
Chris@668 440 if (widget && widget->inherits("QDockWidgetTitleButton")) {
Chris@668 441 // QDockWidget::close-button, QDockWidget::float-button {
Chris@668 442 // border: 1px solid #AAAAAA;
Chris@668 443 // border-radius: 3px;
Chris@668 444 // background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD);
Chris@668 445 //}
Chris@668 446 painter->save();
Chris@668 447 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 448 QLinearGradient gradient;
Chris@668 449 gradient.setStart(0, 0);
Chris@668 450 gradient.setFinalStop(0, option->rect.height());
Chris@668 451 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 452 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 453 painter->setBrush(gradient);
Chris@668 454 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 455 painter->drawRoundedRect(option->rect.adjusted(1, 1, -1, -1), 3, 3);
Chris@668 456 painter->restore();
Chris@668 457 }
Chris@668 458 else if ((option->state & State_On) || (option->state & State_Sunken)) {
Chris@668 459 // QToolButton::pressed, QToolButton::checked { border: 1px solid #AAAAAA; border-radius: 2px;
Chris@668 460 // background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE); }
Chris@668 461 painter->save();
Chris@668 462 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 463 QLinearGradient gradient;
Chris@668 464 gradient.setStart(0, 0);
Chris@668 465 gradient.setFinalStop(0, option->rect.height());
Chris@668 466 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE));
Chris@668 467 gradient.setColorAt(1, QColor(0xE0, 0xE0, 0xE0));
Chris@668 468 painter->setBrush(gradient);
Chris@668 469 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 470 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 2, 2);
Chris@668 471 painter->restore();
Chris@668 472 }
Chris@668 473 else if ((option->state & State_MouseOver) && (option->state & State_Enabled)) {
Chris@668 474 // QToolButton::enabled:hover { border: 1px solid #AAAAAA; border-radius: 2px; background-color: #CCDFFF; }
Chris@668 475 painter->save();
Chris@668 476 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 477 painter->setBrush(QColor(0xCC, 0xDF, 0xFF));
Chris@668 478 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 479 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 2, 2);
Chris@668 480 painter->restore();
Chris@668 481 }
Chris@668 482 return;
Chris@668 483 case PE_IndicatorProgressChunk:
Chris@668 484 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
Chris@668 485 QStyleOptionProgressBar copy = *pb;
Chris@668 486 // QProgressBar::chunk { background-color: #D6E8FB; }
Chris@668 487 copy.palette.setColor(QPalette::Highlight, QColor(0xD6, 0xE8, 0xFB)); // qwindowsstyle.cpp uses Highlight
Chris@668 488 QProxyStyle::drawPrimitive(element, &copy, painter, widget);
Chris@668 489 }
Chris@668 490 return;
Chris@668 491 default:
Chris@668 492 break;
Chris@668 493 }
Chris@668 494 QProxyStyle::drawPrimitive(element, option, painter, widget);
Chris@668 495 }
Chris@668 496
Chris@668 497 void ThornStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
Chris@668 498 {
Chris@668 499 switch (element) {
Chris@668 500 case CE_Splitter: // currently unused, but consistent with PE_IndicatorDockWidgetResizeHandle
Chris@668 501 if (option->state & QStyle::State_MouseOver) {
Chris@668 502 painter->fillRect(option->rect, QColor(0xCC, 0xDF, 0xFF));
Chris@668 503 return;
Chris@668 504 }
Chris@668 505 break;
Chris@668 506 case CE_TabBarTab:
Chris@668 507 /* border: 1px solid #AAAAAA;
Chris@668 508 background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD);
Chris@668 509 color: #000000;
Chris@668 510 border-bottom-color: #BBBBBB; // same as the pane color
Chris@668 511 border-top-left-radius: 4px;
Chris@668 512 border-top-right-radius: 4px;
Chris@668 513 */
Chris@668 514 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
Chris@668 515 QRect tabRect = tab->rect;
Chris@668 516 QColor borderColor;
Chris@668 517 QLinearGradient gradient(0, 0, 0, tab->rect.height());
Chris@668 518 const bool selected = tab->state & State_Selected;
Chris@668 519 if (selected) {
Chris@668 520 // QTabBar::tab:top:selected said
Chris@668 521 // background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE);
Chris@668 522 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xE0));
Chris@668 523 gradient.setColorAt(1, QColor(0xEE, 0xEE, 0xEE));
Chris@668 524 // border: 1px solid #E0E0E0;
Chris@668 525 borderColor = QColor(0xE0, 0xE0, 0xE0);
Chris@668 526 } else {
Chris@668 527 gradient.setColorAt(0, QColor(0x99, 0x99, 0x99));
Chris@668 528 gradient.setColorAt(1, QColor(0xDD, 0xDD, 0xDD));
Chris@668 529 borderColor = QColor(0xAA, 0xAA, 0xAA);
Chris@668 530 }
Chris@668 531
Chris@668 532 QRect roundedRect;
Chris@668 533 // Ruse: we draw a rounded rect that is too big at the bottom (or top, for South), but clipped, so that it looks square
Chris@668 534 switch (tab->shape) {
Chris@668 535 case QTabBar::RoundedNorth:
Chris@668 536 case QTabBar::TriangularNorth:
Chris@668 537 if (!selected) {
Chris@668 538 // QTabBar::tab:top:!selected { margin-top: 2px; }
Chris@668 539 tabRect.adjust(0, 2, 0, 0);
Chris@668 540 }
Chris@668 541 roundedRect = tabRect.adjusted(0, 0, 0, 5);
Chris@668 542 break;
Chris@668 543 case QTabBar::RoundedSouth:
Chris@668 544 case QTabBar::TriangularSouth:
Chris@668 545 if (!selected) {
Chris@668 546 // QTabBar::tab:bottom:!selected { margin-bottom: 2px }
Chris@668 547 tabRect.adjust(0, 0, 0, -2);
Chris@668 548 }
Chris@668 549 roundedRect = tabRect.adjusted(0, -5, 0, 0);
Chris@668 550 break;
Chris@668 551 default:
Chris@668 552 qWarning() << "Vertical tabbars not implemented yet, call David";
Chris@668 553 }
Chris@668 554
Chris@668 555 // Draw tab shape
Chris@668 556 painter->save();
Chris@668 557 painter->setClipRect(tabRect);
Chris@668 558 painter->setPen(borderColor);
Chris@668 559 painter->setBrush(gradient);
Chris@668 560 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 561 painter->drawRoundedRect(roundedRect, 4, 4);
Chris@668 562 painter->restore();
Chris@668 563
Chris@668 564 // Draw tab text
Chris@668 565 QStyleOptionTab modifiedOption = *tab;
Chris@668 566 modifiedOption.palette.setColor(QPalette::WindowText, Qt::black);
Chris@668 567 QProxyStyle::drawControl(CE_TabBarTabLabel, &modifiedOption, painter, widget);
Chris@668 568 }
Chris@668 569 return;
Chris@668 570 case CE_ToolBar:
Chris@668 571 {
Chris@668 572 /*
Chris@668 573 top or bottom: background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD)
Chris@668 574 left or right: background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #DDDDDD, stop:1 #999999)
Chris@668 575 */
Chris@668 576 QLinearGradient gradient;
Chris@668 577 if (option->state & State_Horizontal) {
Chris@668 578 gradient.setStart(0, 0);
Chris@668 579 gradient.setFinalStop(0, option->rect.height());
Chris@668 580 } else {
Chris@668 581 gradient.setStart(0, 0);
Chris@668 582 gradient.setFinalStop(option->rect.width(), 0);
Chris@668 583 }
Chris@668 584 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 585 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 586 painter->fillRect(option->rect, gradient);
Chris@668 587 }
Chris@668 588 return;
Chris@668 589 case CE_PushButtonBevel:
Chris@668 590 painter->save();
Chris@668 591 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 592 if (option->state & State_MouseOver) {
Chris@668 593 // QPushButton:hover { border: 1px solid #AAAAAA; border-radius: 3px; background-color: #DDEFFF; }
Chris@668 594 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 595 painter->setBrush(QColor(0xDD, 0xEF, 0xFF));
Chris@668 596 } else if ((option->state & State_On) || (option->state & State_Sunken)) {
Chris@668 597 // QPushButton::checked, QPushButton::pressed { border: 1px solid #AAAAAA; border-radius: 2px; background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0EA, stop:1 #BBCFFF); }
Chris@668 598 QLinearGradient gradient;
Chris@668 599 gradient.setStart(0, 0);
Chris@668 600 gradient.setFinalStop(0, option->rect.height());
Chris@668 601 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xEA));
Chris@668 602 gradient.setColorAt(1, QColor(0xBB, 0xCF, 0xFF));
Chris@668 603 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 604 painter->setBrush(gradient);
Chris@668 605 } else {
Chris@668 606 // QPushButton::enabled { border: 1px solid #AAAAAA; border-radius: 3px; background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); }
Chris@668 607 // QPushButton::!enabled { border: 1px solid #808080; + same background as Qt does the sunken effect on these, and that looks fine. }
Chris@668 608 QLinearGradient gradient;
Chris@668 609 gradient.setStart(0, 0);
Chris@668 610 gradient.setFinalStop(0, option->rect.height());
Chris@668 611 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 612 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 613 if (option->state & State_Enabled)
Chris@668 614 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 615 else
Chris@668 616 painter->setPen(QPen(QColor(0x80, 0x80, 0x80)));
Chris@668 617 painter->setBrush(gradient);
Chris@668 618 }
Chris@668 619 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 3, 3);
Chris@668 620 painter->restore();
Chris@668 621 return;
Chris@668 622 case CE_MenuItem:
Chris@668 623 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
Chris@668 624 int x, y, w, h;
Chris@668 625 menuitem->rect.getRect(&x, &y, &w, &h);
Chris@668 626 const bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable ? menuitem->checked : false;
Chris@668 627 const bool selected = menuitem->state & State_Selected;
Chris@668 628 const bool disabled = !(menuitem->state & State_Enabled);
Chris@668 629
Chris@668 630 QColor textColor;
Chris@668 631 if (selected) {
Chris@668 632 // QMenu::item:selected { background-color: #80AFFF; }
Chris@668 633 const QColor fill(0x80, 0xAF, 0xFF);
Chris@668 634 painter->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill);
Chris@668 635
Chris@668 636 // QMenu::item:selected { color: #FFFFFF; }
Chris@668 637 textColor = QColor(0xFF, 0xFF, 0xFF);
Chris@668 638 } else {
Chris@668 639 if (disabled) {
Chris@668 640 // QMenu::item:!enabled { color: #AAAAAA; }
Chris@668 641 textColor = QColor(0xAA, 0xAA, 0xAA);
Chris@668 642 } else {
Chris@668 643 // QMenu::item:enabled { color: #000000; }
Chris@668 644 textColor = Qt::black;
Chris@668 645 }
Chris@668 646 }
Chris@668 647
Chris@668 648 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
Chris@668 649 /* QMenu::separator {
Chris@668 650 height: 2px;
Chris@668 651 background: #AAAAAA;
Chris@668 652 margin-left: 10px;
Chris@668 653 margin-right: 5px;
Chris@668 654 } */
Chris@668 655 const int yoff = y-1 + h / 2;
Chris@668 656 painter->fillRect(x + 10, yoff, w - 15, 2, QColor(0xAA, 0xAA, 0xAA));
Chris@668 657 return;
Chris@668 658 }
Chris@668 659
Chris@668 660 // taken from qwindowsstyle.cpp, and modified (due to the width of the checkmarks)
Chris@668 661
Chris@668 662 const bool checkable = menuitem->checkType != QStyleOptionMenuItem::NotCheckable;
Chris@668 663 const int checkcol = qMax<int>(menuitem->maxIconWidth, m_checkboxCheckedPixmap.width() + 4);
Chris@668 664 const QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
Chris@668 665
Chris@668 666 // Draw icon or checkmark
Chris@668 667 QPixmap pixmap;
Chris@668 668 if (!menuitem->icon.isNull()) {
Chris@668 669 QIcon::Mode mode = disabled ? QIcon::Disabled : QIcon::Normal;
Chris@668 670 if (selected && !disabled)
Chris@668 671 mode = QIcon::Active;
Chris@668 672 if (checked)
Chris@668 673 pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
Chris@668 674 else
Chris@668 675 pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode);
Chris@668 676 } else if (checkable) {
Chris@668 677 if (!selected) {
Chris@668 678 if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) {
Chris@668 679 pixmap = menuitem->checked ? m_radiobuttonCheckedPixmap : m_radiobuttonUncheckedPixmap;
Chris@668 680 } else {
Chris@668 681 pixmap = menuitem->checked ? m_checkboxCheckedPixmap : m_checkboxUncheckedPixmap;
Chris@668 682 }
Chris@668 683 } else {
Chris@668 684 if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) {
Chris@668 685 pixmap = menuitem->checked ? m_radiobuttonCheckedHoverPixmap : m_radiobuttonUncheckedHoverPixmap;
Chris@668 686 } else {
Chris@668 687 pixmap = menuitem->checked ? m_checkboxCheckedHoverPixmap : m_checkboxUncheckedHoverPixmap;
Chris@668 688 }
Chris@668 689 }
Chris@668 690 }
Chris@668 691 QRect pmr(QPoint(0, 0), pixmapSize(pixmap));
Chris@668 692 pmr.moveCenter(vCheckRect.center());
Chris@668 693 painter->setPen(menuitem->palette.text().color());
Chris@668 694 painter->drawPixmap(pmr.topLeft(), pixmap);
Chris@668 695
Chris@668 696 const int itemFrame = 2;
Chris@668 697 const int itemHMargin = 2;
Chris@668 698 const int itemVMargin = 2;
Chris@668 699 const int rightBorder = 15;
Chris@668 700 const int arrowHMargin = 6;
Chris@668 701 const int xm = itemFrame + checkcol + itemHMargin;
Chris@668 702 const int xpos = menuitem->rect.x() + xm;
Chris@668 703 painter->setPen(textColor);
Chris@668 704 QRect textRect(xpos, y + itemVMargin,
Chris@668 705 w - xm - rightBorder - menuitem->tabWidth + 1, h - 2 * itemVMargin);
Chris@668 706 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
Chris@668 707 QString s(menuitem->text);
Chris@668 708 if (!s.isEmpty()) { // draw text
Chris@668 709 int t = s.indexOf(QLatin1Char('\t'));
Chris@668 710 int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
Chris@668 711 if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
Chris@668 712 text_flags |= Qt::TextHideMnemonic;
Chris@668 713 if (t >= 0) {
Chris@668 714 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
Chris@668 715 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
Chris@668 716 const QString textToDraw = s.mid(t + 1);
Chris@668 717 painter->drawText(vShortcutRect, text_flags, textToDraw);
Chris@668 718 s = s.left(t);
Chris@668 719 }
Chris@668 720 QFont font = menuitem->font;
Chris@668 721 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
Chris@668 722 font.setBold(true);
Chris@668 723 painter->setFont(font);
Chris@668 724 const QString textToDraw = s.left(t);
Chris@668 725 painter->drawText(vTextRect, text_flags, textToDraw);
Chris@668 726 }
Chris@668 727 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow
Chris@668 728 const int dim = (h - 2 * itemFrame) / 2;
Chris@668 729 const PrimitiveElement arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
Chris@668 730 const int submenuXPos = x + w - arrowHMargin - itemFrame - dim;
Chris@668 731 const QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(submenuXPos, y + h / 2 - dim / 2, dim, dim));
Chris@668 732 QStyleOptionMenuItem newMI = *menuitem;
Chris@668 733 newMI.rect = vSubMenuRect;
Chris@668 734 newMI.state = disabled ? State_None : State_Enabled;
Chris@668 735 if (selected) {
Chris@668 736 newMI.palette.setColor(QPalette::ButtonText, textColor);
Chris@668 737 }
Chris@668 738 QProxyStyle::drawPrimitive(arrow, &newMI, painter, widget);
Chris@668 739 }
Chris@668 740 }
Chris@668 741 return;
Chris@668 742 case CE_CheckBoxLabel:
Chris@668 743 case CE_RadioButtonLabel:
Chris@668 744 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
Chris@668 745 QStyleOptionButton modifiedOption = *btn;
Chris@668 746 const bool disabled = !(option->state & State_Enabled);
Chris@668 747 // QCheckBox:!enabled { color: #000000; }
Chris@668 748 // QCheckBox:enabled { color: #FFFFFF }
Chris@668 749 modifiedOption.palette.setColor(QPalette::WindowText, disabled ? Qt::black : Qt::white);
Chris@668 750 QProxyStyle::drawControl(element, &modifiedOption, painter, widget);
Chris@668 751 }
Chris@668 752 return;
Chris@668 753 case CE_ComboBoxLabel:
Chris@668 754 if (option->state & State_Enabled) {
Chris@668 755 painter->setPen(Qt::black);
Chris@668 756 } else {
Chris@668 757 // disabled text light enough to be legible but not as stark as white
Chris@668 758 painter->setPen(QColor(0xEE, 0xEE, 0xEE));
Chris@668 759 }
Chris@668 760 QCommonStyle::drawControl(element, option, painter, widget);
Chris@668 761 return;
Chris@668 762 case CE_Header:
Chris@668 763 // Copied straight from qwindowsstyle.cpp because the subElementRect calls don't use proxy()->.
Chris@668 764 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
Chris@668 765 QRegion clipRegion = painter->clipRegion();
Chris@668 766 painter->setClipRect(option->rect);
Chris@668 767 drawControl(CE_HeaderSection, header, painter, widget);
Chris@668 768 QStyleOptionHeader subopt = *header;
Chris@668 769 subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
Chris@668 770 if (subopt.rect.isValid()) {
Chris@668 771 subopt.palette.setColor(QPalette::ButtonText, Qt::white); // QHeaderView::section { color: #FFFFFF; }
Chris@668 772 drawControl(CE_HeaderLabel, &subopt, painter, widget);
Chris@668 773 }
Chris@668 774 if (header->sortIndicator != QStyleOptionHeader::None) {
Chris@668 775 subopt.rect = subElementRect(SE_HeaderArrow, option, widget);
Chris@668 776 drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
Chris@668 777 }
Chris@668 778 painter->setClipRegion(clipRegion);
Chris@668 779 }
Chris@668 780 return;
Chris@668 781 case CE_HeaderSection:
Chris@668 782 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
Chris@668 783 // QHeaderView::section { background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #707070, stop:1 #808080); }
Chris@668 784 QLinearGradient gradient;
Chris@668 785 gradient.setStart(0, 0);
Chris@668 786 gradient.setFinalStop(0, option->rect.height());
Chris@668 787 gradient.setColorAt(0, QColor(0x80, 0x80, 0x80));
Chris@668 788 gradient.setColorAt(1, QColor(0x70, 0x70, 0x70));
Chris@668 789 painter->setBrush(gradient);
Chris@668 790 // border: 1px solid #AAAAAA;
Chris@668 791 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA)));
Chris@668 792 painter->drawRect(header->rect);
Chris@668 793 // Not converted, not sure what it did: padding-left: 4px; padding-right: 1em;
Chris@668 794 }
Chris@668 795 return;
Chris@668 796 case CE_MenuBarItem:
Chris@668 797 if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
Chris@668 798 QStyleOptionMenuItem modifiedOption(*m);
Chris@668 799 if (option->state & State_Selected) {
Chris@668 800 // QMenuBar::item:selected { background-color: #80AFFF; }
Chris@668 801 modifiedOption.palette.setColor(QPalette::Button, QColor(0x80, 0xAF, 0xFF));
Chris@668 802 } else if (option->state & State_Sunken) {
Chris@668 803 // QMenuBar::item:pressed { background-color: #BBCEFF; }
Chris@668 804 modifiedOption.palette.setColor(QPalette::Button, QColor(0xBB, 0xCE, 0xFF));
Chris@668 805 } else {
Chris@668 806 // QMenuBar { background-color: #404040; }
Chris@668 807 modifiedOption.palette.setColor(QPalette::Button, QColor(0x40, 0x40, 0x40));
Chris@668 808 }
Chris@668 809 // QMenuBar::item:selected { color: #FFFFFF; }
Chris@668 810 // QMenuBar::item { color: #FFFFFF; }
Chris@668 811 modifiedOption.palette.setColor(QPalette::ButtonText, Qt::white);
Chris@668 812
Chris@668 813 QProxyStyle::drawControl(element, &modifiedOption, painter, widget);
Chris@668 814 }
Chris@668 815 return;
Chris@668 816 case CE_MenuBarEmptyArea:
Chris@668 817 // QMenuBar { background-color: #404040; }
Chris@668 818 painter->fillRect(option->rect, QColor(0x40, 0x40, 0x40));
Chris@668 819 return;
Chris@668 820 case CE_ScrollBarSubLine:
Chris@668 821 case CE_ScrollBarAddLine:
Chris@668 822 {
Chris@668 823 // QScrollBar::add-line:horizontal { border: 2px solid #404040; background: #808080; } but the 2px border didn't appear
Chris@668 824 painter->fillRect(option->rect, QColor(0x80, 0x80, 0x80));
Chris@668 825 // taken from qwindowsstyle.cpp
Chris@668 826 PrimitiveElement arrow;
Chris@668 827 if (option->state & State_Horizontal) {
Chris@668 828 if (element == CE_ScrollBarAddLine)
Chris@668 829 arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft;
Chris@668 830 else
Chris@668 831 arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight;
Chris@668 832 } else {
Chris@668 833 if (element == CE_ScrollBarAddLine)
Chris@668 834 arrow = PE_IndicatorArrowDown;
Chris@668 835 else
Chris@668 836 arrow = PE_IndicatorArrowUp;
Chris@668 837 }
Chris@668 838 QStyleOption arrowOpt = *option;
Chris@668 839 // QScrollBar:*-arrow { width: 8px; height 8px; }
Chris@668 840 arrowOpt.rect = alignedRect(option->direction, Qt::AlignCenter, QSize(8, 8), option->rect);
Chris@668 841 drawPrimitive(arrow, &arrowOpt, painter, widget);
Chris@668 842 }
Chris@668 843 return;
Chris@668 844 case CE_ScrollBarSubPage:
Chris@668 845 case CE_ScrollBarAddPage:
Chris@668 846 // Nothing to be done, CC_ScrollBar did the full fillRect()
Chris@668 847 return;
Chris@668 848 case CE_ScrollBarSlider:
Chris@668 849 {
Chris@668 850 // QScrollBar::handle:horizontal { background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); }
Chris@668 851 // QScrollBar::handle:vertical { background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #DDDDDD, stop:1 #999999); }
Chris@668 852 QLinearGradient gradient;
Chris@668 853 gradient.setStart(0, 0);
Chris@668 854 if (option->state & State_Horizontal)
Chris@668 855 gradient.setFinalStop(0, option->rect.height());
Chris@668 856 else
Chris@668 857 gradient.setFinalStop(option->rect.width(), 0);
Chris@668 858 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 859 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 860 painter->fillRect(option->rect, gradient);
Chris@668 861 }
Chris@668 862 return;
Chris@668 863 case CE_DockWidgetTitle: // titlebar on floating dock widgets
Chris@668 864 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) {
Chris@668 865 const bool active = dwOpt->state & State_Active;
Chris@668 866 const bool floating = dwOpt->movable && (dwOpt->state & State_Window);
Chris@668 867 QStyleOptionDockWidget copy = *dwOpt;
Chris@668 868 copy.palette.setColor(QPalette::Dark, Qt::transparent); // QCommonStyle draws a border around the title with this color, we don't want it
Chris@668 869 if (floating && !active)
Chris@668 870 copy.palette.setColor(QPalette::WindowText, QColor(0xAA, 0xAA, 0xAA));
Chris@668 871 else
Chris@668 872 copy.palette.setColor(QPalette::WindowText, Qt::white);
Chris@668 873 // Don't use QWindowsStyle for this, it uses black for the floating && !active case, cached from the initial app palette.
Chris@668 874 QCommonStyle::drawControl(element, &copy, painter, widget);
Chris@668 875 }
Chris@668 876 return;
Chris@668 877 case CE_ProgressBarGroove:
Chris@668 878 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
Chris@668 879 // QProgressBar { background: #FFFFFF; border: 1px solid #AAAAAA; border-radius: 3px; }
Chris@668 880 painter->save();
Chris@668 881 painter->setBrush(Qt::white);
Chris@668 882 painter->setPen(QColor(0xAA, 0xAA, 0xAA));
Chris@668 883 painter->drawRoundedRect(pb->rect.adjusted(0, 0, -1, -1), 3, 3);
Chris@668 884 painter->restore();
Chris@668 885 }
Chris@668 886 return;
Chris@668 887 case CE_ProgressBarLabel:
Chris@668 888 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
Chris@668 889 // QProgressBar { color: #000000; text-align: center; }
Chris@668 890 QStyleOptionProgressBar copy = *pb;
Chris@668 891 copy.palette.setColor(QPalette::HighlightedText, Qt::black);
Chris@668 892 QProxyStyle::drawControl(element, &copy, painter, widget);
Chris@668 893 }
Chris@668 894 return;
Chris@668 895 default:
Chris@668 896 break;
Chris@668 897 }
Chris@668 898 QProxyStyle::drawControl(element, option, painter, widget);
Chris@668 899 }
Chris@668 900
Chris@668 901 void ThornStyle::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
Chris@668 902 {
Chris@668 903 switch (control) {
Chris@668 904 case CC_ScrollBar:
Chris@668 905 if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
Chris@668 906 // QScrollBar { border: 2px solid #404040; background-color: none; }
Chris@668 907 // QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: #404040; }
Chris@668 908 // Done here by filling the whole scrollbar, and moving the subcontrols by 2 pixels, then drawing nothing for AddPage/SubPage
Chris@668 909 painter->fillRect(scrollBar->rect, QColor(0x40, 0x40, 0x40));
Chris@668 910 }
Chris@668 911 break; // let the base class do the rest
Chris@668 912 case CC_Slider:
Chris@668 913 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
Chris@668 914 const QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
Chris@668 915 const QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
Chris@668 916 if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
Chris@668 917 // QSlider::groove:horizontal { background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #E0E0E0, stop:1 #EEEEEE); }
Chris@668 918 QLinearGradient gradient;
Chris@668 919 gradient.setStart(0, 0);
Chris@668 920 if (option->state & State_Horizontal)
Chris@668 921 gradient.setFinalStop(0, option->rect.height());
Chris@668 922 else
Chris@668 923 gradient.setFinalStop(option->rect.width(), 0);
Chris@668 924 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xE0));
Chris@668 925 gradient.setColorAt(1, QColor(0xEE, 0xEE, 0xEE));
Chris@668 926 painter->fillRect(groove, gradient);
Chris@668 927 }
Chris@668 928 #if 0 // no tickmarks
Chris@668 929 if (slider->subControls & SC_SliderTickmarks) {
Chris@668 930 QStyleOptionSlider tmpSlider = *slider;
Chris@668 931 tmpSlider.subControls = SC_SliderTickmarks;
Chris@668 932 QCommonStyle::drawComplexControl(control, &tmpSlider, painter, widget);
Chris@668 933 }
Chris@668 934 #endif
Chris@668 935 if (slider->subControls & SC_SliderHandle) {
Chris@668 936 // QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);
Chris@668 937 // border: 1px solid #5c5c5c; border-radius: 3px; }
Chris@668 938 QLinearGradient gradient;
Chris@668 939 gradient.setStart(0, 0);
Chris@668 940 gradient.setFinalStop(option->rect.width(), option->rect.height());
Chris@668 941 gradient.setColorAt(0, QColor(0xB4, 0xB4, 0xB4));
Chris@668 942 gradient.setColorAt(1, QColor(0x8F, 0x8F, 0x8F));
Chris@668 943 painter->setPen(QColor(0x5C, 0x5C, 0x5C));
Chris@668 944 painter->setBrush(gradient);
Chris@668 945 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 946 painter->drawRoundedRect(handle, 3, 3);
Chris@668 947 }
Chris@668 948 }
Chris@668 949 return;
Chris@668 950 case CC_GroupBox:
Chris@668 951 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
Chris@668 952 QStyleOptionGroupBox copy = *groupBox;
Chris@668 953 // QGroupBox::title { subcontrol-position: top center; }
Chris@668 954 copy.textAlignment = Qt::AlignHCenter;
Chris@668 955
Chris@668 956 // Draw frame
Chris@668 957 QRect textRect = subControlRect(CC_GroupBox, &copy, SC_GroupBoxLabel, widget);
Chris@668 958 QRect checkBoxRect = subControlRect(CC_GroupBox, &copy, SC_GroupBoxCheckBox, widget);
Chris@668 959 if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
Chris@668 960 QStyleOptionFrame frame;
Chris@668 961 frame.QStyleOption::operator=(*groupBox);
Chris@668 962 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Chris@668 963 frame.features = groupBox->features;
Chris@668 964 #endif
Chris@668 965 frame.lineWidth = groupBox->lineWidth;
Chris@668 966 frame.midLineWidth = groupBox->midLineWidth;
Chris@668 967 frame.rect = subControlRect(CC_GroupBox, &copy, SC_GroupBoxFrame, widget);
Chris@668 968 painter->save();
Chris@668 969
Chris@668 970 QRegion region(groupBox->rect);
Chris@668 971 if (!groupBox->text.isEmpty()) {
Chris@668 972 bool ltr = groupBox->direction == Qt::LeftToRight;
Chris@668 973 QRect finalRect;
Chris@668 974 if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
Chris@668 975 finalRect = checkBoxRect.united(textRect);
Chris@668 976 finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
Chris@668 977 } else {
Chris@668 978 finalRect = textRect;
Chris@668 979 }
Chris@668 980 region -= finalRect;
Chris@668 981 }
Chris@668 982
Chris@668 983 // Draw background without clipping
Chris@668 984 painter->setPen(Qt::NoPen);
Chris@668 985 painter->setBrush(QColor(0x40, 0x40, 0x40));
Chris@668 986 painter->drawRoundedRect(frame.rect.adjusted(2, 2, -2, -2), 4, 4);
Chris@668 987
Chris@668 988 painter->setClipRegion(region);
Chris@668 989 // Draw frame with clipping
Chris@668 990 drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
Chris@668 991 painter->restore();
Chris@668 992 }
Chris@668 993
Chris@668 994 copy.subControls &= ~SC_GroupBoxFrame;
Chris@668 995 QProxyStyle::drawComplexControl(control, &copy, painter, widget);
Chris@668 996 }
Chris@668 997 return;
Chris@668 998 case CC_ToolButton:
Chris@668 999 if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
Chris@668 1000 QRect button = subControlRect(control, toolbutton, SC_ToolButton, widget);
Chris@668 1001 QRect menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
Chris@668 1002 State bflags = toolbutton->state & ~State_Sunken;
Chris@668 1003
Chris@668 1004 /*if (bflags & State_AutoRaise) {
Chris@668 1005 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) {
Chris@668 1006 bflags &= ~State_Raised;
Chris@668 1007 }
Chris@668 1008 }*/
Chris@668 1009 State mflags = bflags;
Chris@668 1010 if (toolbutton->state & State_Sunken) {
Chris@668 1011 if (toolbutton->activeSubControls & SC_ToolButton)
Chris@668 1012 bflags |= State_Sunken;
Chris@668 1013 else // added this "else" so that the down arrow only shifts by +1,+1 when actually clicking on it, not when clicking on the main toolbutton
Chris@668 1014 mflags |= State_Sunken;
Chris@668 1015 }
Chris@668 1016
Chris@668 1017 QStyleOption tool = *toolbutton;
Chris@668 1018 if (toolbutton->subControls & SC_ToolButton) {
Chris@668 1019 tool.rect = button;
Chris@668 1020 tool.state = bflags;
Chris@668 1021 drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
Chris@668 1022 }
Chris@668 1023 QStyleOptionToolButton label = *toolbutton;
Chris@668 1024 label.state = bflags;
Chris@668 1025 int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
Chris@668 1026 label.rect = button.adjusted(fw, fw, -fw, -fw);
Chris@668 1027 // QToolButton { color: #FFFFFF; }
Chris@668 1028 label.palette.setColor(QPalette::ButtonText, Qt::white);
Chris@668 1029 drawControl(CE_ToolButtonLabel, &label, painter, widget);
Chris@668 1030
Chris@668 1031 if (mflags & State_Sunken) {
Chris@668 1032 // QToolButton::menu-arrow:open { top: 1px; left: 1px; /* shift it a bit */ }
Chris@668 1033 painter->translate(1, 1);
Chris@668 1034 }
Chris@668 1035 if (toolbutton->subControls & SC_ToolButtonMenu) { // popupMode == QToolButton::MenuButtonPopup
Chris@668 1036 tool.rect = menuarea;
Chris@668 1037 tool.state = mflags;
Chris@668 1038 drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
Chris@668 1039 } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { // InstantPopup, like QPushButton menu
Chris@668 1040 // "the arrow on tool buttons with menus in InstantPopup mode is intentionally styled out of existence"
Chris@668 1041 }
Chris@668 1042 }
Chris@668 1043 return;
Chris@668 1044 case CC_ComboBox:
Chris@668 1045 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
Chris@668 1046 if ((cmb->subControls & SC_ComboBoxFrame)) {
Chris@668 1047 // QComboBox { border: 1px solid #AAAAAA; border-radius: 3px; }
Chris@668 1048 // QComboBox::!enabled { border: 1px solid #808080; border-radius: 3px; }
Chris@668 1049 if (option->state & State_Enabled)
Chris@668 1050 painter->setPen(QColor(0xAA, 0xAA, 0xAA));
Chris@668 1051 else
Chris@668 1052 painter->setPen(QColor(0x80, 0x80, 0x80));
Chris@668 1053
Chris@668 1054 if (option->state & State_MouseOver) {
Chris@668 1055 // QComboBox:hover { background-color: #CCDFFF; }
Chris@668 1056 painter->setBrush(QColor(0xCC, 0xDF, 0xFF));
Chris@668 1057 } else if (cmb->editable) {
Chris@668 1058 // QComboBox::editable { background-color: #FFFFFF; }
Chris@668 1059 painter->setBrush(Qt::white);
Chris@668 1060 } else {
Chris@668 1061 // QComboBox::!editable { background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); }
Chris@668 1062 // QComboBox::!editable::on { background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE); }
Chris@668 1063 QLinearGradient gradient;
Chris@668 1064 gradient.setStart(0, 0);
Chris@668 1065 gradient.setFinalStop(0, option->rect.height());
Chris@668 1066 if (option->state & State_On) {
Chris@668 1067 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE));
Chris@668 1068 gradient.setColorAt(1, QColor(0xE0, 0xE0, 0xE0));
Chris@668 1069 } else {
Chris@668 1070 if (qobject_cast<QToolBar*>(widget->parentWidget())) {
Chris@668 1071 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE));
Chris@668 1072 gradient.setColorAt(1, QColor(0xDD, 0xDD, 0xDD));
Chris@668 1073 } else {
Chris@668 1074 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 1075 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 1076 }
Chris@668 1077 }
Chris@668 1078 painter->setBrush(gradient);
Chris@668 1079 }
Chris@668 1080 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 1081 painter->drawRoundedRect(option->rect, 3, 3);
Chris@668 1082 }
Chris@668 1083 if (cmb->subControls & SC_ComboBoxArrow) {
Chris@668 1084 // from qwindowsstyle.cpp, without the rect around the arrow
Chris@668 1085 State flags = State_None;
Chris@668 1086 QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
Chris@668 1087 bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow
Chris@668 1088 && cmb->state & State_Sunken;
Chris@668 1089 ar.adjust(2, 2, -2, -2);
Chris@668 1090 if (option->state & State_Enabled)
Chris@668 1091 flags |= State_Enabled;
Chris@668 1092 if (option->state & State_HasFocus)
Chris@668 1093 flags |= State_HasFocus;
Chris@668 1094
Chris@668 1095 if (sunkenArrow)
Chris@668 1096 flags |= State_Sunken;
Chris@668 1097 QStyleOption arrowOpt = *cmb;
Chris@668 1098 arrowOpt.rect = ar.adjusted(1, 1, -1, -1);
Chris@668 1099 arrowOpt.state = flags;
Chris@668 1100 drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
Chris@668 1101 }
Chris@668 1102 #if 0
Chris@668 1103 if (cmb->subControls & SC_ComboBoxEditField) {
Chris@668 1104 QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
Chris@668 1105 if (cmb->state & State_HasFocus && !cmb->editable)
Chris@668 1106 p->fillRect(re.x(), re.y(), re.width(), re.height(),
Chris@668 1107 cmb->palette.brush(QPalette::Highlight));
Chris@668 1108 }
Chris@668 1109 #endif
Chris@668 1110 }
Chris@668 1111 return;
Chris@668 1112 case CC_SpinBox:
Chris@668 1113 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
Chris@668 1114 bool enabled = option->state & State_Enabled;
Chris@668 1115 painter->setRenderHint(QPainter::Antialiasing);
Chris@668 1116 QPainterPath framePath;
Chris@668 1117 // Draw background color (white), clipped to the rounded rect frame,
Chris@668 1118 // without drawing that frame yet (we'll do that last).
Chris@668 1119 // That same clipping will be useful for the round corner of the up/down buttons
Chris@668 1120 QRect frameRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget).adjusted(2, 2, -2, -2);
Chris@668 1121 framePath.addRoundedRect(frameRect, 4, 4);
Chris@668 1122 painter->setClipPath(framePath);
Chris@668 1123 painter->fillRect(frameRect, sb->palette.brush(QPalette::Base));
Chris@668 1124 const QRect spinupRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
Chris@668 1125 QLinearGradient gradient;
Chris@668 1126 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD));
Chris@668 1127 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99));
Chris@668 1128 painter->setPen(QColor(0xAA, 0xAA, 0xAA));
Chris@668 1129 if (sb->subControls & SC_SpinBoxUp) {
Chris@668 1130 gradient.setStart(spinupRect.topLeft());
Chris@668 1131 gradient.setFinalStop(spinupRect.bottomLeft());
Chris@668 1132 if (sb->activeSubControls == SC_SpinBoxUp && !(option->state & State_Sunken))
Chris@668 1133 painter->setBrush(QColor(0xDD, 0xEF, 0xFF));
Chris@668 1134 else
Chris@668 1135 painter->setBrush(gradient);
Chris@668 1136 painter->drawRect(spinupRect);
Chris@668 1137
Chris@668 1138 QPixmap pixmap = enabled ? m_arrowUpSmallPixmap
Chris@668 1139 : m_arrowUpSmallInvertedPixmap; // off state when value is max
Chris@668 1140 pixmap = pixmap.scaled(QSize(7, 7), Qt::KeepAspectRatio, Qt::SmoothTransformation); // TODO: edit the PNGs instead, would be faster
Chris@668 1141 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), spinupRect);
Chris@668 1142 painter->drawPixmap(drawRect.topLeft(), pixmap);
Chris@668 1143 }
Chris@668 1144 if (sb->subControls & SC_SpinBoxDown) {
Chris@668 1145 const QRect spindownRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
Chris@668 1146 gradient.setStart(spindownRect.topLeft());
Chris@668 1147 gradient.setFinalStop(spindownRect.bottomLeft());
Chris@668 1148 if (sb->activeSubControls == SC_SpinBoxDown && (option->state & State_MouseOver))
Chris@668 1149 painter->setBrush(QColor(0xDD, 0xEF, 0xFF));
Chris@668 1150 else
Chris@668 1151 painter->setBrush(gradient);
Chris@668 1152 painter->drawRect(spindownRect);
Chris@668 1153
Chris@668 1154 QPixmap pixmap = enabled ? m_arrowDownSmallPixmap
Chris@668 1155 : m_arrowDownSmallInvertedPixmap; // off state when value is max
Chris@668 1156 pixmap = pixmap.scaled(QSize(7, 7), Qt::KeepAspectRatio, Qt::SmoothTransformation); // TODO: edit the PNGs instead, would be faster
Chris@668 1157 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), spindownRect);
Chris@668 1158 painter->drawPixmap(drawRect.topLeft(), pixmap);
Chris@668 1159 }
Chris@668 1160 painter->setClipping(false);
Chris@668 1161 painter->setBrush(Qt::NoBrush);
Chris@668 1162 painter->setPen(QColor(0xB0, 0xB0, 0xB0)); // grabbed in frame.png
Chris@668 1163 painter->drawRoundedRect(frameRect, 4, 4);
Chris@668 1164 }
Chris@668 1165 return;
Chris@668 1166 default:
Chris@668 1167 break;
Chris@668 1168 }
Chris@668 1169 QProxyStyle::drawComplexControl(control, option, painter, widget);
Chris@668 1170 }
Chris@668 1171
Chris@668 1172 QSize ThornStyle::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const
Chris@668 1173 {
Chris@668 1174 QSize sz = QProxyStyle::sizeFromContents(type, option, size, widget);
Chris@668 1175 switch (type) {
Chris@668 1176 case CT_LineEdit:
Chris@668 1177 // Reduce size of lineedits, to make the NameSetEditor more compact (in the BankEditorDialog)
Chris@668 1178 sz -= QSize(2, 2);
Chris@668 1179 break;
Chris@668 1180 case CT_SpinBox:
Chris@668 1181 if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
Chris@668 1182 // Add button + frame widths
Chris@668 1183 const int buttonWidth = m_spinupPixmap.width();
Chris@668 1184 const int fw = vopt->frame ? pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
Chris@668 1185 sz += QSize(buttonWidth + 2*fw, 2*fw);
Chris@668 1186 }
Chris@668 1187 break;
Chris@668 1188 default:
Chris@668 1189 break;
Chris@668 1190 }
Chris@668 1191 return sz;
Chris@668 1192 }
Chris@668 1193
Chris@668 1194 QRect ThornStyle::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const
Chris@668 1195 {
Chris@668 1196 QRect rect = QProxyStyle::subElementRect(element, option, widget);
Chris@668 1197 switch (element) {
Chris@668 1198 case SE_TabWidgetTabBar:
Chris@668 1199 // QTabWidget::tab-bar { left: 5px; /* move to the right by 5px */ }
Chris@668 1200 return rect.translated(5, 0);
Chris@668 1201 case SE_TabWidgetTabPane:
Chris@668 1202 return rect;
Chris@668 1203 case SE_TabWidgetTabContents:
Chris@668 1204 return rect.adjusted(2, 2, -2, -2);
Chris@668 1205 case SE_HeaderArrow: {
Chris@668 1206 const QSize size = pixmapSize(m_arrowUpSmallInvertedPixmap);
Chris@668 1207 QRect sectionRect = option->rect.adjusted(0, 0, -5, 0);
Chris@668 1208 const QRect ret = alignedRect(option->direction, Qt::AlignRight | Qt::AlignVCenter, size, sectionRect);
Chris@668 1209 return ret;
Chris@668 1210 }
Chris@668 1211 case SE_ToolBarHandle:
Chris@668 1212 if (const QStyleOptionToolBar *tbopt = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
Chris@668 1213 // initially from qcommonstyle.cpp
Chris@668 1214 if (tbopt->features & QStyleOptionToolBar::Movable) {
Chris@668 1215 const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
Chris@668 1216 const int margin = 1;
Chris@668 1217 const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, option, tb);
Chris@668 1218 QRect ret;
Chris@668 1219 if (tbopt->state & QStyle::State_Horizontal) {
Chris@668 1220 ret = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin);
Chris@668 1221 ret = QStyle::visualRect(tbopt->direction, tbopt->rect, ret);
Chris@668 1222 } else {
Chris@668 1223 ret = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent);
Chris@668 1224 }
Chris@668 1225 return ret;
Chris@668 1226 }
Chris@668 1227 }
Chris@668 1228 break;
Chris@668 1229 default:
Chris@668 1230 break;
Chris@668 1231 }
Chris@668 1232
Chris@668 1233 return rect;
Chris@668 1234 }
Chris@668 1235
Chris@668 1236 QRect ThornStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *option, QStyle::SubControl sc, const QWidget *widget) const
Chris@668 1237 {
Chris@668 1238 switch (cc) {
Chris@668 1239 case CC_ScrollBar:
Chris@668 1240 if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
Chris@668 1241 QStyleOptionSlider copy = *scrollBar;
Chris@668 1242 // QScrollBar said { border: 2px solid #404040; }
Chris@668 1243 // We draw that border by filling everything and reducing the available size for contents
Chris@668 1244 copy.rect.adjust(2, 2, -2, -2);
Chris@668 1245 return QProxyStyle::subControlRect(cc, &copy, sc, widget).adjusted(2, 2, 2, 2);
Chris@668 1246 }
Chris@668 1247 break;
Chris@668 1248 case CC_Slider:
Chris@668 1249 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
Chris@668 1250 //QSlider::groove:horizontal { height: 5px; }
Chris@668 1251 const int grooveThickness = 5;
Chris@668 1252 QRect ret;
Chris@668 1253
Chris@668 1254 switch (sc) {
Chris@668 1255 case SC_SliderHandle: {
Chris@668 1256 int sliderPos = 0;
Chris@668 1257 // QSlider::handle:horizontal { width: 8px; }, but this needs to be 9 to look like the old qss for some reason
Chris@668 1258 int len = 9;
Chris@668 1259 bool horizontal = slider->orientation == Qt::Horizontal;
Chris@668 1260 sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum,
Chris@668 1261 slider->sliderPosition,
Chris@668 1262 (horizontal ? slider->rect.width()
Chris@668 1263 : slider->rect.height()) - len,
Chris@668 1264 slider->upsideDown);
Chris@668 1265 if (horizontal) {
Chris@668 1266 ret.setRect(slider->rect.x() + sliderPos, slider->rect.y() + 1, len, slider->rect.height() - 2);
Chris@668 1267 } else {
Chris@668 1268 ret.setRect(slider->rect.x() + 1, slider->rect.y() + sliderPos, slider->rect.width() - 2, len);
Chris@668 1269 }
Chris@668 1270 //qDebug() << "ret=" << ret;
Chris@668 1271 break;
Chris@668 1272 }
Chris@668 1273 case SC_SliderGroove:
Chris@668 1274 if (slider->orientation == Qt::Horizontal) {
Chris@668 1275 const int yOff = (slider->rect.height() - grooveThickness ) / 2;
Chris@668 1276 ret.setRect(slider->rect.x(), slider->rect.y() + yOff,
Chris@668 1277 slider->rect.width(), grooveThickness);
Chris@668 1278 } else {
Chris@668 1279 const int xOff = (slider->rect.width() - grooveThickness ) / 2;
Chris@668 1280 ret.setRect(slider->rect.x() + xOff, slider->rect.y(),
Chris@668 1281 grooveThickness, slider->rect.height());
Chris@668 1282 }
Chris@668 1283 break;
Chris@668 1284 default:
Chris@668 1285 break;
Chris@668 1286 }
Chris@668 1287 return visualRect(slider->direction, slider->rect, ret);
Chris@668 1288 }
Chris@668 1289 break;
Chris@668 1290 case CC_SpinBox:
Chris@668 1291 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
Chris@668 1292 const int fw = 3; // frame width
Chris@668 1293 const int buttonTopBottomMargin = fw - 1;
Chris@668 1294 const QSize buttonSize(18, (sb->rect.height() - buttonTopBottomMargin) / 2 - 1);
Chris@668 1295 const int x = sb->rect.x() + sb->rect.width() - fw - buttonSize.width();
Chris@668 1296 const int y = sb->rect.y() + buttonTopBottomMargin;
Chris@668 1297 QRect ret;
Chris@668 1298 switch (sc) {
Chris@668 1299 case SC_SpinBoxFrame:
Chris@668 1300 return sb->rect;
Chris@668 1301 case SC_SpinBoxUp:
Chris@668 1302 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons)
Chris@668 1303 return QRect();
Chris@668 1304 ret = QRect(x, y, buttonSize.width(), buttonSize.height());
Chris@668 1305 break;
Chris@668 1306 case SC_SpinBoxDown:
Chris@668 1307 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons)
Chris@668 1308 return QRect();
Chris@668 1309 ret = QRect(x, sb->rect.height() - buttonTopBottomMargin - buttonSize.height(), buttonSize.width(), buttonSize.height());
Chris@668 1310 break;
Chris@668 1311 case SC_SpinBoxEditField:
Chris@668 1312 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons) {
Chris@668 1313 ret = QRect(sb->rect.x() + fw, fw, sb->rect.width() - 2*fw, sb->rect.height() - 2*fw);
Chris@668 1314 } else {
Chris@668 1315 ret = QRect(sb->rect.x() + fw, fw, x - fw, sb->rect.height() - 2*fw);
Chris@668 1316 }
Chris@668 1317 break;
Chris@668 1318 default:
Chris@668 1319 break;
Chris@668 1320 }
Chris@668 1321 return visualRect(sb->direction, sb->rect, ret);
Chris@668 1322 }
Chris@668 1323 break;
Chris@668 1324 default:
Chris@668 1325 break;
Chris@668 1326 }
Chris@668 1327
Chris@668 1328 return QProxyStyle::subControlRect(cc, option, sc, widget);
Chris@668 1329 }
Chris@668 1330
Chris@668 1331 #pragma GCC diagnostic pop