Merge branch 'qt-radio-groups'

Fix radio button grouping in Qt.

See https://github.com/wxWidgets/wxWidgets/pull/1212
This commit is contained in:
Vadim Zeitlin
2019-02-05 03:03:10 +01:00
3 changed files with 92 additions and 16 deletions

View File

@@ -37,8 +37,6 @@ public:
virtual QWidget *GetHandle() const; virtual QWidget *GetHandle() const;
protected:
private: private:
QRadioButton *m_qtRadioButton; QRadioButton *m_qtRadioButton;

View File

@@ -13,6 +13,53 @@
#include "wx/qt/private/winevent.h" #include "wx/qt/private/winevent.h"
#include <QtWidgets/QRadioButton> #include <QtWidgets/QRadioButton>
#include <QtWidgets/QButtonGroup>
namespace
{
// Tiny helper applying a safe cast to return the handle of wxRadioButton as
// its actual type.
inline
QRadioButton* QtGetRadioButton(wxRadioButton* radioBtn)
{
return static_cast<QRadioButton*>(radioBtn->GetHandle());
}
void QtStartNewGroup(QRadioButton* qtRadioButton)
{
// Note that the QButtonGroup created here will be deallocated when its
// parent // QRadioButton is destroyed.
QButtonGroup* qtButtonGroup = new QButtonGroup(qtRadioButton);
qtButtonGroup->addButton(qtRadioButton);
}
bool QtTryJoiningExistingGroup(wxRadioButton* radioBtnThis)
{
for ( wxWindow* previous = radioBtnThis->GetPrevSibling();
previous;
previous = previous->GetPrevSibling() )
{
if ( wxRadioButton* radioBtn = wxDynamicCast(previous, wxRadioButton) )
{
// We should never join the exclusive group of wxRB_SINGLE button.
if ( !radioBtn->HasFlag(wxRB_SINGLE) )
{
if ( QButtonGroup *qtGroup = QtGetRadioButton(radioBtn)->group() )
{
qtGroup->addButton(QtGetRadioButton(radioBtnThis));
return true;
}
}
break;
}
}
return false;
}
} // anonymous namespace
class wxQtRadioButton : public wxQtEventSignalHandler< QRadioButton, wxRadioButton > class wxQtRadioButton : public wxQtEventSignalHandler< QRadioButton, wxRadioButton >
{ {
@@ -65,7 +112,27 @@ bool wxRadioButton::Create( wxWindow *parent,
m_qtRadioButton = new wxQtRadioButton( parent, this ); m_qtRadioButton = new wxQtRadioButton( parent, this );
m_qtRadioButton->setText( wxQtConvertString( label )); m_qtRadioButton->setText( wxQtConvertString( label ));
return QtCreateControl( parent, id, pos, size, style, validator, name ); if ( !QtCreateControl(parent, id, pos, size, style, validator, name) )
return false;
// Check if we need to create a new button group: this must be done when
// explicitly requested to do so (wxRB_GROUP) but also for wxRB_SINGLE
// buttons to prevent them implicitly becoming part of an existing group.
if ( (style & wxRB_GROUP) || (style & wxRB_SINGLE) )
{
QtStartNewGroup(m_qtRadioButton);
}
else
{
// Otherwise try to join an already existing group. Currently we don't
// do anything if joining it fails, i.e. if there is no current group
// yet, because the radio buttons not explicitly associated with some
// group still work as if they were part of one, so we just ignore the
// return value of this function.
QtTryJoiningExistingGroup(this);
}
return true;
} }
void wxRadioButton::SetValue(bool value) void wxRadioButton::SetValue(bool value)

View File

@@ -17,6 +17,7 @@
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/app.h" #include "wx/app.h"
#include "wx/radiobut.h" #include "wx/radiobut.h"
#include "wx/stattext.h"
#endif // WX_PRECOMP #endif // WX_PRECOMP
#include "wx/uiaction.h" #include "wx/uiaction.h"
@@ -105,22 +106,25 @@ void RadioButtonTestCase::Value()
void RadioButtonTestCase::Group() void RadioButtonTestCase::Group()
{ {
//Add another button to the first group and create another of two buttons wxWindow* const parent = wxTheApp->GetTopWindow();
wxRadioButton* g1radio0 = new wxRadioButton(wxTheApp->GetTopWindow(),
wxID_ANY, "wxRadioButton",
wxDefaultPosition,
wxDefaultSize, wxRB_GROUP);
wxRadioButton* g1radio1 = new wxRadioButton(wxTheApp->GetTopWindow(), // Create two different radio groups.
wxID_ANY, "wxRadioButton"); wxRadioButton* g1radio0 = new wxRadioButton(parent, wxID_ANY, "radio 1.0",
wxDefaultPosition, wxDefaultSize,
wxRB_GROUP);
wxRadioButton* g2radio0 = new wxRadioButton(wxTheApp->GetTopWindow(), wxRadioButton* g1radio1 = new wxRadioButton(parent, wxID_ANY, "radio 1.1");
wxID_ANY, "wxRadioButton",
wxDefaultPosition,
wxDefaultSize, wxRB_GROUP);
wxRadioButton* g2radio1 = new wxRadioButton(wxTheApp->GetTopWindow(), wxRadioButton* g2radio0 = new wxRadioButton(parent, wxID_ANY, "radio 2.0",
wxID_ANY, "wxRadioButton"); wxDefaultPosition, wxDefaultSize,
wxRB_GROUP);
wxRadioButton* g2radio1 = new wxRadioButton(parent, wxID_ANY, "radio 2.1");
// Check that having another control between radio buttons doesn't break
// grouping.
wxStaticText* text = new wxStaticText(parent, wxID_ANY, "Label");
wxRadioButton* g2radio2 = new wxRadioButton(parent, wxID_ANY, "radio 2.1");
g1radio0->SetValue(true); g1radio0->SetValue(true);
g2radio0->SetValue(true); g2radio0->SetValue(true);
@@ -138,6 +142,11 @@ void RadioButtonTestCase::Group()
CPPUNIT_ASSERT(!g2radio0->GetValue()); CPPUNIT_ASSERT(!g2radio0->GetValue());
CPPUNIT_ASSERT(g2radio1->GetValue()); CPPUNIT_ASSERT(g2radio1->GetValue());
g2radio2->SetValue(true);
CPPUNIT_ASSERT(!g2radio0->GetValue());
CPPUNIT_ASSERT(!g2radio1->GetValue());
CPPUNIT_ASSERT(g2radio2->GetValue());
g1radio0->SetValue(true); g1radio0->SetValue(true);
g2radio0->SetValue(true); g2radio0->SetValue(true);
@@ -150,6 +159,8 @@ void RadioButtonTestCase::Group()
wxDELETE(g1radio1); wxDELETE(g1radio1);
wxDELETE(g2radio0); wxDELETE(g2radio0);
wxDELETE(g2radio1); wxDELETE(g2radio1);
wxDELETE(g2radio2);
wxDELETE(text);
} }
void RadioButtonTestCase::Single() void RadioButtonTestCase::Single()