1171 lines
41 KiB
C++
1171 lines
41 KiB
C++
/***************************************************************************
|
|
**
|
|
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
|
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qpixmapstyle_p.h"
|
|
#include "qpixmapstyle_p_p.h"
|
|
|
|
#include <QDebug>
|
|
#include <QTextEdit>
|
|
#include <QStringBuilder>
|
|
#include <QPainter>
|
|
#include <QPixmapCache>
|
|
#include <QStyleOption>
|
|
#include <QString>
|
|
#include <QProgressBar>
|
|
#include <QSlider>
|
|
#include <QEvent>
|
|
#include <QComboBox>
|
|
#include <QAbstractItemView>
|
|
#include <QListView>
|
|
#include <QTreeView>
|
|
#include <QStyledItemDelegate>
|
|
#include <QAbstractScrollArea>
|
|
#include <QScrollBar>
|
|
|
|
#include <qscroller.h>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
\class QPixmapStyle
|
|
\brief The QPixmapStyle class provides mechanism for writing pixmap based styles.
|
|
|
|
\since 5.7
|
|
\ingroup appearance
|
|
\inmodule QtWidgets
|
|
\internal
|
|
|
|
This is a convenience class that enables the implementation of a widget style using
|
|
pixmaps, on the same fashion used by the \l{BorderImage} QML type.
|
|
|
|
In order to style a QWidget, one simply needs to call QPixmapStyle::addDescriptor()
|
|
or QPixmapStyle::addPixmap() with the id of the component to be styled, the path of
|
|
the image to be used, the margins and the tiling rules:
|
|
|
|
\snippet styles/qcustompixmapstyle.cpp 0
|
|
|
|
\sa QStyle, QCommonStyle
|
|
*/
|
|
|
|
/*!
|
|
\internal
|
|
|
|
Constructs a QPixmapStyle object.
|
|
*/
|
|
QPixmapStyle::QPixmapStyle()
|
|
: QCommonStyle(*new QPixmapStylePrivate)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Destroys the QPixmapStyle object.
|
|
*/
|
|
QPixmapStyle::~QPixmapStyle()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::polish(QApplication *application)
|
|
{
|
|
QCommonStyle::polish(application);
|
|
#if 0 // Used to be included in Qt4 for Q_WS_WIN
|
|
QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::polish(QPalette &palette)
|
|
{
|
|
palette = proxy()->standardPalette();
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::polish(QWidget *widget)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
|
|
// Don't fill the interior of the QTextEdit
|
|
if (qobject_cast<QTextEdit*>(widget)) {
|
|
QPalette p = widget->palette();
|
|
p.setBrush(QPalette::Base, Qt::NoBrush);
|
|
widget->setPalette(p);
|
|
}
|
|
|
|
if (QProgressBar *pb = qobject_cast<QProgressBar*>(widget)) {
|
|
// Center the text in the progress bar
|
|
pb->setAlignment(Qt::AlignCenter);
|
|
// Change the font size if needed, as it's used to compute the minimum size
|
|
QFont font = pb->font();
|
|
font.setPixelSize(d->descriptors.value(PB_HBackground).size.height()/2);
|
|
pb->setFont(font);
|
|
}
|
|
|
|
if (qobject_cast<QSlider*>(widget))
|
|
widget->installEventFilter(this);
|
|
|
|
if (QComboBox *cb = qobject_cast<QComboBox*>(widget)) {
|
|
widget->installEventFilter(this);
|
|
// NOTE: This will break if the private API of QComboBox changes drastically
|
|
// Make sure the popup is created so we can change the frame style
|
|
QAbstractItemView *list = cb->view();
|
|
list->setProperty("_pixmap_combobox_list", true);
|
|
list->setItemDelegate(new QStyledItemDelegate(list));
|
|
QPalette p = list->palette();
|
|
p.setBrush(QPalette::Active, QPalette::Base, QBrush(Qt::transparent) );
|
|
p.setBrush(QPalette::Active, QPalette::AlternateBase, QBrush(Qt::transparent) );
|
|
p.setBrush(QPalette::Inactive, QPalette::Base, QBrush(Qt::transparent) );
|
|
p.setBrush(QPalette::Inactive, QPalette::AlternateBase, QBrush(Qt::transparent) );
|
|
p.setBrush(QPalette::Disabled, QPalette::Base, QBrush(Qt::transparent) );
|
|
p.setBrush(QPalette::Disabled, QPalette::AlternateBase, QBrush(Qt::transparent) );
|
|
list->setPalette(p);
|
|
|
|
QFrame *frame = qobject_cast<QFrame*>(list->parent());
|
|
if (frame) {
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_PopupDown);
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ItemSeparator);
|
|
frame->setContentsMargins(pix.margins.left(), desc.margins.top(),
|
|
pix.margins.right(), desc.margins.bottom());
|
|
frame->setAttribute(Qt::WA_TranslucentBackground);
|
|
#if 0 // Used to be included in Qt4 for Q_WS_WIN
|
|
// FramelessWindowHint is needed on windows to make
|
|
// WA_TranslucentBackground work properly
|
|
frame->setWindowFlags(widget->windowFlags() | Qt::FramelessWindowHint);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0)
|
|
widget->installEventFilter(this);
|
|
|
|
if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget)) {
|
|
scrollArea->viewport()->setAutoFillBackground(false);
|
|
if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(scrollArea)) {
|
|
view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
}
|
|
#if QT_CONFIG(gestures)
|
|
QScroller::grabGesture(scrollArea->viewport(), QScroller::LeftMouseButtonGesture);
|
|
#endif
|
|
}
|
|
|
|
if (qobject_cast<QScrollBar*>(widget))
|
|
widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
|
|
|
|
QCommonStyle::polish(widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::unpolish(QApplication *application)
|
|
{
|
|
QCommonStyle::unpolish(application);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::unpolish(QWidget *widget)
|
|
{
|
|
if (qobject_cast<QSlider*>(widget) ||
|
|
qobject_cast<QComboBox*>(widget)) {
|
|
widget->removeEventFilter(this);
|
|
}
|
|
|
|
if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0)
|
|
widget->removeEventFilter(this);
|
|
|
|
#if QT_CONFIG(gestures)
|
|
if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget))
|
|
QScroller::ungrabGesture(scrollArea->viewport());
|
|
#endif
|
|
|
|
QCommonStyle::unpolish(widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
switch (element) {
|
|
case PE_FrameFocusRect: //disable focus rectangle
|
|
break;
|
|
case PE_PanelButtonBevel:
|
|
case PE_PanelButtonCommand:
|
|
drawPushButton(option, painter, widget);
|
|
break;
|
|
case PE_PanelLineEdit:
|
|
case PE_FrameLineEdit:
|
|
drawLineEdit(option, painter, widget);
|
|
break;
|
|
case PE_Frame:
|
|
case PE_FrameDefaultButton:
|
|
if (qobject_cast<const QTextEdit*>(widget))
|
|
drawTextEdit(option, painter, widget);
|
|
break;
|
|
case PE_IndicatorCheckBox:
|
|
drawCheckBox(option, painter, widget);
|
|
break;
|
|
case PE_IndicatorRadioButton:
|
|
drawRadioButton(option, painter, widget);
|
|
break;
|
|
case PE_PanelItemViewItem:
|
|
if (qobject_cast<const QListView*>(widget))
|
|
drawPanelItemViewItem(option, painter, widget);
|
|
else
|
|
QCommonStyle::drawPrimitive(element, option, painter, widget);
|
|
break;
|
|
default:
|
|
QCommonStyle::drawPrimitive(element, option, painter, widget);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::drawControl(ControlElement element, const QStyleOption *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
switch (element) {
|
|
case CE_ProgressBarGroove:
|
|
drawProgressBarBackground(option, painter, widget);
|
|
break;
|
|
case CE_ProgressBarLabel:
|
|
drawProgressBarLabel(option, painter, widget);
|
|
break;
|
|
case CE_ProgressBarContents:
|
|
drawProgressBarFill(option, painter, widget);
|
|
break;
|
|
case CE_ShapedFrame:
|
|
// NOTE: This will break if the private API of QComboBox changes drastically
|
|
if (qstrcmp(widget->metaObject()->className(),"QComboBoxPrivateContainer") == 0) {
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_PopupDown);
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ItemSeparator);
|
|
QRect rect = option->rect;
|
|
rect.adjust(-pix.margins.left(), -desc.margins.top(),
|
|
pix.margins.right(), desc.margins.bottom());
|
|
bool up = widget->property("_pixmapstyle_combobox_up").toBool();
|
|
drawCachedPixmap(up ? DD_PopupUp : DD_PopupDown, rect, painter);
|
|
}
|
|
else {
|
|
QCommonStyle::drawControl(element, option, painter, widget);
|
|
}
|
|
break;
|
|
default:
|
|
QCommonStyle::drawControl(element, option, painter, widget);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
void QPixmapStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
switch (cc) {
|
|
case CC_Slider:
|
|
drawSlider(option, painter, widget);
|
|
break;
|
|
case CC_ComboBox:
|
|
drawComboBox(option, painter, widget);
|
|
break;
|
|
case CC_ScrollBar:
|
|
drawScrollBar(option, painter, widget);
|
|
break;
|
|
default:
|
|
QCommonStyle::drawComplexControl(cc, option, painter, widget);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
QSize QPixmapStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
|
|
const QSize &contentsSize, const QWidget *widget) const
|
|
{
|
|
switch (type) {
|
|
case CT_PushButton:
|
|
return pushButtonSizeFromContents(option, contentsSize, widget);
|
|
case CT_LineEdit:
|
|
return lineEditSizeFromContents(option, contentsSize, widget);
|
|
case CT_ProgressBar:
|
|
return progressBarSizeFromContents(option, contentsSize, widget);
|
|
case CT_Slider:
|
|
return sliderSizeFromContents(option, contentsSize, widget);
|
|
case CT_ComboBox:
|
|
return comboBoxSizeFromContents(option, contentsSize, widget);
|
|
case CT_ItemViewItem:
|
|
return itemViewSizeFromContents(option, contentsSize, widget);
|
|
default: ;
|
|
}
|
|
|
|
return QCommonStyle::sizeFromContents(type, option, contentsSize, widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
QRect QPixmapStyle::subElementRect(SubElement element, const QStyleOption *option,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
switch (element) {
|
|
case SE_LineEditContents:
|
|
{
|
|
QRect rect = QCommonStyle::subElementRect(element, option, widget);
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
|
|
rect.adjust(desc.margins.left(), desc.margins.top(),
|
|
-desc.margins.right(), -desc.margins.bottom());
|
|
rect = visualRect(option->direction, option->rect, rect);
|
|
return rect;
|
|
}
|
|
default: ;
|
|
}
|
|
|
|
return QCommonStyle::subElementRect(element, option, widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
QRect QPixmapStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option,
|
|
SubControl sc, const QWidget *widget) const
|
|
{
|
|
switch (cc) {
|
|
case CC_ComboBox:
|
|
return comboBoxSubControlRect(option, sc, widget);
|
|
case CC_ScrollBar:
|
|
return scrollBarSubControlRect(option, sc, widget);
|
|
default: ;
|
|
}
|
|
|
|
return QCommonStyle::subControlRect(cc, option, sc, widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
int QPixmapStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
switch (metric) {
|
|
case PM_ButtonShiftHorizontal:
|
|
case PM_ButtonShiftVertical:
|
|
return 0;
|
|
case PM_DefaultFrameWidth:
|
|
if (qobject_cast<const QTextEdit*>(widget)) {
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
|
|
return qMax(qMax(desc.margins.left(), desc.margins.right()),
|
|
qMax(desc.margins.top(), desc.margins.bottom()));
|
|
}
|
|
return 0;
|
|
case PM_IndicatorWidth:
|
|
return d->pixmaps.value(CB_Enabled).pixmap.width();
|
|
case PM_IndicatorHeight:
|
|
return d->pixmaps.value(CB_Enabled).pixmap.height();
|
|
case PM_CheckBoxLabelSpacing:
|
|
{
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(CB_Enabled);
|
|
return qMax(qMax(pix.margins.left(), pix.margins.right()),
|
|
qMax(pix.margins.top(), pix.margins.bottom()));
|
|
}
|
|
case PM_ExclusiveIndicatorWidth:
|
|
return d->pixmaps.value(RB_Enabled).pixmap.width();
|
|
case PM_ExclusiveIndicatorHeight:
|
|
return d->pixmaps.value(RB_Enabled).pixmap.height();
|
|
case PM_RadioButtonLabelSpacing:
|
|
{
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(RB_Enabled);
|
|
return qMax(qMax(pix.margins.left(), pix.margins.right()),
|
|
qMax(pix.margins.top(), pix.margins.bottom()));
|
|
}
|
|
case PM_SliderThickness:
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
const QPixmapStyleDescriptor desc =
|
|
d->descriptors.value(slider->orientation == Qt::Horizontal
|
|
? SG_HEnabled : SG_VEnabled);
|
|
return slider->orientation == Qt::Horizontal
|
|
? desc.size.height() : desc.size.width();
|
|
}
|
|
break;
|
|
case PM_SliderControlThickness:
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
const QPixmapStylePixmap pix =
|
|
d->pixmaps.value(slider->orientation == Qt::Horizontal
|
|
? SH_HEnabled : SH_VEnabled);
|
|
return slider->orientation == Qt::Horizontal
|
|
? pix.pixmap.height() : pix.pixmap.width();
|
|
}
|
|
break;
|
|
case PM_SliderLength:
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
const QPixmapStylePixmap pix =
|
|
d->pixmaps.value(slider->orientation == Qt::Horizontal
|
|
? SH_HEnabled : SH_VEnabled);
|
|
return slider->orientation == Qt::Horizontal
|
|
? pix.pixmap.width() : pix.pixmap.height();
|
|
}
|
|
break;
|
|
case PM_ScrollBarExtent:
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
const QPixmapStyleDescriptor desc =
|
|
d->descriptors.value(slider->orientation == Qt::Horizontal
|
|
? SB_Horizontal : SB_Vertical);
|
|
return slider->orientation == Qt::Horizontal
|
|
? desc.size.height() : desc.size.width();
|
|
}
|
|
break;
|
|
case PM_ScrollBarSliderMin:
|
|
return 0;
|
|
default: ;
|
|
}
|
|
|
|
return QCommonStyle::pixelMetric(metric, option, widget);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
int QPixmapStyle::styleHint(StyleHint hint, const QStyleOption *option,
|
|
const QWidget *widget, QStyleHintReturn *returnData) const
|
|
{
|
|
switch (hint) {
|
|
case SH_EtchDisabledText:
|
|
return false;
|
|
case SH_ComboBox_Popup:
|
|
return false;
|
|
default: ;
|
|
}
|
|
|
|
return QCommonStyle::styleHint(hint, option, widget, returnData);
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
QStyle::SubControl QPixmapStyle::hitTestComplexControl(QStyle::ComplexControl control,
|
|
const QStyleOptionComplex *option,
|
|
const QPoint &pos,
|
|
const QWidget *widget) const
|
|
{
|
|
const SubControl sc = QCommonStyle::hitTestComplexControl(control, option, pos, widget);
|
|
if (control == CC_ScrollBar) {
|
|
if (sc == SC_ScrollBarAddLine)
|
|
return SC_ScrollBarAddPage;
|
|
else if (sc == SC_ScrollBarSubLine)
|
|
return SC_ScrollBarSubPage;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*!
|
|
\reimp
|
|
*/
|
|
bool QPixmapStyle::eventFilter(QObject *watched, QEvent *event)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
|
|
if (QSlider *slider = qobject_cast<QSlider*>(watched)) {
|
|
switch (event->type()) {
|
|
case QEvent::MouseButtonPress:
|
|
case QEvent::MouseButtonRelease:
|
|
case QEvent::MouseMove:
|
|
slider->update();
|
|
break;
|
|
default: ;
|
|
}
|
|
}
|
|
|
|
if (QComboBox *comboBox = qobject_cast<QComboBox*>(watched)) {
|
|
switch (event->type()) {
|
|
case QEvent::MouseButtonPress:
|
|
event->ignore();
|
|
comboBox->setProperty("_pixmapstyle_combobox_pressed", true);
|
|
comboBox->repaint();
|
|
return true;
|
|
case QEvent::MouseButtonRelease:
|
|
comboBox->setProperty("_pixmapstyle_combobox_pressed", false);
|
|
comboBox->repaint();
|
|
if ( comboBox->view() ) {
|
|
if ( comboBox->view()->isVisible() || (!comboBox->isEnabled()))
|
|
comboBox->hidePopup();
|
|
else
|
|
comboBox->showPopup();
|
|
}
|
|
break;
|
|
default: ;
|
|
}
|
|
}
|
|
|
|
if (qstrcmp(watched->metaObject()->className(),"QComboBoxPrivateContainer") == 0) {
|
|
if (event->type() == QEvent::Show) {
|
|
QWidget *widget = qobject_cast<QWidget*>(watched);
|
|
int yPopup = widget->geometry().top();
|
|
int yCombo = widget->parentWidget()->mapToGlobal(QPoint(0, 0)).y();
|
|
QRect geom = widget->geometry();
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
|
|
const bool up = yPopup < yCombo;
|
|
geom.moveTop(geom.top() + (up ? desc.margins.top() : -desc.margins.bottom()));
|
|
widget->setGeometry(geom);
|
|
widget->setProperty("_pixmapstyle_combobox_up", up);
|
|
widget->parentWidget()->setProperty("_pixmapstyle_combobox_up", up);
|
|
}
|
|
}
|
|
|
|
return QCommonStyle::eventFilter(watched, event);
|
|
}
|
|
|
|
/*!
|
|
\fn void QPixmapStyle::addDescriptor(QPixmapStyle::ControlDescriptor control, const QString &fileName, QMargins margins, QTileRules tileRules)
|
|
|
|
Associates the pixmap having the given \a fileName with the given \a control. The \a margins parameter describe the boundaries
|
|
of the pixmap's top-left, top-right, bottom-left and bottom-right corners, as well as the left, right, top and bottorm segments
|
|
and the middle. The \a tileRules parameter describes how QPixmapStyle is supposed to handle the scaling of the center of the pixmap.
|
|
|
|
Use QPixmapStyle::addPixmap() for controls that are not resizable.
|
|
|
|
\snippet styles/qcustompixmapstyle.cpp 1
|
|
|
|
\sa addPixmap, copyDescriptor
|
|
|
|
*/
|
|
void QPixmapStyle::addDescriptor(QPixmapStyle::ControlDescriptor control, const QString &fileName,
|
|
QMargins margins, QTileRules tileRules)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
|
|
QPixmapStyleDescriptor desc;
|
|
QImage image(fileName);
|
|
|
|
if (image.isNull())
|
|
return;
|
|
|
|
desc.fileName = fileName;
|
|
desc.margins = margins;
|
|
desc.tileRules = tileRules;
|
|
desc.size = image.size();
|
|
|
|
d->descriptors[control] = desc;
|
|
}
|
|
|
|
/*!
|
|
\fn void QPixmapStyle::copyDescriptor(QPixmapStyle::ControlDescriptor source, QPixmapStyle::ControlDescriptor dest)
|
|
|
|
Copies the data associated with the \a source descriptor to the \a dest descriptor.
|
|
|
|
\snippet styles/qcustompixmapstyle.cpp 2
|
|
*/
|
|
|
|
void QPixmapStyle::copyDescriptor(QPixmapStyle::ControlDescriptor source,
|
|
QPixmapStyle::ControlDescriptor dest)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
d->descriptors[dest] = d->descriptors.value(source);
|
|
}
|
|
|
|
/*!
|
|
\fn void QPixmapStyle::drawCachedPixmap(QPixmapStyle::ControlDescriptor control, const QRect &rect, QPainter *painter) const
|
|
|
|
Draws the image associated with the current \a control on the given \a rect using the given \a painter.
|
|
*/
|
|
void QPixmapStyle::drawCachedPixmap(QPixmapStyle::ControlDescriptor control, const QRect &rect,
|
|
QPainter *p) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
auto descriptor = d->descriptors.constFind(control);
|
|
if (descriptor == d->descriptors.constEnd())
|
|
return;
|
|
const QPixmap pix = d->getCachedPixmap(control, descriptor.value(), rect.size());
|
|
Q_ASSERT(!pix.isNull());
|
|
p->drawPixmap(rect, pix);
|
|
}
|
|
|
|
/*!
|
|
\fn void QPixmapStyle::addPixmap(ControlPixmap control, const QString &fileName, QMargins margins)
|
|
|
|
Use this function to style statically sized controls such as check boxes.
|
|
|
|
\sa addDescriptor, copyPixmap
|
|
*/
|
|
void QPixmapStyle::addPixmap(ControlPixmap control, const QString &fileName,
|
|
QMargins margins)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
|
|
QPixmapStylePixmap pix;
|
|
QPixmap image(fileName);
|
|
|
|
if (image.isNull())
|
|
return;
|
|
|
|
pix.pixmap = image;
|
|
pix.margins = margins;
|
|
|
|
d->pixmaps[control] = pix;
|
|
}
|
|
|
|
/*
|
|
\fn void QPixmapStyle::copyPixmap(QPixmapStyle::ControlPixmap source, QPixmapStyle::ControlPixmap dest)
|
|
|
|
Copies the data associated with the \a source pixmap to the \a dest pixmap.
|
|
|
|
\sa addPixmap, addDescriptor, copyDescriptor
|
|
*/
|
|
void QPixmapStyle::copyPixmap(QPixmapStyle::ControlPixmap source, QPixmapStyle::ControlPixmap dest)
|
|
{
|
|
Q_D(QPixmapStyle);
|
|
d->pixmaps[dest] = d->pixmaps.value(source);
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
|
|
Constructs a QPixmapStyle object.
|
|
*/
|
|
QPixmapStyle::QPixmapStyle(QPixmapStylePrivate &dd)
|
|
: QCommonStyle(dd)
|
|
{}
|
|
|
|
void QPixmapStyle::drawPushButton(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
const bool checked = option->state & State_On;
|
|
const bool pressed = option->state & State_Sunken;
|
|
const bool enabled = option->state & State_Enabled;
|
|
|
|
ControlDescriptor control = PB_Enabled;
|
|
if (enabled)
|
|
control = pressed ? PB_Pressed : (checked ? PB_Checked : PB_Enabled);
|
|
else
|
|
control = checked ? PB_PressedDisabled : PB_Disabled;
|
|
drawCachedPixmap(control, option->rect, painter);
|
|
}
|
|
|
|
void QPixmapStyle::drawLineEdit(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
// Don't draw for the line edit inside a combobox
|
|
if (widget && qobject_cast<const QComboBox*>(widget->parentWidget()))
|
|
return;
|
|
|
|
const bool enabled = option->state & State_Enabled;
|
|
const bool focused = option->state & State_HasFocus;
|
|
ControlDescriptor control = enabled ? (focused ? LE_Focused : LE_Enabled) : LE_Disabled;
|
|
drawCachedPixmap(control, option->rect, painter);
|
|
}
|
|
|
|
void QPixmapStyle::drawTextEdit(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
const bool enabled = option->state & State_Enabled;
|
|
const bool focused = option->state & State_HasFocus;
|
|
ControlDescriptor control = enabled ? (focused ? TE_Focused : TE_Enabled) : TE_Disabled;
|
|
drawCachedPixmap(control, option->rect, painter);
|
|
}
|
|
|
|
void QPixmapStyle::drawCheckBox(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option);
|
|
|
|
const bool down = button->state & State_Sunken;
|
|
const bool enabled = button->state & State_Enabled;
|
|
const bool on = button->state & State_On;
|
|
|
|
ControlPixmap control;
|
|
if (enabled)
|
|
control = on ? (down ? CB_PressedChecked : CB_Checked) : (down ? CB_Pressed : CB_Enabled);
|
|
else
|
|
control = on ? CB_DisabledChecked : CB_Disabled;
|
|
painter->drawPixmap(button->rect, d->pixmaps.value(control).pixmap);
|
|
}
|
|
|
|
void QPixmapStyle::drawRadioButton(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option);
|
|
|
|
const bool down = button->state & State_Sunken;
|
|
const bool enabled = button->state & State_Enabled;
|
|
const bool on = button->state & State_On;
|
|
|
|
ControlPixmap control;
|
|
if (enabled)
|
|
control = on ? RB_Checked : (down ? RB_Pressed : RB_Enabled);
|
|
else
|
|
control = on ? RB_DisabledChecked : RB_Disabled;
|
|
painter->drawPixmap(button->rect, d->pixmaps.value(control).pixmap);
|
|
}
|
|
|
|
void QPixmapStyle::drawPanelItemViewItem(const QStyleOption *option, QPainter *painter,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
ControlPixmap cp = ID_Separator;
|
|
ControlDescriptor cd = ID_Selected;
|
|
|
|
if (widget && widget->property("_pixmap_combobox_list").toBool()) {
|
|
cp = DD_ItemSeparator;
|
|
cd = DD_ItemSelected;
|
|
}
|
|
|
|
QPixmap pix = d->pixmaps.value(cp).pixmap;
|
|
QRect rect = option->rect;
|
|
rect.setBottom(rect.top() + pix.height()-1);
|
|
painter->drawPixmap(rect, pix);
|
|
if (option->state & QStyle::State_Selected) {
|
|
rect = option->rect;
|
|
rect.setTop(rect.top() + pix.height());
|
|
drawCachedPixmap(cd, rect, painter);
|
|
}
|
|
}
|
|
|
|
void QPixmapStyle::drawProgressBarBackground(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
bool vertical = false;
|
|
if (const QStyleOptionProgressBar *pb =
|
|
qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
|
|
vertical = pb->orientation == Qt::Vertical;
|
|
}
|
|
drawCachedPixmap(vertical ? PB_VBackground : PB_HBackground, option->rect, painter);
|
|
}
|
|
|
|
void QPixmapStyle::drawProgressBarLabel(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
if (const QStyleOptionProgressBar *pb =
|
|
qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
|
|
const bool vertical = pb->orientation == Qt::Vertical;
|
|
if (!vertical) {
|
|
QPalette::ColorRole textRole = QPalette::ButtonText;
|
|
proxy()->drawItemText(painter, pb->rect,
|
|
Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
|
|
pb->state & State_Enabled, pb->text, textRole);
|
|
}
|
|
}
|
|
}
|
|
|
|
void QPixmapStyle::drawProgressBarFill(const QStyleOption *option,
|
|
QPainter *painter, const QWidget *) const
|
|
{
|
|
const QStyleOptionProgressBar *pbar =
|
|
qstyleoption_cast<const QStyleOptionProgressBar*>(option);
|
|
const bool vertical = pbar->orientation == Qt::Vertical;
|
|
const bool flip = (pbar->direction == Qt::RightToLeft) ^ pbar->invertedAppearance;
|
|
|
|
if (pbar->progress == pbar->maximum) {
|
|
drawCachedPixmap(vertical ? PB_VComplete : PB_HComplete, option->rect, painter);
|
|
|
|
} else {
|
|
if (pbar->progress == pbar->minimum)
|
|
return;
|
|
const auto totalSteps = qint64(pbar->maximum) - pbar->minimum;
|
|
const auto progressSteps = qint64(pbar->progress) - pbar->minimum;
|
|
const auto availablePixels = vertical ? option->rect.height() : option->rect.width();
|
|
const auto pixelsPerStep = double(availablePixels) / totalSteps;
|
|
|
|
const auto progress = static_cast<int>(progressSteps * pixelsPerStep); // width in pixels
|
|
|
|
QRect optRect = option->rect;
|
|
if (vertical) {
|
|
if (flip)
|
|
optRect.setBottom(optRect.top()+progress-1);
|
|
else
|
|
optRect.setTop(optRect.bottom()-progress+1);
|
|
} else {
|
|
if (flip)
|
|
optRect.setLeft(optRect.right()-progress+1);
|
|
else
|
|
optRect.setRight(optRect.left()+progress-1);
|
|
}
|
|
|
|
drawCachedPixmap(vertical ? PB_VContent : PB_HContent, optRect, painter);
|
|
}
|
|
}
|
|
|
|
void QPixmapStyle::drawSlider(const QStyleOptionComplex *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option);
|
|
if (!slider)
|
|
return;
|
|
|
|
const bool enabled = option->state & State_Enabled;
|
|
const bool pressed = option->state & State_Sunken;
|
|
const Qt::Orientation orient = slider->orientation;
|
|
|
|
const QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
|
|
if (option->subControls & SC_SliderGroove) {
|
|
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
|
|
if (groove.isValid()) {
|
|
// Draw the background
|
|
ControlDescriptor control;
|
|
if (orient == Qt::Horizontal)
|
|
control = enabled ? SG_HEnabled : SG_HDisabled;
|
|
else
|
|
control = enabled ? SG_VEnabled : SG_VDisabled;
|
|
drawCachedPixmap(control, groove, painter);
|
|
|
|
// Draw the active part
|
|
if (orient == Qt::Horizontal) {
|
|
control = enabled ? (pressed ? SG_HActivePressed : SG_HActiveEnabled )
|
|
: SG_HActiveDisabled;
|
|
} else {
|
|
control = enabled ? (pressed ? SG_VActivePressed : SG_VActiveEnabled )
|
|
: SG_VActiveDisabled;
|
|
}
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(control);
|
|
const QPixmap pix = d->getCachedPixmap(control, desc, groove.size());
|
|
if (!pix.isNull()) {
|
|
groove.setRight(orient == Qt::Horizontal
|
|
? handle.center().x() : handle.center().y());
|
|
painter->drawPixmap(groove, pix, groove);
|
|
}
|
|
}
|
|
}
|
|
if (option->subControls & SC_SliderHandle) {
|
|
if (handle.isValid()) {
|
|
ControlPixmap pix;
|
|
if (orient == Qt::Horizontal)
|
|
pix = enabled ? (pressed ? SH_HPressed : SH_HEnabled) : SH_HDisabled;
|
|
else
|
|
pix = enabled ? (pressed ? SH_VPressed : SH_VEnabled) : SH_VDisabled;
|
|
painter->drawPixmap(handle, d->pixmaps.value(pix).pixmap);
|
|
}
|
|
}
|
|
}
|
|
|
|
void QPixmapStyle::drawComboBox(const QStyleOptionComplex *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const bool enabled = option->state & State_Enabled;
|
|
const bool pressed = widget->property("_pixmapstyle_combobox_pressed").toBool();
|
|
const bool opened = option->state & State_On;
|
|
|
|
ControlDescriptor control =
|
|
enabled ? (pressed ? DD_ButtonPressed : DD_ButtonEnabled) : DD_ButtonDisabled;
|
|
drawCachedPixmap(control, option->rect, painter);
|
|
|
|
ControlPixmap cp = enabled ? (opened ? DD_ArrowOpen
|
|
: (pressed ? DD_ArrowPressed : DD_ArrowEnabled))
|
|
: DD_ArrowDisabled;
|
|
QPixmapStylePixmap pix = d->pixmaps.value(cp);
|
|
QRect rect = comboBoxSubControlRect(option, SC_ComboBoxArrow, widget);
|
|
painter->drawPixmap(rect, pix.pixmap);
|
|
}
|
|
|
|
void QPixmapStyle::drawScrollBar(const QStyleOptionComplex *option,
|
|
QPainter *painter, const QWidget *widget) const
|
|
{
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
// Do not draw the scrollbar
|
|
if (slider->minimum == slider->maximum)
|
|
return;
|
|
|
|
QRect rect = scrollBarSubControlRect(option, SC_ScrollBarSlider, widget);
|
|
ControlDescriptor control = slider->orientation == Qt::Horizontal
|
|
? SB_Horizontal : SB_Vertical;
|
|
drawCachedPixmap(control, rect, painter);
|
|
}
|
|
}
|
|
|
|
QSize QPixmapStyle::pushButtonSizeFromContents(const QStyleOption *option,
|
|
const QSize &contentsSize,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(PB_Enabled);
|
|
const int bm = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
|
|
|
|
int w = contentsSize.width();
|
|
int h = contentsSize.height();
|
|
w += desc.margins.left() + desc.margins.right() + bm;
|
|
h += desc.margins.top() + desc.margins.bottom() + bm;
|
|
|
|
return d->computeSize(desc, w, h);
|
|
}
|
|
|
|
QSize QPixmapStyle::lineEditSizeFromContents(const QStyleOption *,
|
|
const QSize &contentsSize, const QWidget *) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
|
|
const int border = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth);
|
|
|
|
int w = contentsSize.width() + border + desc.margins.left() + desc.margins.right();
|
|
int h = contentsSize.height() + border + desc.margins.top() + desc.margins.bottom();
|
|
|
|
return d->computeSize(desc, w, h);
|
|
}
|
|
|
|
QSize QPixmapStyle::progressBarSizeFromContents(const QStyleOption *option,
|
|
const QSize &contentsSize,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
bool vertical = false;
|
|
if (const QStyleOptionProgressBar *pb =
|
|
qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
|
|
vertical = pb->orientation == Qt::Vertical;
|
|
}
|
|
QSize result = QCommonStyle::sizeFromContents(CT_Slider, option, contentsSize, widget);
|
|
if (vertical) {
|
|
const QPixmapStyleDescriptor desc = d->descriptors.value(PB_VBackground);
|
|
return QSize(desc.size.height(), result.height());
|
|
} else {
|
|
const QPixmapStyleDescriptor desc = d->descriptors.value(PB_HBackground);
|
|
return QSize(result.width(), desc.size.height());
|
|
}
|
|
}
|
|
|
|
QSize QPixmapStyle::sliderSizeFromContents(const QStyleOption *option,
|
|
const QSize &contentsSize,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option);
|
|
if (!slider)
|
|
return QSize();
|
|
|
|
QSize result = QCommonStyle::sizeFromContents(CT_Slider, option, contentsSize, widget);
|
|
|
|
const QPixmapStyleDescriptor desc = d->descriptors.value(slider->orientation == Qt::Horizontal
|
|
? SG_HEnabled : SG_VEnabled);
|
|
|
|
if (slider->orientation == Qt::Horizontal)
|
|
return QSize(result.width(), desc.size.height());
|
|
else
|
|
return QSize(desc.size.width(), result.height());
|
|
}
|
|
|
|
QSize QPixmapStyle::comboBoxSizeFromContents(const QStyleOption *option,
|
|
const QSize &contentsSize,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
|
|
|
|
QSize result = QCommonStyle::sizeFromContents(CT_ComboBox, option, contentsSize, widget);
|
|
return d->computeSize(desc, result.width(), result.height());
|
|
}
|
|
|
|
QSize QPixmapStyle::itemViewSizeFromContents(const QStyleOption *option,
|
|
const QSize &contentsSize,
|
|
const QWidget *widget) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
QSize size = QCommonStyle::sizeFromContents(CT_ItemViewItem, option, contentsSize, widget);
|
|
|
|
ControlPixmap cp = ID_Separator;
|
|
ControlDescriptor cd = ID_Selected;
|
|
if (widget && widget->property("_pixmap_combobox_list").toBool()) {
|
|
cp = DD_ItemSeparator;
|
|
cd = DD_ItemSelected;
|
|
}
|
|
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(cd);
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(cp);
|
|
size.setHeight(qMax(size.height(),
|
|
desc.size.height() + pix.pixmap.height()));
|
|
return size;
|
|
}
|
|
|
|
QRect QPixmapStyle::comboBoxSubControlRect(const QStyleOptionComplex *option,
|
|
QStyle::SubControl sc, const QWidget *) const
|
|
{
|
|
Q_D(const QPixmapStyle);
|
|
|
|
QRect r = option->rect; // Default size
|
|
const QPixmapStylePixmap &pix = d->pixmaps.value(DD_ArrowEnabled);
|
|
const QPixmapStyleDescriptor &desc = d->descriptors.value(DD_ButtonEnabled);
|
|
|
|
switch (sc) {
|
|
case SC_ComboBoxArrow:
|
|
r.setRect(r.right() - pix.margins.right() - pix.pixmap.width(),
|
|
r.top() + pix.margins.top(),
|
|
pix.pixmap.width(), pix.pixmap.height());
|
|
break;
|
|
case SC_ComboBoxEditField:
|
|
r.adjust(desc.margins.left(), desc.margins.right(),
|
|
-desc.margins.right(), -desc.margins.bottom());
|
|
r.setRight(r.right() - pix.margins.right() - pix.margins.left() - pix.pixmap.width());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
r = visualRect(option->direction, option->rect, r);
|
|
return r;
|
|
}
|
|
|
|
QRect QPixmapStyle::scrollBarSubControlRect(const QStyleOptionComplex *option,
|
|
QStyle::SubControl sc, const QWidget *) const
|
|
{
|
|
if (const QStyleOptionSlider *slider =
|
|
qstyleoption_cast<const QStyleOptionSlider*>(option)) {
|
|
int length = (slider->orientation == Qt::Horizontal)
|
|
? slider->rect.width() : slider->rect.height();
|
|
int page = length * slider->pageStep
|
|
/ (slider->maximum - slider->minimum + slider->pageStep);
|
|
int pos = length * slider->sliderValue
|
|
/ (slider->maximum - slider->minimum + slider->pageStep);
|
|
pos = qMin(pos+page, length) - page;
|
|
|
|
QRect rect = slider->rect;
|
|
|
|
if (slider->orientation == Qt::Horizontal) {
|
|
switch (sc) {
|
|
case SC_ScrollBarAddPage:
|
|
rect.setLeft(pos+page);
|
|
return rect;
|
|
case SC_ScrollBarSubPage:
|
|
rect.setRight(pos);
|
|
return rect;
|
|
case SC_ScrollBarGroove:
|
|
return rect;
|
|
case SC_ScrollBarSlider:
|
|
rect.setLeft(pos);
|
|
rect.setRight(pos+page);
|
|
return rect;
|
|
default: ;
|
|
}
|
|
} else {
|
|
switch (sc) {
|
|
case SC_ScrollBarAddPage:
|
|
rect.setTop(pos+page);
|
|
return rect;
|
|
case SC_ScrollBarSubPage:
|
|
rect.setBottom(pos);
|
|
return rect;
|
|
case SC_ScrollBarGroove:
|
|
return rect;
|
|
case SC_ScrollBarSlider:
|
|
rect.setTop(pos);
|
|
rect.setBottom(pos+page);
|
|
return rect;
|
|
default: ;
|
|
}
|
|
}
|
|
}
|
|
return QRect();
|
|
}
|
|
|
|
QPixmap QPixmapStylePrivate::scale(int w, int h, const QPixmap &pixmap, const QPixmapStyleDescriptor &desc)
|
|
{
|
|
QPixmap result(w, h);
|
|
{
|
|
const QColor transparent(0, 0, 0, 0);
|
|
result.fill( transparent );
|
|
QPainter p( &result );
|
|
const QMargins margins = desc.margins;
|
|
qDrawBorderPixmap(&p, result.rect(), margins, pixmap,
|
|
pixmap.rect(), margins, desc.tileRules);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QPixmap QPixmapStylePrivate::getCachedPixmap(QPixmapStyle::ControlDescriptor control,
|
|
const QPixmapStyleDescriptor &desc,
|
|
const QSize &size) const
|
|
{
|
|
Q_Q(const QPixmapStyle);
|
|
|
|
const QString sizeString = QString::number(size.width()) % QLatin1Char('*')
|
|
% QString::number(size.height());
|
|
const QString key = QLatin1String(q->metaObject()->className()) % QString::number(control)
|
|
% QLatin1Char('@') % sizeString;
|
|
|
|
QPixmap result;
|
|
|
|
if (!QPixmapCache::find( key, &result)) {
|
|
QPixmap source(desc.fileName);
|
|
result = scale(size.width(), size.height(), source, desc);
|
|
QPixmapCache::insert(key, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QSize QPixmapStylePrivate::computeSize(const QPixmapStyleDescriptor &desc, int width, int height) const
|
|
{
|
|
if (desc.tileRules.horizontal != Qt::RepeatTile)
|
|
width = qMax(width, desc.size.width());
|
|
if (desc.tileRules.vertical != Qt::RepeatTile)
|
|
height = qMax(height, desc.size.height());
|
|
return QSize(width, height);
|
|
}
|
|
|
|
QT_END_NAMESPACE
|