Fix crash on Android L and list view items.

This crash is visible on Android L. This patch removes the static_cast which caused the
crash and it also fixed the list view item problem. I could not create separated patches
because they depend too much on each other.

Task-number: QTBUG-42673
Task-number: QTBUG-41814
Change-Id: I5d3e9c2b73df8f0e87e815b785b1c64d65a3ffaf
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
This commit is contained in:
BogDan Vatra 2014-11-14 13:01:13 +02:00 committed by Jani Heikkinen
parent 946cf4ca00
commit dfbd09378c
2 changed files with 42 additions and 78 deletions

View File

@ -244,6 +244,10 @@ QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::PrimitiveElement primit
case QStyle::PE_FrameLineEdit:
return QC_EditText;
case QStyle::PE_IndicatorViewItemCheck:
case QStyle::PE_IndicatorCheckBox:
return QC_Checkbox;
case QStyle::PE_FrameWindow:
case QStyle::PE_Widget:
case QStyle::PE_Frame:
@ -357,37 +361,8 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element,
}
break;
default:
break;
}
} else if (element == CE_ItemViewItem) {
const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt);
if (vopt && vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
p->save();
p->setClipRect(opt->rect);
QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, w);
// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, w);
// draw the check mark
QStyleOptionViewItem option(*vopt);
option.rect = checkRect;
option.state = option.state & ~QStyle::State_HasFocus;
switch (vopt->checkState) {
case Qt::Unchecked:
option.state |= QStyle::State_Off;
break;
default:
option.state |= QStyle::State_On;
break;
}
QPixmap pixmap = checkBoxControl->imgCheckBox(&option);
p->drawPixmap(checkRect, pixmap);
p->restore();
} else {
QFusionStyle::drawControl(element, opt, p, w);
break;
}
} else {
QFusionStyle::drawControl(element, opt, p, w);
@ -532,7 +507,7 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc,
case CC_GroupBox: {
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
QSize checkBoxSize = checkBoxControl->size(opt);
int indicatorWidth = checkBoxSize.width();
int indicatorHeight = checkBoxSize.height();
QRect checkBoxRect;
@ -589,9 +564,9 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_ScrollBarExtent:
return 0;
case PM_IndicatorWidth:
return checkBoxControl->sizeCheckBox(option).width();
return checkBoxControl->size(option).width();
case PM_IndicatorHeight:
return checkBoxControl->sizeCheckBox(option).height();
return checkBoxControl->size(option).height();
default:
return QFusionStyle::pixelMetric(metric, option, widget);
}
@ -608,7 +583,7 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct,
if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
bool nullIcon = hdr->icon.isNull();
int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w);
int iconSize = nullIcon ? 0 : checkBoxControl->sizeCheckBox(opt).width();
int iconSize = nullIcon ? 0 : checkBoxControl->size(opt).width();
QSize txt;
/*
* These next 4 lines are a bad hack to fix a bug in case a QStyleSheet is applied at QApplication level.
@ -642,7 +617,7 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct,
if (ct == CT_GroupBox) {
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2);
QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt);
QSize checkBoxSize = checkBoxControl->size(opt);
int indicatorWidth = checkBoxSize.width();
int indicatorHeight = checkBoxSize.height();
QRect checkBoxRect;
@ -738,13 +713,6 @@ QSize QAndroidStyle::AndroidDrawable::size() const
return QSize();
}
QPixmap QAndroidStyle::AndroidDrawable::img() const
{
if (type() == Image || type() == NinePatch)
return static_cast<const QAndroidStyle::AndroidImageDrawable *>(this)->img();
return QPixmap();
}
QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable,
ItemType itemType)
@ -810,19 +778,7 @@ void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOp
QPixmapCache::insert(m_hashKey, pm);
}
painter->drawPixmap(opt->rect.x(), (opt->rect.height() - pm.height()) / 2, pm);
}
QPixmap QAndroidStyle::AndroidImageDrawable::img() const
{
if (m_hashKey.isEmpty())
m_hashKey = QFileInfo(m_filePath).fileName();
QPixmap pm;
if (!QPixmapCache::find(m_hashKey, &pm)) {
pm.load(m_filePath);
QPixmapCache::insert(m_hashKey, pm);
}
return pm;
painter->drawPixmap(opt->rect.x(), opt->rect.y() + (opt->rect.height() - pm.height()) / 2, pm);
}
QSize QAndroidStyle::AndroidImageDrawable::size() const
@ -1220,14 +1176,6 @@ QSize QAndroidStyle::AndroidStateDrawable::sizeImage(const QStyleOption *opt) co
s = drawable->size();
return s;
}
QPixmap QAndroidStyle::AndroidStateDrawable::img(const QStyleOption *opt) const
{
QPixmap pm;
const AndroidDrawable *drawable = bestAndroidStateMatch(opt);
if (drawable)
pm = drawable->img();
return pm;
}
const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const
{
@ -1507,7 +1455,6 @@ QRect QAndroidStyle::AndroidControl::subElementRect(QStyle::SubElement /* subEle
return visualRect(option->direction, option->rect, r);
}
return option->rect;
}
QRect QAndroidStyle::AndroidControl::subControlRect(const QStyleOptionComplex *option,
@ -1552,6 +1499,16 @@ QMargins QAndroidStyle::AndroidControl::padding()
return QMargins();
}
QSize QAndroidStyle::AndroidControl::size(const QStyleOption *option)
{
if (const AndroidDrawable *drawable = backgroundDrawable()) {
if (drawable->type() == State)
drawable = static_cast<const AndroidStateDrawable *>(backgroundDrawable())->bestAndroidStateMatch(option);
return drawable->size();
}
return QSize();
}
const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidControl::backgroundDrawable() const
{
return m_background;
@ -1562,11 +1519,12 @@ QAndroidStyle::AndroidCompoundButtonControl::AndroidCompoundButtonControl(const
: AndroidControl(control, itemType)
{
QVariantMap::const_iterator it = control.find(QLatin1String("CompoundButton_button"));
if (it != control.end())
if (it != control.end()) {
m_button = AndroidDrawable::fromMap(it.value().toMap(), itemType);
else
m_button = 0;
const_cast<AndroidDrawable *>(m_button)->setPaddingLeftToSizeWidth();
} else {
m_button = 0;
}
}
QAndroidStyle::AndroidCompoundButtonControl::~AndroidCompoundButtonControl()
@ -1582,16 +1540,24 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption
if (m_button)
m_button->draw(p, opt);
}
QSize QAndroidStyle::AndroidCompoundButtonControl::sizeCheckBox(const QStyleOption *opt) const
QMargins QAndroidStyle::AndroidCompoundButtonControl::padding()
{
const AndroidDrawable *drawable = m_button;
return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->sizeImage(opt);
if (m_button)
return m_button->padding();
return AndroidControl::padding();
}
QPixmap QAndroidStyle::AndroidCompoundButtonControl::imgCheckBox(const QStyleOption *opt) const
QSize QAndroidStyle::AndroidCompoundButtonControl::size(const QStyleOption *option)
{
const AndroidDrawable *drawable = m_button;
return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->img(opt);
if (m_button) {
if (m_button->type() == State)
return static_cast<const AndroidStateDrawable *>(m_button)->bestAndroidStateMatch(option)->size();
return m_button->size();
}
return AndroidControl::size(option);
}
const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const
{
return m_background ? m_background : m_button;

View File

@ -124,7 +124,6 @@ public:
static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType);
static QMargins extractMargins(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
QPixmap img() const;
protected:
ItemType m_itemType;
QMargins m_padding;
@ -149,7 +148,6 @@ public:
virtual void draw(QPainter *painter,const QStyleOption *opt) const;
virtual QSize size() const;
QPixmap img() const;
protected:
QString m_filePath;
mutable QString m_hashKey;
@ -223,7 +221,6 @@ public:
static int extractState(const QVariantMap &value);
virtual void setPaddingLeftToSizeWidth();
QSize sizeImage(const QStyleOption *opt) const;
QPixmap img(const QStyleOption *opt) const;
private:
typedef QPair<int, const AndroidDrawable *> StateType;
QList<StateType> m_states;
@ -263,6 +260,7 @@ public:
const QSize &contentsSize,
const QWidget *w) const;
virtual QMargins padding();
virtual QSize size(const QStyleOption *option);
protected:
virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_background;
@ -276,8 +274,8 @@ public:
AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType);
virtual ~AndroidCompoundButtonControl();
virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w);
QSize sizeCheckBox(const QStyleOption *opt) const;
QPixmap imgCheckBox(const QStyleOption *opt) const;
virtual QMargins padding();
virtual QSize size(const QStyleOption *option);
protected:
virtual const AndroidDrawable * backgroundDrawable() const;
const AndroidDrawable *m_button;