Merge branch 'qt-dropdown'
Make wxQt wxComboBox behave more consistently with the other ports. Also includes related fixes to wxChoice and wxTextEntry. See https://github.com/wxWidgets/wxWidgets/pull/1161
This commit is contained in:
@@ -71,6 +71,8 @@ protected:
|
|||||||
virtual void DoClear();
|
virtual void DoClear();
|
||||||
virtual void DoDeleteOneItem(unsigned int pos);
|
virtual void DoDeleteOneItem(unsigned int pos);
|
||||||
|
|
||||||
|
void QtInitSort(QComboBox *combo);
|
||||||
|
|
||||||
QComboBox *m_qtComboBox;
|
QComboBox *m_qtComboBox;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -52,7 +52,7 @@ public:
|
|||||||
const wxValidator& validator = wxDefaultValidator,
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
const wxString& name = wxComboBoxNameStr);
|
const wxString& name = wxComboBoxNameStr);
|
||||||
|
|
||||||
virtual void SetSelection(int n) wxOVERRIDE { wxChoice::SetSelection(n); }
|
virtual void SetSelection(int n) wxOVERRIDE;
|
||||||
virtual void SetSelection(long from, long to) wxOVERRIDE;
|
virtual void SetSelection(long from, long to) wxOVERRIDE;
|
||||||
|
|
||||||
virtual int GetSelection() const wxOVERRIDE { return wxChoice::GetSelection(); }
|
virtual int GetSelection() const wxOVERRIDE { return wxChoice::GetSelection(); }
|
||||||
@@ -70,6 +70,12 @@ public:
|
|||||||
bool IsTextEmpty() const { return wxTextEntry::IsEmpty(); }
|
bool IsTextEmpty() const { return wxTextEntry::IsEmpty(); }
|
||||||
|
|
||||||
virtual void SetValue(const wxString& value) wxOVERRIDE;
|
virtual void SetValue(const wxString& value) wxOVERRIDE;
|
||||||
|
virtual void ChangeValue(const wxString& value) wxOVERRIDE;
|
||||||
|
virtual void AppendText(const wxString &value) wxOVERRIDE;
|
||||||
|
virtual void Replace(long from, long to, const wxString &value) wxOVERRIDE;
|
||||||
|
virtual void WriteText(const wxString &value) wxOVERRIDE;
|
||||||
|
virtual void SetInsertionPoint(long insertion) wxOVERRIDE;
|
||||||
|
virtual long GetInsertionPoint() const wxOVERRIDE;
|
||||||
|
|
||||||
virtual void Popup();
|
virtual void Popup();
|
||||||
virtual void Dismiss();
|
virtual void Dismiss();
|
||||||
@@ -80,6 +86,7 @@ protected:
|
|||||||
virtual wxString DoGetValue() const wxOVERRIDE;
|
virtual wxString DoGetValue() const wxOVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetActualValue(const wxString& value);
|
||||||
|
|
||||||
// From wxTextEntry:
|
// From wxTextEntry:
|
||||||
virtual wxWindow *GetEditableWindow() wxOVERRIDE { return this; }
|
virtual wxWindow *GetEditableWindow() wxOVERRIDE { return this; }
|
||||||
|
@@ -10,7 +10,38 @@
|
|||||||
|
|
||||||
#include "wx/choice.h"
|
#include "wx/choice.h"
|
||||||
#include "wx/qt/private/winevent.h"
|
#include "wx/qt/private/winevent.h"
|
||||||
|
|
||||||
#include <QtWidgets/QComboBox>
|
#include <QtWidgets/QComboBox>
|
||||||
|
#include <QtCore/QSortFilterProxyModel>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class LexicalSortProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
const QVariant leftData = sourceModel()->data( left );
|
||||||
|
const QVariant rightData = sourceModel()->data( right );
|
||||||
|
|
||||||
|
if ( leftData.type() != QVariant::String )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int insensitiveResult = QString::compare(
|
||||||
|
leftData.value<QString>(),
|
||||||
|
rightData.value<QString>(),
|
||||||
|
Qt::CaseInsensitive );
|
||||||
|
|
||||||
|
if ( insensitiveResult == 0 )
|
||||||
|
{
|
||||||
|
return QString::compare( leftData.value<QString>(),
|
||||||
|
rightData.value<QString>() ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return insensitiveResult < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class wxQtChoice : public wxQtEventSignalHandler< QComboBox, wxChoice >
|
class wxQtChoice : public wxQtEventSignalHandler< QComboBox, wxChoice >
|
||||||
{
|
{
|
||||||
@@ -36,12 +67,22 @@ void wxQtChoice::activated(int WXUNUSED(index))
|
|||||||
handler->SendSelectionChangedEvent(wxEVT_CHOICE);
|
handler->SendSelectionChangedEvent(wxEVT_CHOICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
wxChoice::wxChoice() :
|
wxChoice::wxChoice() :
|
||||||
m_qtComboBox(NULL)
|
m_qtComboBox(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxChoice::QtInitSort( QComboBox *combo )
|
||||||
|
{
|
||||||
|
QSortFilterProxyModel *proxyModel = new LexicalSortProxyModel();
|
||||||
|
proxyModel->setSourceModel(combo->model());
|
||||||
|
combo->model()->setParent(proxyModel);
|
||||||
|
combo->setModel(proxyModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxChoice::wxChoice( wxWindow *parent, wxWindowID id,
|
wxChoice::wxChoice( wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos,
|
const wxPoint& pos,
|
||||||
@@ -90,6 +131,8 @@ bool wxChoice::Create( wxWindow *parent, wxWindowID id,
|
|||||||
{
|
{
|
||||||
m_qtComboBox = new wxQtChoice( parent, this );
|
m_qtComboBox = new wxQtChoice( parent, this );
|
||||||
|
|
||||||
|
QtInitSort( m_qtComboBox );
|
||||||
|
|
||||||
while ( n-- > 0 )
|
while ( n-- > 0 )
|
||||||
m_qtComboBox->addItem( wxQtConvertString( *choices++ ));
|
m_qtComboBox->addItem( wxQtConvertString( *choices++ ));
|
||||||
|
|
||||||
@@ -169,11 +212,17 @@ int wxChoice::DoInsertItems(const wxArrayStringsAdapter & items,
|
|||||||
|
|
||||||
int wxChoice::DoInsertOneItem(const wxString& item, unsigned int pos)
|
int wxChoice::DoInsertOneItem(const wxString& item, unsigned int pos)
|
||||||
{
|
{
|
||||||
|
// Maintain unselected state
|
||||||
|
const bool unselected = m_qtComboBox->currentIndex() == -1;
|
||||||
|
|
||||||
m_qtComboBox->insertItem(pos, wxQtConvertString(item));
|
m_qtComboBox->insertItem(pos, wxQtConvertString(item));
|
||||||
|
|
||||||
if ( IsSorted() )
|
if ( IsSorted() )
|
||||||
m_qtComboBox->model()->sort(0);
|
m_qtComboBox->model()->sort(0);
|
||||||
|
|
||||||
|
if ( unselected )
|
||||||
|
m_qtComboBox->setCurrentIndex(-1);
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +246,12 @@ void wxChoice::DoClear()
|
|||||||
|
|
||||||
void wxChoice::DoDeleteOneItem(unsigned int pos)
|
void wxChoice::DoDeleteOneItem(unsigned int pos)
|
||||||
{
|
{
|
||||||
|
const int selection = GetSelection();
|
||||||
|
|
||||||
|
if ( selection >= 0 && static_cast<unsigned int>(selection) == pos )
|
||||||
|
{
|
||||||
|
SetSelection( wxNOT_FOUND );
|
||||||
|
}
|
||||||
m_qtComboBox->removeItem(pos);
|
m_qtComboBox->removeItem(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,13 +23,37 @@ public:
|
|||||||
virtual void showPopup() wxOVERRIDE;
|
virtual void showPopup() wxOVERRIDE;
|
||||||
virtual void hidePopup() wxOVERRIDE;
|
virtual void hidePopup() wxOVERRIDE;
|
||||||
|
|
||||||
|
class IgnoreTextChange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Note that wxComboBox inherits its QComboBox pointer from wxChoice,
|
||||||
|
// where it can't be stored as wxQtComboBox, but its dynamic type is
|
||||||
|
// nevertheless always wxQtComboBox, so the cast below is safe.
|
||||||
|
explicit IgnoreTextChange(QComboBox *combo)
|
||||||
|
: m_combo(static_cast<wxQtComboBox*>(combo))
|
||||||
|
{
|
||||||
|
m_combo->m_textChangeIgnored = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IgnoreTextChange()
|
||||||
|
{
|
||||||
|
m_combo->m_textChangeIgnored = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxQtComboBox* m_combo;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void activated(int index);
|
void activated(int index);
|
||||||
void editTextChanged(const QString &text);
|
void editTextChanged(const QString &text);
|
||||||
|
|
||||||
|
bool m_textChangeIgnored;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxQtComboBox::wxQtComboBox( wxWindow *parent, wxComboBox *handler )
|
wxQtComboBox::wxQtComboBox( wxWindow *parent, wxComboBox *handler )
|
||||||
: wxQtEventSignalHandler< QComboBox, wxComboBox >( parent, handler )
|
: wxQtEventSignalHandler< QComboBox, wxComboBox >( parent, handler ),
|
||||||
|
m_textChangeIgnored( false )
|
||||||
{
|
{
|
||||||
setEditable( true );
|
setEditable( true );
|
||||||
connect(this, static_cast<void (QComboBox::*)(int index)>(&QComboBox::activated),
|
connect(this, static_cast<void (QComboBox::*)(int index)>(&QComboBox::activated),
|
||||||
@@ -61,6 +85,9 @@ void wxQtComboBox::activated(int WXUNUSED(index))
|
|||||||
|
|
||||||
void wxQtComboBox::editTextChanged(const QString &text)
|
void wxQtComboBox::editTextChanged(const QString &text)
|
||||||
{
|
{
|
||||||
|
if ( m_textChangeIgnored )
|
||||||
|
return;
|
||||||
|
|
||||||
wxComboBox *handler = GetHandler();
|
wxComboBox *handler = GetHandler();
|
||||||
if ( handler )
|
if ( handler )
|
||||||
{
|
{
|
||||||
@@ -70,6 +97,11 @@ void wxQtComboBox::editTextChanged(const QString &text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxComboBox::SetSelection( int n )
|
||||||
|
{
|
||||||
|
wxQtComboBox::IgnoreTextChange ignore( m_qtComboBox );
|
||||||
|
wxChoice::SetSelection( n );
|
||||||
|
}
|
||||||
|
|
||||||
wxComboBox::wxComboBox()
|
wxComboBox::wxComboBox()
|
||||||
{
|
{
|
||||||
@@ -128,6 +160,8 @@ bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
|
|||||||
const wxString& name )
|
const wxString& name )
|
||||||
{
|
{
|
||||||
m_qtComboBox = new wxQtComboBox( parent, this );
|
m_qtComboBox = new wxQtComboBox( parent, this );
|
||||||
|
QtInitSort( m_qtComboBox );
|
||||||
|
|
||||||
while ( n-- > 0 )
|
while ( n-- > 0 )
|
||||||
m_qtComboBox->addItem( wxQtConvertString( *choices++ ));
|
m_qtComboBox->addItem( wxQtConvertString( *choices++ ));
|
||||||
m_qtComboBox->setEditText( wxQtConvertString( value ));
|
m_qtComboBox->setEditText( wxQtConvertString( value ));
|
||||||
@@ -135,12 +169,67 @@ bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
|
|||||||
return QtCreateControl( parent, id, pos, size, style, validator, name );
|
return QtCreateControl( parent, id, pos, size, style, validator, name );
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxComboBox::SetValue(const wxString& value)
|
void wxComboBox::SetActualValue(const wxString &value)
|
||||||
{
|
{
|
||||||
if ( HasFlag(wxCB_READONLY) )
|
if ( HasFlag(wxCB_READONLY) )
|
||||||
SetStringSelection(value);
|
{
|
||||||
|
SetStringSelection( value );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
wxTextEntry::SetValue(value);
|
wxTextEntry::SetValue(value);
|
||||||
|
m_qtComboBox->setEditText( wxQtConvertString(value) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::SetValue(const wxString& value)
|
||||||
|
{
|
||||||
|
SetActualValue( value );
|
||||||
|
SetInsertionPoint( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::ChangeValue(const wxString &value)
|
||||||
|
{
|
||||||
|
wxQtComboBox::IgnoreTextChange ignore( m_qtComboBox );
|
||||||
|
SetValue( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::AppendText(const wxString &value)
|
||||||
|
{
|
||||||
|
SetActualValue( GetValue() + value );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::Replace(long from, long to, const wxString &value)
|
||||||
|
{
|
||||||
|
const wxString original( GetValue() );
|
||||||
|
|
||||||
|
if ( to < 0 )
|
||||||
|
{
|
||||||
|
to = original.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( from == 0 )
|
||||||
|
{
|
||||||
|
SetActualValue( value + original.substr(to, original.length()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString front = original.substr( 0, from ) + value;
|
||||||
|
|
||||||
|
long iPoint = front.length();
|
||||||
|
if ( front.length() <= original.length() )
|
||||||
|
{
|
||||||
|
SetActualValue( front + original.substr(to, original.length()) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetActualValue( front );
|
||||||
|
}
|
||||||
|
SetInsertionPoint( iPoint );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::WriteText(const wxString &value)
|
||||||
|
{
|
||||||
|
m_qtComboBox->lineEdit()->insert( wxQtConvertString( value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString wxComboBox::DoGetValue() const
|
wxString wxComboBox::DoGetValue() const
|
||||||
@@ -166,15 +255,40 @@ void wxComboBox::Clear()
|
|||||||
|
|
||||||
void wxComboBox::SetSelection( long from, long to )
|
void wxComboBox::SetSelection( long from, long to )
|
||||||
{
|
{
|
||||||
// SelectAll uses -1 to -1, adjust for qt:
|
if ( from == -1 )
|
||||||
if (from == -1 && to == -1)
|
|
||||||
{
|
{
|
||||||
from = 0;
|
from = 0;
|
||||||
|
}
|
||||||
|
if ( to == -1 )
|
||||||
|
{
|
||||||
to = GetValue().length();
|
to = GetValue().length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetInsertionPoint( from );
|
||||||
// use the inner text entry widget (note that can be null if not editable)
|
// use the inner text entry widget (note that can be null if not editable)
|
||||||
if ( m_qtComboBox->lineEdit() != NULL )
|
if ( m_qtComboBox->lineEdit() != NULL )
|
||||||
m_qtComboBox->lineEdit()->setSelection(from, to);
|
{
|
||||||
|
m_qtComboBox->lineEdit()->setSelection( from, to - from );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxComboBox::SetInsertionPoint( long pos )
|
||||||
|
{
|
||||||
|
// check if pos indicates end of text:
|
||||||
|
if ( pos == -1 )
|
||||||
|
m_qtComboBox->lineEdit()->end( false );
|
||||||
|
else
|
||||||
|
m_qtComboBox->lineEdit()->setCursorPosition( pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
long wxComboBox::GetInsertionPoint() const
|
||||||
|
{
|
||||||
|
long selectionStart = m_qtComboBox->lineEdit()->selectionStart();
|
||||||
|
|
||||||
|
if ( selectionStart >= 0 )
|
||||||
|
return selectionStart;
|
||||||
|
|
||||||
|
return m_qtComboBox->lineEdit()->cursorPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxComboBox::GetSelection(long* from, long* to) const
|
void wxComboBox::GetSelection(long* from, long* to) const
|
||||||
|
@@ -20,9 +20,11 @@ void wxTextEntry::WriteText(const wxString& WXUNUSED(text))
|
|||||||
|
|
||||||
void wxTextEntry::Remove(long from, long to)
|
void wxTextEntry::Remove(long from, long to)
|
||||||
{
|
{
|
||||||
|
const long insertionPoint = GetInsertionPoint();
|
||||||
wxString string = GetValue();
|
wxString string = GetValue();
|
||||||
string.erase(from, to - from);
|
string.erase(from, to - from);
|
||||||
SetValue(string);
|
SetValue(string);
|
||||||
|
SetInsertionPoint( std::min(insertionPoint, static_cast<long>(string.length())) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxTextEntry::Copy()
|
void wxTextEntry::Copy()
|
||||||
|
@@ -201,6 +201,28 @@ void TextEntryTestCase::Replace()
|
|||||||
CPPUNIT_ASSERT_EQUAL(2, entry->GetInsertionPoint());
|
CPPUNIT_ASSERT_EQUAL(2, entry->GetInsertionPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEntryTestCase::WriteText()
|
||||||
|
{
|
||||||
|
wxTextEntry * const entry = GetTestEntry();
|
||||||
|
|
||||||
|
entry->SetValue("foo");
|
||||||
|
entry->SetInsertionPoint(3);
|
||||||
|
entry->WriteText("bar");
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "foobar", entry->GetValue() );
|
||||||
|
|
||||||
|
entry->SetValue("foo");
|
||||||
|
entry->SetInsertionPoint(0);
|
||||||
|
entry->WriteText("bar");
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "barfoo", entry->GetValue() );
|
||||||
|
|
||||||
|
entry->SetValue("abxxxhi");
|
||||||
|
entry->SetSelection(2, 5);
|
||||||
|
entry->WriteText("cdefg");
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "abcdefghi", entry->GetValue() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( 7, entry->GetInsertionPoint() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( false, entry->HasSelection() );
|
||||||
|
}
|
||||||
|
|
||||||
#if wxUSE_UIACTIONSIMULATOR
|
#if wxUSE_UIACTIONSIMULATOR
|
||||||
|
|
||||||
class TextEventHandler
|
class TextEventHandler
|
||||||
|
@@ -44,7 +44,8 @@ protected:
|
|||||||
WXUISIM_TEST( Editable ); \
|
WXUISIM_TEST( Editable ); \
|
||||||
CPPUNIT_TEST( Hint ); \
|
CPPUNIT_TEST( Hint ); \
|
||||||
CPPUNIT_TEST( CopyPaste ); \
|
CPPUNIT_TEST( CopyPaste ); \
|
||||||
CPPUNIT_TEST( UndoRedo )
|
CPPUNIT_TEST( UndoRedo ); \
|
||||||
|
CPPUNIT_TEST( WriteText )
|
||||||
|
|
||||||
void SetValue();
|
void SetValue();
|
||||||
void TextChangeEvents();
|
void TextChangeEvents();
|
||||||
@@ -55,6 +56,7 @@ protected:
|
|||||||
void Hint();
|
void Hint();
|
||||||
void CopyPaste();
|
void CopyPaste();
|
||||||
void UndoRedo();
|
void UndoRedo();
|
||||||
|
void WriteText();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Selection() test helper: verify that selection is as described by the
|
// Selection() test helper: verify that selection is as described by the
|
||||||
|
Reference in New Issue
Block a user