Istvan Szasz
Istvan Szasz

Reputation: 1567

Override checkable QGroupBox toggle behaviour

I've subclassed the QGroupBox class, with the checkable property enabled. I'm trying to override the behaviour of the toggle/checked events.

Here's the code:

class SideWidgetGroupBox: public QGroupBox
{
    Q_OBJECT
public:
    SideWidgetGroupBox(QWidget* parent = 0): QGroupBox(parent)
    {
        this->setCheckable(true);
        connect(this, SIGNAL(toggled(bool)), this, SLOT(my_toggled(bool)));
    }

private slots:
    void my_toggled (bool on)
    {
        std::cout << "my toggled method" <<std::endl;
    }
};

So far so good, my slot gets executed. However the groupboxs' contents also get enabled/disabled. Is there a way to prevent that? Or do I have to manually reset the original enabled/disabled state?

Upvotes: 3

Views: 4244

Answers (1)

Ezee
Ezee

Reputation: 4344

Is there a way to prevent enabling/disabling of a content?

Yes, but this way is not easy, because there is no QCheckBox there. What looks like a check box is an area of QGroupBox. And all events are processed by QGroupBox:
1. Override event method and prevent processing of QEvent::KeyRelease and QEvent::MouseRelease events by the base class.

bool SideWidgetGroupBox::event(QEvent *e)
{
  switch (e->type()) {
   case QEvent::KeyRelease:
   case QEvent::MouseButtonRelease:
     myHandler(e);
     return true;
  }
 return QGroupBox::event(e);
}

2. In myHandler check whether space pressed or the mouse clicked on the checkbox. Store checkBox value and do what you need. Use this code to check what is under cursor:

QStyleOptionGroupBox box;
initStyleOption(&box);
QStyle::SubControl released = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
                                                             event->pos(), this);
bool toggle = released == QStyle::SC_GroupBoxLabel || released == QStyle::SC_GroupBoxCheckBox;
if (toggle)
{
    m_state = !m_state;
    update();
}

3. Add method initStyleOption and set state to the state of the checkBox (you should store it by yourself):

void SideWidgetGroupBox::initStyleOption(QStyleOptionGroupBox *option) const
{
    QGroupBox::initStyleOption(option);
    QStyle::State flagToSet = m_state ? QStyle::State_On : QStyle::State_Off;
    QStyle::State flagToRemove = m_state ? QStyle::State_Off : QStyle::State_On;

    option->state |= flagToSet;     
    option->state &= ~flagToRemove;
    option->state &= ~QStyle::State_Sunken;
}

4.Method initStyleOption in QGroupBox is not virtual that is why you need to reimplement paintEvent also:

void paintEvent(QPaintEvent *)
{
    QStylePainter paint(this);
    QStyleOptionGroupBox option;
    initStyleOption(&option);
    paint.drawComplexControl(QStyle::CC_GroupBox, option);
}

do I have to manually reset the original enabled/disabled state?
You can't do this with setEnabled because it checks current checked state and prevents enabling of children. Although you can call setEnabled for children directly using this->findChildren<QWidget*>

Suggestion
You can use ways described above or remove standard checkBox and(or) label and put your own QCheckBox over the group (without layout, of course) and use it as you want. If you group can be moved you will need to move the check box also.

Upvotes: 6

Related Questions