View Full Version : Painting a CC_ToolButton in a custom delegate

10th October 2008, 16:23
I have a read-only model providing a contact list and a custom delegate to paint the contacts' details as well as two buttons. I also subclassed the view to be able to get mouse move and press events. Thus, the buttons can be clicked and react to mouse over events although they are just painted in the paint() method of the delegate. They are working fine but now I want to use toolbuttons instead, since one of them will have to be able to display a drop-down popup menu. This is the relevant part of paint() in the custom delegate:

// Draw buttons
QStyleOptionToolButton callOptionButton;
callOptionButton.direction = qApp->layoutDirection();
callOptionButton.features = QStyleOptionToolButton::MenuButtonPopup;
callOptionButton.palette = qApp->palette();
callOptionButton.rect = callButtonRect(option.rect);
callOptionButton.state = QStyle::State_Enabled | QStyle::State_Raised;
callOptionButton.toolButtonStyle = Qt::ToolButtonIconOnly;
if(m_activeOnIndex == index && m_activeButton == CallButton) {
if(m_isActiveButtonHovered) {
callOptionButton.state &= ~QStyle::State_Raised;
callOptionButton.state |= QStyle::State_Sunken;
} else if(m_pointerOnIndex == index && m_hoveredButton == CallButton)
callOptionButton.state |= QStyle::State_MouseOver;
callOptionButton.icon = QIcon(":/images/22x22/apps/internet-telephony.png");
callOptionButton.iconSize = QSize(22, 22);
qApp->style()->drawComplexControl(QStyle::CC_ToolButton, &callOptionButton, painter, m_view);

if(!email.isEmpty()) {
QStyleOptionToolButton emailOptionButton;
emailOptionButton.arrowType = Qt::NoArrow;
emailOptionButton.direction = qApp->layoutDirection();
emailOptionButton.features = QStyleOptionToolButton::None;
emailOptionButton.palette = qApp->palette();
emailOptionButton.rect = emailButtonRect(option.rect);
emailOptionButton.state = QStyle::State_Enabled | QStyle::State_Raised;
emailOptionButton.toolButtonStyle = Qt::ToolButtonIconOnly;
if(m_activeOnIndex == index && m_activeButton == EmailButton) {
if(m_isActiveButtonHovered) {
emailOptionButton.state &= ~QStyle::State_Raised;
emailOptionButton.state |= QStyle::State_Sunken;
} else if(m_pointerOnIndex == index && m_hoveredButton == EmailButton)
emailOptionButton.state |= QStyle::State_MouseOver;
emailOptionButton.icon = QIcon(":/images/22x22/actions/mail-message-new.png");
emailOptionButton.iconSize = QSize(22, 22);
qApp->style()->drawComplexControl(QStyle::CC_ToolButton, &emailOptionButton, painter, m_view);

The problem is they don't look as they should. With the Oxygen style (1st attachment), the phone toolbuttons look like if they had QStyle::State_AutoRaise set while it isn't. With the Plastique style (2nd attachment), they look fine but the E-mail tool buttons are painted with an arrow icon instead of the mail icon, like if QStyleOptionToolButton::arrowType was Qt:: DownArrow. Any idea why this happens? Is there, perhaps, a better way to have tool buttons for every row in the view?

PS: The 3rd attachment is how I'd like them to look like.

12th October 2008, 13:37
The best way to debug these kind of issues is to step line by line through the style drawing code to see exactly what happens.

17th October 2008, 12:11
I got an answer from the Trolltech technical support, so I post the solution here. I Just needed to add this:

emailOptionButton.subControls = QStyle::SC_ToolButton;

That way only the ToolButton subcontrol is painted but the arrow subcontrol isn't. I personally find it a bit weird having to do it this way while I already set Qt::NoArrow but it works.