c++qtqtoolbutton

autoexclusive tool buttons in Qt


Here I come up with my another question and this time regarding Qt Tool Buttons AutoExclusive property. Please find my question below:

Q) I have 4 tool buttons which are autoExclusive to each other but the problem I am facing is when I want deselect the selected button its not allowing me to do so(this is the defined behavior in Qt) but I want each button to mutually exclusive to each other as well as be possible to deselect it on clicking the selected button. Can anyone help me with this scenario. Programmatic examples are much more helpful.

Thanks in Advance Keshav


Solution

  • I had a similar requirement and ended up in developing a small container for QActions which had roughly the following interface:

    class ExclusiveActionGroup : public QObject
    {
        Q_OBJECT
    public:
        explicit ExclusiveActionGroup(QObject *parent = 0);
        QAction * addAction ( QAction * action );
        const QAction * checkedAction() const;
        void untrigger();
    
    protected slots:
        void slotActionToggled(bool);
    
    private:
        QList<QAction*> actions;
    };
    

    The slotActionToggled is hooked to the toggle function of the added actions and handles both the exclusivity of the group as well as the deselection (untriggering) of the whole group. Note that slotActionToggled might be triggered within the process of deselecting the corresponding QAction, so your code should handle this (and not toggle the Action again which triggers untoggling which ...)

    ADD-ON Complete implementation:

    #include "exclusiveactiongroup.h"
    #include <QAction>
    
    #if defined(_MSC_VER) && defined(_DEBUG)
    #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
    #define new DEBUG_NEW
    #endif // _MSC_VER
    
    ExclusiveActionGroup::ExclusiveActionGroup(QObject *parent) :
        QObject(parent)
    {
    }
    
    QAction * ExclusiveActionGroup::addAction ( QAction * action )
    {
        actions.push_back(action);
        connect(action, SIGNAL(toggled(bool)), this, SLOT(slotActionToggled(bool)));
        return action;
    }
    
    void ExclusiveActionGroup::slotActionToggled ( bool checked )
    {
        QAction* action = qobject_cast<QAction*>(sender());
        if (action && checked)
        {
            foreach(QAction* uncheck, actions)
            {
                if (uncheck != action)
                {
                    uncheck->setChecked(false); // triggers recursion, doesnt matter though
                }
            }
        }
    }
    
    const QAction* ExclusiveActionGroup::checkedAction() const
    {
        foreach(const QAction* a, actions)
        {
            if (a->isChecked())
            {
                return a;
            }
        }
        return 0;
    }
    
    void ExclusiveActionGroup::untrigger()
    {
        foreach(QAction* a, actions)
        {
            if (a->isChecked())
            {
                a->trigger();
                break;
            }
        }
    }