diff options
Diffstat (limited to 'src/qtdesktop/qstyleitem.cpp')
-rw-r--r-- | src/qtdesktop/qstyleitem.cpp | 1072 |
1 files changed, 1072 insertions, 0 deletions
diff --git a/src/qtdesktop/qstyleitem.cpp b/src/qtdesktop/qstyleitem.cpp new file mode 100644 index 00000000..1acfb8b5 --- /dev/null +++ b/src/qtdesktop/qstyleitem.cpp @@ -0,0 +1,1072 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstyleitem.h" + +#include <QtGui/QPainter> +#include <QtWidgets/QStyle> +#include <QtWidgets/QStyleOption> +#include <QtWidgets/QApplication> +#include <QtWidgets/QMainWindow> +#include <QtWidgets/QGroupBox> +#include <QtWidgets/QToolBar> +#include <QtWidgets/QMenu> +#include <QtWidgets/QtWidgets> +#include <QtCore/QStringBuilder> + +#ifdef Q_OS_MAC +#include <Carbon/Carbon.h> + +static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect()) +{ + return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(), + convertRect.width() - rect.width(), convertRect.height() - rect.height()); +} + +/*! \internal + + Returns the CoreGraphics CGContextRef of the paint device. 0 is + returned if it can't be obtained. It is the caller's responsibility to + CGContextRelease the context when finished using it. + + \warning This function is only available on Mac OS X. + \warning This function is duplicated in qmacstyle_mac.mm +*/ +CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) +{ + + if (pdev->devType() == QInternal::Image) { + const QImage *i = static_cast<const QImage*>(pdev); + QImage *image = const_cast< QImage*>(i); + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); + uint flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; + CGContextRef ret = 0; + + ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + + CGContextTranslateCTM(ret, 0, image->height()); + CGContextScaleCTM(ret, 1, -1); + return ret; + } + return 0; +} + +#endif + +QStyleItem::QStyleItem(QQuickPaintedItem *parent) + : QQuickPaintedItem(parent), + m_styleoption(0), + m_itemType(Undefined), + m_sunken(false), + m_raised(false), + m_active(true), + m_selected(false), + m_focus(false), + m_hover(false), + m_on(false), + m_horizontal(true), + m_sharedWidget(false), + m_minimum(0), + m_maximum(100), + m_value(0), + m_step(0), + m_paintMargins(0), + m_contentWidth(0), + m_contentHeight(0) + +{ + m_font = qApp->font(); + setFlag(QQuickItem::ItemHasContents, true); + setSmooth(false); + + connect(this, SIGNAL(enabledChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(infoChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(onChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(selectedChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(activeChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(textChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(activeChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(raisedChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(sunkenChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(hoverChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(maximumChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(minimumChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(valueChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(horizontalChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(activeControlChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(hasFocusChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(activeControlChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(elementTypeChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(textChanged()), this, SLOT(updateSizeHint())); + connect(this, SIGNAL(contentWidthChanged(int)), this, SLOT(updateSizeHint())); + connect(this, SIGNAL(contentHeightChanged(int)), this, SLOT(updateSizeHint())); +} + +QStyleItem::~QStyleItem() +{ + delete m_styleoption; + m_styleoption = 0; +} + +void QStyleItem::initStyleOption() +{ + QString type = elementType(); + if (m_styleoption) + m_styleoption->state = 0; + + switch (m_itemType) { + case Button: { + if (!m_styleoption) + m_styleoption = new QStyleOptionButton(); + + QStyleOptionButton *opt = qstyleoption_cast<QStyleOptionButton*>(m_styleoption); + opt->text = text(); + opt->features = (activeControl() == "default") ? + QStyleOptionButton::DefaultButton : + QStyleOptionButton::None; + } + break; + case ItemRow: { + if (!m_styleoption) + m_styleoption = new QStyleOptionViewItem(); + + QStyleOptionViewItem *opt = qstyleoption_cast<QStyleOptionViewItem*>(m_styleoption); + opt->features = 0; + if (activeControl() == "alternate") + opt->features |= QStyleOptionViewItem::Alternate; + } + break; + + case Splitter: { + if (!m_styleoption) { + m_styleoption = new QStyleOption; + } + } + break; + + case Item: { + if (!m_styleoption) { + m_styleoption = new QStyleOptionViewItem(); + } + QStyleOptionViewItem *opt = qstyleoption_cast<QStyleOptionViewItem*>(m_styleoption); + opt->features = QStyleOptionViewItem::HasDisplay; + opt->text = text(); + opt->textElideMode = Qt::ElideRight; + QPalette pal = m_styleoption->palette; + pal.setBrush(QPalette::Base, Qt::NoBrush); + m_styleoption->palette = pal; + } + break; + case Header: { + if (!m_styleoption) + m_styleoption = new QStyleOptionHeader(); + + QStyleOptionHeader *opt = qstyleoption_cast<QStyleOptionHeader*>(m_styleoption); + opt->text = text(); + opt->sortIndicator = activeControl() == "down" ? + QStyleOptionHeader::SortDown + : activeControl() == "up" ? + QStyleOptionHeader::SortUp : QStyleOptionHeader::None; + if (info() == QLatin1String("beginning")) + opt->position = QStyleOptionHeader::Beginning; + else if (info() == QLatin1String("end")) + opt->position = QStyleOptionHeader::End; + else if (info() == QLatin1String("only")) + opt->position = QStyleOptionHeader::OnlyOneSection; + else + opt->position = QStyleOptionHeader::Middle; + } + break; + case ToolButton: { + if (!m_styleoption) + m_styleoption = new QStyleOptionToolButton(); + + QStyleOptionToolButton *opt = + qstyleoption_cast<QStyleOptionToolButton*>(m_styleoption); + opt->subControls = QStyle::SC_ToolButton; + opt->state |= QStyle::State_AutoRaise; + opt->activeSubControls = QStyle::SC_ToolButton; + } + break; + case ToolBar: { + if (!m_styleoption) + m_styleoption = new QStyleOptionToolBar(); + } + break; + case Tab: { + if (!m_styleoption) + m_styleoption = new QStyleOptionTab(); + + QStyleOptionTab *opt = qstyleoption_cast<QStyleOptionTab*>(m_styleoption); + opt->text = text(); + opt->shape = info() == "South" ? QTabBar::RoundedSouth : QTabBar::RoundedNorth; + if (activeControl() == QLatin1String("beginning")) + opt->position = QStyleOptionTab::Beginning; + else if (activeControl() == QLatin1String("end")) + opt->position = QStyleOptionTab::End; + else if (activeControl() == QLatin1String("only")) + opt->position = QStyleOptionTab::OnlyOneTab; + else + opt->position = QStyleOptionTab::Middle; + + } break; + + case Menu: { + if (!m_styleoption) + m_styleoption = new QStyleOptionMenuItem(); + } + break; + case Frame: { + if (!m_styleoption) + m_styleoption = new QStyleOptionFrame(); + + QStyleOptionFrame *opt = qstyleoption_cast<QStyleOptionFrame*>(m_styleoption); + opt->frameShape = QFrame::StyledPanel; + opt->lineWidth = 1; + opt->midLineWidth = 1; + } + break; + case TabFrame: { + if (!m_styleoption) + m_styleoption = new QStyleOptionTabWidgetFrame(); + QStyleOptionTabWidgetFrame *opt = qstyleoption_cast<QStyleOptionTabWidgetFrame*>(m_styleoption); + opt->shape = (info() == "South") ? QTabBar::RoundedSouth : QTabBar::RoundedNorth; + if (minimum()) + opt->selectedTabRect = QRect(value(), 0, minimum(), height()); + opt->tabBarSize = QSize(minimum() , height()); + // oxygen style needs this hack + opt->leftCornerWidgetSize = QSize(value(), 0); + } + break; + case MenuItem: + case ComboBoxItem: + { + if (!m_styleoption) + m_styleoption = new QStyleOptionMenuItem(); + + QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption); + opt->checked = false; + opt->text = text(); + } + break; + case CheckBox: + case RadioButton: + { + if (!m_styleoption) + m_styleoption = new QStyleOptionButton(); + + QStyleOptionButton *opt = qstyleoption_cast<QStyleOptionButton*>(m_styleoption); + if (!on()) + opt->state |= QStyle::State_Off; + opt->text = text(); + } + break; + case Edit: { + if (!m_styleoption) + m_styleoption = new QStyleOptionFrame(); + + QStyleOptionFrame *opt = qstyleoption_cast<QStyleOptionFrame*>(m_styleoption); + opt->lineWidth = 1; // this must be non-zero + } + break; + case ComboBox :{ + if (!m_styleoption) + m_styleoption = new QStyleOptionComboBox(); + QStyleOptionComboBox *opt = qstyleoption_cast<QStyleOptionComboBox*>(m_styleoption); + opt->currentText = text(); + } + break; + case SpinBox: { + if (!m_styleoption) + m_styleoption = new QStyleOptionSpinBox(); + + QStyleOptionSpinBox *opt = qstyleoption_cast<QStyleOptionSpinBox*>(m_styleoption); + opt->frame = true; + if (value() & 0x1) + opt->activeSubControls = QStyle::SC_SpinBoxUp; + else if (value() & (1<<1)) + opt->activeSubControls = QStyle::SC_SpinBoxDown; + opt->subControls = QStyle::SC_All; + opt->stepEnabled = 0; + if (value() & (1<<2)) + opt->stepEnabled |= QAbstractSpinBox::StepUpEnabled; + if (value() & (1<<3)) + opt->stepEnabled |= QAbstractSpinBox::StepDownEnabled; + } + break; + case Slider: + case Dial: + { + if (!m_styleoption) + m_styleoption = new QStyleOptionSlider(); + + QStyleOptionSlider *opt = qstyleoption_cast<QStyleOptionSlider*>(m_styleoption); + opt->minimum = minimum(); + opt->maximum = maximum(); + opt->sliderPosition = value(); + opt->singleStep = step(); + + if (opt->singleStep) { + qreal numOfSteps = (opt->maximum - opt->minimum) / opt->singleStep; + // at least 5 pixels between tick marks + if (numOfSteps && (width() / numOfSteps < 5)) + opt->tickInterval = qRound((5*numOfSteps / width()) + 0.5)*step(); + else + opt->tickInterval = opt->singleStep; + } else // default Qt-components implementation + opt->tickInterval = opt->maximum != opt->minimum ? 1200 / (opt->maximum - opt->minimum) : 0; + + opt->sliderValue = value(); + opt->subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle; + opt->tickPosition = (activeControl() == "tick" ? + QSlider::TicksBelow : QSlider::NoTicks); + if (opt->tickPosition != QSlider::NoTicks) + opt->subControls |= QStyle::SC_SliderTickmarks; + + opt->activeSubControls = QStyle::SC_None; + } + break; + case ProgressBar: { + if (!m_styleoption) + m_styleoption = new QStyleOptionProgressBar(); + + QStyleOptionProgressBar *opt = qstyleoption_cast<QStyleOptionProgressBar*>(m_styleoption); + opt->orientation = horizontal() ? Qt::Horizontal : Qt::Vertical; + opt->minimum = minimum(); + opt->maximum = maximum(); + opt->progress = value(); + } + break; + case GroupBox: { + if (!m_styleoption) + m_styleoption = new QStyleOptionGroupBox(); + + QStyleOptionGroupBox *opt = qstyleoption_cast<QStyleOptionGroupBox*>(m_styleoption); + opt->text = text(); + opt->lineWidth = 1; + opt->subControls = QStyle::SC_GroupBoxLabel; + opt->features = 0; + if (sunken()) { // Qt draws an ugly line here so I ignore it + opt->subControls |= QStyle::SC_GroupBoxFrame; + } else { + opt->features |= QStyleOptionFrame::Flat; + } + if (activeControl() == "checkbox") + opt->subControls |= QStyle::SC_GroupBoxCheckBox; + + } + break; + case ScrollBar: { + if (!m_styleoption) + m_styleoption = new QStyleOptionSlider(); + + QStyleOptionSlider *opt = qstyleoption_cast<QStyleOptionSlider*>(m_styleoption); + opt->minimum = minimum(); + opt->maximum = maximum(); + opt->pageStep = qMax(0, int(horizontal() ? width() : height())); + opt->orientation = horizontal() ? Qt::Horizontal : Qt::Vertical; + opt->sliderPosition = value(); + opt->sliderValue = value(); + opt->activeSubControls = (activeControl() == QLatin1String("up")) + ? QStyle::SC_ScrollBarSubLine : + (activeControl() == QLatin1String("down")) ? + QStyle::SC_ScrollBarAddLine: + QStyle::SC_ScrollBarSlider; + + opt->sliderValue = value(); + opt->subControls = QStyle::SC_All; + + } + case MenuBar: + if (!m_styleoption) { + QStyleOptionMenuItem *menuOpt = new QStyleOptionMenuItem(); + menuOpt->menuItemType = QStyleOptionMenuItem::EmptyArea; + m_styleoption = menuOpt; + } + + break; + case MenuBarItem: + if (!m_styleoption) { + QStyleOptionMenuItem *menuOpt = new QStyleOptionMenuItem(); + menuOpt->text = text(); + menuOpt->menuItemType = QStyleOptionMenuItem::Normal; + m_styleoption = menuOpt; + } + break; + default: + break; + } + + if (!m_styleoption) + m_styleoption = new QStyleOption(); + + m_styleoption->styleObject = this; + m_styleoption->rect = QRect(m_paintMargins, m_paintMargins, width() - 2* m_paintMargins, height() - 2 * m_paintMargins); + + if (isEnabled()) + m_styleoption->state |= QStyle::State_Enabled; + if (m_active) + m_styleoption->state |= QStyle::State_Active; + if (m_sunken) + m_styleoption->state |= QStyle::State_Sunken; + if (m_raised) + m_styleoption->state |= QStyle::State_Raised; + if (m_selected) + m_styleoption->state |= QStyle::State_Selected; + if (m_focus) + m_styleoption->state |= QStyle::State_HasFocus; + if (m_on) + m_styleoption->state |= QStyle::State_On; + if (m_hover) + m_styleoption->state |= QStyle::State_MouseOver; + if (m_horizontal) + m_styleoption->state |= QStyle::State_Horizontal; + + if (m_hint.indexOf("mini") != -1) { + m_styleoption->state |= QStyle::State_Mini; + } else if (m_hint.indexOf("small") != -1) { + m_styleoption->state |= QStyle::State_Small; + } + +} + +/* + * Property style + * + * Returns a simplified style name. + * + * QMacStyle = "mac" + * QWindowsXPStyle = "windowsxp" + * QFusionStyle = "fusion" + */ + +QString QStyleItem::style() const +{ + QString style = qApp->style()->metaObject()->className(); + style = style.toLower(); + if (style.startsWith(QLatin1Char('q'))) + style = style.right(style.length() - 1); + if (style.endsWith("style")) + style = style.left(style.length() - 5); + return style.toLower(); +} + +QString QStyleItem::hitTest(int px, int py) +{ + QStyle::SubControl subcontrol = QStyle::SC_All; + switch (m_itemType) { + case SpinBox :{ + subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_SpinBox, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + QPoint(px,py), 0); + if (subcontrol == QStyle::SC_SpinBoxUp) + return "up"; + else if (subcontrol == QStyle::SC_SpinBoxDown) + return "down"; + + } + break; + + case Slider: { + subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_Slider, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + QPoint(px,py), 0); + if (subcontrol == QStyle::SC_SliderHandle) + return "handle"; + + } + break; + case ScrollBar: { + subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_ScrollBar, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + QPoint(px,py), 0); + if (subcontrol == QStyle::SC_ScrollBarSlider) + return "handle"; + + if (subcontrol == QStyle::SC_ScrollBarSubLine) + return "up"; + else if (subcontrol == QStyle::SC_ScrollBarSubPage) + return "upPage"; + + if (subcontrol == QStyle::SC_ScrollBarAddLine) + return "down"; + else if (subcontrol == QStyle::SC_ScrollBarAddPage) + return "downPage"; + } + break; + default: + break; + } + return "none"; +} + +QSize QStyleItem::sizeFromContents(int width, int height) +{ + initStyleOption(); + + QSize size; + switch (m_itemType) { + case RadioButton: + size = qApp->style()->sizeFromContents(QStyle::CT_RadioButton, m_styleoption, QSize(width,height)); + break; + case CheckBox: + size = qApp->style()->sizeFromContents(QStyle::CT_CheckBox, m_styleoption, QSize(width,height)); + break; + case ToolBar: + size = QSize(200, 40); + break; + case ToolButton: { + QStyleOptionToolButton *btn = qstyleoption_cast<QStyleOptionToolButton*>(m_styleoption); + int newWidth = qMax(width, btn->fontMetrics.width(btn->text)); + int newHeight = qMax(height, btn->fontMetrics.height()); + size = qApp->style()->sizeFromContents(QStyle::CT_ToolButton, m_styleoption, QSize(newWidth, newHeight)); } + break; + case Button: { + QStyleOptionButton *btn = qstyleoption_cast<QStyleOptionButton*>(m_styleoption); + int newWidth = qMax(width, btn->fontMetrics.width(btn->text)); + int newHeight = qMax(height, btn->fontMetrics.height()); + size = qApp->style()->sizeFromContents(QStyle::CT_PushButton, m_styleoption, QSize(newWidth, newHeight)); } + break; + case ComboBox: { + QStyleOptionComboBox *btn = qstyleoption_cast<QStyleOptionComboBox*>(m_styleoption); + int newWidth = qMax(width, btn->fontMetrics.width(btn->currentText)); + int newHeight = qMax(height, btn->fontMetrics.height()); + size = qApp->style()->sizeFromContents(QStyle::CT_ComboBox, m_styleoption, QSize(newWidth, newHeight)); } + break; + case SpinBox: { + QStyleOptionSpinBox *box = qstyleoption_cast<QStyleOptionSpinBox*>(m_styleoption); + int newWidth = qMax(width, box->fontMetrics.width(QLatin1String("0.0"))); + int newHeight = qMax(height, box->fontMetrics.height()); + size = qApp->style()->sizeFromContents(QStyle::CT_SpinBox, m_styleoption, QSize(newWidth, newHeight)); } + break; + case Tab: + size = qApp->style()->sizeFromContents(QStyle::CT_TabBarTab, m_styleoption, QSize(width,height)); + break; + case Slider: + size = qApp->style()->sizeFromContents(QStyle::CT_Slider, m_styleoption, QSize(width,height)); + break; + case ProgressBar: + size = qApp->style()->sizeFromContents(QStyle::CT_ProgressBar, m_styleoption, QSize(width,height)); + break; + case Edit: + size = qApp->style()->sizeFromContents(QStyle::CT_LineEdit, m_styleoption, QSize(width,height)); + if (hint().indexOf("rounded") != -1) + size += QSize(0, 3); + break; + case GroupBox: + size = qApp->style()->sizeFromContents(QStyle::CT_GroupBox, m_styleoption, QSize(width,height)); + break; + case Header: + size = qApp->style()->sizeFromContents(QStyle::CT_HeaderSection, m_styleoption, QSize(width,height)); +#ifdef Q_OS_MAC + if (style() =="mac") + size.setHeight(15); +#endif + break; + case ItemRow: + case Item: //fall through + size = qApp->style()->sizeFromContents(QStyle::CT_ItemViewItem, m_styleoption, QSize(width,height)); + break; + case MenuBarItem: //fall through + size = qApp->style()->sizeFromContents(QStyle::CT_MenuBarItem, m_styleoption, QSize(width,height)); + break; + case MenuBar: //fall through + size = qApp->style()->sizeFromContents(QStyle::CT_MenuBar, m_styleoption, QSize(width,height)); + break; + default: + break; + } + return size; +} + +void QStyleItem::updateSizeHint() +{ + QSize implicitSize = sizeFromContents(m_contentWidth, m_contentHeight); + setImplicitSize(implicitSize.width(), implicitSize.height()); +} + +int QStyleItem::pixelMetric(const QString &metric) +{ + + if (metric == "scrollbarExtent") + return qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0) + 1; + else if (metric == "defaultframewidth") + return qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0); + else if (metric == "taboverlap") + return qApp->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0 ); + else if (metric == "tabbaseoverlap") + return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, 0 ); + else if (metric == "tabhspace") + return qApp->style()->pixelMetric(QStyle::PM_TabBarTabHSpace, 0 ); + else if (metric == "indicatorwidth") + return qApp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth, 0 ); + else if (metric == "tabvspace") + return qApp->style()->pixelMetric(QStyle::PM_TabBarTabVSpace, 0 ); + else if (metric == "tabbaseheight") + return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseHeight, 0 ); + else if (metric == "tabvshift") + return qApp->style()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, 0 ); + else if (metric == "menuhmargin") + return qApp->style()->pixelMetric(QStyle::PM_MenuHMargin, 0 ); + else if (metric == "menuvmargin") + return qApp->style()->pixelMetric(QStyle::PM_MenuVMargin, 0 ); + else if (metric == "menupanelwidth") + return qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0 ); + else if (metric == "splitterwidth") + return qApp->style()->pixelMetric(QStyle::PM_SplitterWidth, 0 ); + else if (metric == "scrollbarspacing") + return abs(qApp->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, 0 )); + return 0; +} + +QVariant QStyleItem::styleHint(const QString &metric) +{ + initStyleOption(); + if (metric == "comboboxpopup") { + return qApp->style()->styleHint(QStyle::SH_ComboBox_Popup, m_styleoption); + } else if (metric == "highlightedTextColor") { + return qApp->palette().highlightedText().color().name(); + } else if (metric == "textColor") { + return qApp->palette().text().color().name(); + } else if (metric == "focuswidget") { + return qApp->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget); + } else if (metric == "tabbaralignment") { + int result = qApp->style()->styleHint(QStyle::SH_TabBar_Alignment); + if (result == Qt::AlignCenter) + return "center"; + return "left"; + } else if (metric == "framearoundcontents") { + return qApp->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents); + } else if (metric == "scrollToClickPosition") + return qApp->style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition); + return 0; +} + +void QStyleItem::setHint(const QStringList &str) +{ + if (m_hint != str) { + m_hint = str; + initStyleOption(); + updateSizeHint(); + if (m_styleoption->state & QStyle::State_Mini) { + m_font.setPointSize(9.); + emit fontChanged(); + } else if (m_styleoption->state & QStyle::State_Small) { + m_font.setPointSize(11.); + emit fontChanged(); + } + } +} + + +void QStyleItem::setElementType(const QString &str) +{ + if (m_type == str) + return; + + m_type = str; + + emit elementTypeChanged(); + if (m_styleoption) { + delete m_styleoption; + m_styleoption = 0; + } + + // Only enable visible if the widget can animate + if (str == "menu" || str == "menuitem") { + m_itemType = (str == "menu") ? Menu : MenuItem; + } else if (str == "item" || str == "itemrow" || str == "header") { +#ifdef Q_OS_MAC + m_font.setPointSize(11.0); + emit fontChanged(); +#endif + if (str == "header") { + m_itemType = Header; + } else { + m_itemType = (str == "item") ? Item : ItemRow; + } + } else if (str == "groupbox") { + m_itemType = GroupBox; + } else if (str == "tab") { + m_itemType = Tab; + } else if (str == "tabframe") { + m_itemType = TabFrame; + } else if (str == "comboboxitem") { + // Gtk uses qobject cast, hence we need to separate this from menuitem + // On mac, we temporarily use the menu item because it has more accurate + // palette. + m_itemType = ComboBoxItem; + } else if (str == "toolbar") { + m_itemType = ToolBar; + } else if (str == "toolbutton") { + m_itemType = ToolButton; + } else if (str == "slider") { + m_itemType = Slider; + } else if (str == "frame") { + m_itemType = Frame; + } else if (str == "combobox") { + m_itemType = ComboBox; + } else if (str == "splitter") { + m_itemType = Splitter; + } else if (str == "progressbar") { + m_itemType = ProgressBar; + } else if (str == "button") { + m_itemType = Button; + } else if (str == "checkbox") { + m_itemType = CheckBox; + } else if (str == "radiobutton") { + m_itemType = RadioButton; + } else if (str == "edit") { + m_itemType = Edit; + } else if (str == "spinbox") { + m_itemType = SpinBox; + } else if (str == "scrollbar") { + m_itemType = ScrollBar; + } else if (str == "widget") { + m_itemType = Widget; + } else if (str == "focusframe") { + m_itemType = FocusFrame; + } else if (str == "dial") { + m_itemType = Dial; + } else if (str == "statusbar") { + m_itemType = StatusBar; + } else if (str == "machelpbutton") { + m_itemType = MacHelpButton; + } else if (str == "scrollareacorner") { + m_itemType = ScrollAreaCorner; + } else if (str == "menubar") { + m_itemType = MenuBar; + } else if (str == "menubaritem") { + m_itemType = MenuBarItem; + } else { + m_itemType = Undefined; + } + updateSizeHint(); +} + +QRectF QStyleItem::subControlRect(const QString &subcontrolString) +{ + QStyle::SubControl subcontrol = QStyle::SC_None; + initStyleOption(); + switch (m_itemType) { + case SpinBox: + { + QStyle::ComplexControl control = QStyle::CC_SpinBox; + if (subcontrolString == QLatin1String("down")) + subcontrol = QStyle::SC_SpinBoxDown; + else if (subcontrolString == QLatin1String("up")) + subcontrol = QStyle::SC_SpinBoxUp; + else if (subcontrolString == QLatin1String("edit")){ + subcontrol = QStyle::SC_SpinBoxEditField; + } + return qApp->style()->subControlRect(control, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + subcontrol); + + } + break; + case Slider: + { + QStyle::ComplexControl control = QStyle::CC_Slider; + if (subcontrolString == QLatin1String("handle")) + subcontrol = QStyle::SC_SliderHandle; + else if (subcontrolString == QLatin1String("groove")) + subcontrol = QStyle::SC_SliderGroove; + return qApp->style()->subControlRect(control, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + subcontrol); + + } + break; + case ScrollBar: + { + QStyle::ComplexControl control = QStyle::CC_ScrollBar; + if (subcontrolString == QLatin1String("slider")) + subcontrol = QStyle::SC_ScrollBarSlider; + if (subcontrolString == QLatin1String("groove")) + subcontrol = QStyle::SC_ScrollBarGroove; + else if (subcontrolString == QLatin1String("handle")) + subcontrol = QStyle::SC_ScrollBarSlider; + else if (subcontrolString == QLatin1String("add")) + subcontrol = QStyle::SC_ScrollBarAddPage; + else if (subcontrolString == QLatin1String("sub")) + subcontrol = QStyle::SC_ScrollBarSubPage; + return qApp->style()->subControlRect(control, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + subcontrol); + } + break; + default: + break; + } + return QRectF(); +} + +void QStyleItem::paint(QPainter *painter) +{ + if (width() < 1 || height() <1) + return; + + initStyleOption(); + + switch (m_itemType) { + case Button: + qApp->style()->drawControl(QStyle::CE_PushButton, m_styleoption, painter); + break; + case ItemRow :{ + QPixmap pixmap; + // Only draw through style once + const QString pmKey = QLatin1Literal("itemrow") % QString::number(m_styleoption->state,16) % activeControl(); + if (!QPixmapCache::find(pmKey, pixmap) || pixmap.width() < width() || height() != pixmap.height()) { + int newSize = width(); + pixmap = QPixmap(newSize, height()); + pixmap.fill(Qt::transparent); + QPainter pixpainter(&pixmap); + qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, m_styleoption, &pixpainter); + if (!qApp->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected) && selected()) + pixpainter.fillRect(m_styleoption->rect, m_styleoption->palette.highlight()); + QPixmapCache::insert(pmKey, pixmap); + } + painter->drawPixmap(0, 0, pixmap); + } + break; + case Item: + qApp->style()->drawControl(QStyle::CE_ItemViewItem, m_styleoption, painter); + break; + case Header: + qApp->style()->drawControl(QStyle::CE_Header, m_styleoption, painter); + break; + case ToolButton: + +#ifdef Q_OS_MAC + if (style() == "mac" && hint().indexOf("segmented") != -1) { + const QPaintDevice *target = painter->device(); + HIThemeSegmentDrawInfo sgi; + sgi.version = 0; + sgi.state = isEnabled() ? kThemeStateActive : kThemeStateDisabled; + if (sunken()) sgi.state |= kThemeStatePressed; + sgi.size = kHIThemeSegmentSizeNormal; + sgi.kind = kHIThemeSegmentKindTextured; + sgi.value = on() && !sunken() ? kThemeButtonOn : kThemeButtonOff; + + sgi.adornment |= kHIThemeSegmentAdornmentLeadingSeparator; + if (sunken()) { + sgi.adornment |= kHIThemeSegmentAdornmentTrailingSeparator; + } + SInt32 button_height; + GetThemeMetric(kThemeMetricButtonRoundedHeight, &button_height); + sgi.position = info() == "leftmost" ? kHIThemeSegmentPositionFirst: + info() == "rightmost" ? kHIThemeSegmentPositionLast : + info() == "h_middle" ? kHIThemeSegmentPositionMiddle : + kHIThemeSegmentPositionOnly; + QRect centered = m_styleoption->rect; + centered.setHeight(button_height); + centered.moveCenter(m_styleoption->rect.center()); + HIRect hirect = qt_hirectForQRect(centered.translated(0, -1), QRect(0, 0, 0, 0)); + HIThemeDrawSegment(&hirect, &sgi, qt_mac_cg_context(target), kHIThemeOrientationNormal); + } else +#endif + qApp->style()->drawComplexControl(QStyle::CC_ToolButton, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter); + break; + case Tab: + qApp->style()->drawControl(QStyle::CE_TabBarTab, m_styleoption, painter); + break; + case Frame: + qApp->style()->drawControl(QStyle::CE_ShapedFrame, m_styleoption, painter); + break; + case FocusFrame: + if (style() == "mac" && hint().indexOf("rounded") != -1) + break; // embedded in the line itself + else + qApp->style()->drawControl(QStyle::CE_FocusFrame, m_styleoption, painter); + break; + case TabFrame: + qApp->style()->drawPrimitive(QStyle::PE_FrameTabWidget, m_styleoption, painter); + break; + case MenuBar: + qApp->style()->drawControl(QStyle::CE_MenuBarEmptyArea, m_styleoption, painter); + break; + case MenuBarItem: + qApp->style()->drawControl(QStyle::CE_MenuBarItem, m_styleoption, painter); + break; + case MenuItem: + case ComboBoxItem: // fall through + qApp->style()->drawControl(QStyle::CE_MenuItem, m_styleoption, painter); + break; + case CheckBox: + qApp->style()->drawControl(QStyle::CE_CheckBox, m_styleoption, painter); + break; + case RadioButton: + qApp->style()->drawControl(QStyle::CE_RadioButton, m_styleoption, painter); + break; + case Edit: { +#ifdef Q_OS_MAC + if (style() == "mac" && hint().indexOf("rounded") != -1) { + const QPaintDevice *target = painter->device(); + HIThemeFrameDrawInfo fdi; + fdi.version = 0; + fdi.state = kThemeStateActive; + SInt32 frame_size; + GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); + fdi.kind = kHIThemeFrameTextFieldRound; + if ((m_styleoption->state & QStyle::State_ReadOnly) || !(m_styleoption->state & QStyle::State_Enabled)) + fdi.state = kThemeStateInactive; + fdi.isFocused = hasFocus(); + HIRect hirect = qt_hirectForQRect(m_styleoption->rect, + QRect(frame_size, frame_size, + frame_size * 2, frame_size * 2)); + HIThemeDrawFrame(&hirect, &fdi, qt_mac_cg_context(target), kHIThemeOrientationNormal); + } else +#endif + qApp->style()->drawPrimitive(QStyle::PE_PanelLineEdit, m_styleoption, painter); + } + break; + case MacHelpButton: +#ifdef Q_OS_MAC + { + const QPaintDevice *target = painter->device(); + HIThemeButtonDrawInfo fdi; + fdi.kind = kThemeRoundButtonHelp; + fdi.version = 0; + fdi.adornment = 0; + fdi.state = sunken() ? kThemeStatePressed : kThemeStateActive; + HIRect hirect = qt_hirectForQRect(m_styleoption->rect,QRect(0, 0, 0, 0)); + HIThemeDrawButton(&hirect, &fdi, qt_mac_cg_context(target), kHIThemeOrientationNormal, NULL); + } +#endif + break; + case Widget: + qApp->style()->drawPrimitive(QStyle::PE_Widget, m_styleoption, painter); + break; + case ScrollAreaCorner: + qApp->style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, m_styleoption, painter); + break; + case Splitter: + if (m_styleoption->rect.width() == 1) + painter->fillRect(0, 0, width(), height(), m_styleoption->palette.dark().color()); + else + qApp->style()->drawControl(QStyle::CE_Splitter, m_styleoption, painter); + break; + case ComboBox: + { + qApp->style()->drawComplexControl(QStyle::CC_ComboBox, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + painter); + // This is needed on mac as it will use the painter color and ignore the palette + QPen pen = painter->pen(); + painter->setPen(m_styleoption->palette.text().color()); + qApp->style()->drawControl(QStyle::CE_ComboBoxLabel, m_styleoption, painter); + painter->setPen(pen); + } break; + case SpinBox: + qApp->style()->drawComplexControl(QStyle::CC_SpinBox, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + painter); + break; + case Slider: + qApp->style()->drawComplexControl(QStyle::CC_Slider, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + painter); + break; + case Dial: + qApp->style()->drawComplexControl(QStyle::CC_Dial, + qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), + painter); + break; + case ProgressBar: + qApp->style()->drawControl(QStyle::CE_ProgressBar, m_styleoption, painter); + break; + case ToolBar: + qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter); + break; + case StatusBar: + if (style() == "mac") { + m_styleoption->rect.adjust(0, 1, 0, 0); + qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter); + m_styleoption->rect.adjust(0, -1, 0, 0); + painter->setPen(m_styleoption->palette.dark().color().darker(120)); + painter->drawLine(m_styleoption->rect.topLeft(), m_styleoption->rect.topRight()); + } else { + qApp->style()->drawPrimitive(QStyle::PE_PanelToolBar, m_styleoption, painter); + } + break; + case GroupBox: + qApp->style()->drawComplexControl(QStyle::CC_GroupBox, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter); + break; + case ScrollBar: + qApp->style()->drawComplexControl(QStyle::CC_ScrollBar, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter); + break; + case Menu: { + QStyleHintReturnMask val; + qApp->style()->styleHint(QStyle::SH_Menu_Mask, m_styleoption, 0, &val); + painter->save(); + painter->setClipRegion(val.region); + painter->fillRect(m_styleoption->rect, m_styleoption->palette.window()); + painter->restore(); + qApp->style()->drawPrimitive(QStyle::PE_PanelMenu, m_styleoption, painter); + + QStyleOptionFrame frame; + frame.lineWidth = qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth); + frame.midLineWidth = 0; + frame.rect = m_styleoption->rect; + qApp->style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, painter); + } + break; + default: + break; + } +} + +int QStyleItem::textWidth(const QString &text) +{ + return QFontMetrics(m_font).boundingRect(text).width(); +} + +QString QStyleItem::elidedText(const QString &text, int elideMode, int width) +{ + return qApp->fontMetrics().elidedText(text, Qt::TextElideMode(elideMode), width); +} + +bool QStyleItem::hasThemeIcon(const QString &icon) const +{ + return QIcon::hasThemeIcon(icon); +} |