Merge branch 'qt-textctrl-hittest' of https://github.com/AliKet/wxWidgets
Implement several previously missing wxTextCtrl functions in wxQt. See #23984.
This commit is contained in:
commit
9e8a913e4d
3 changed files with 149 additions and 10 deletions
|
|
@ -52,6 +52,14 @@ public:
|
|||
|
||||
virtual void ShowPosition(long pos) override;
|
||||
|
||||
virtual wxTextCtrlHitTestResult HitTest(const wxPoint& pt, long *pos) const override;
|
||||
virtual wxTextCtrlHitTestResult HitTest(const wxPoint& pt,
|
||||
wxTextCoord *col,
|
||||
wxTextCoord *row) const override
|
||||
{
|
||||
return wxTextCtrlBase::HitTest(pt, col, row);
|
||||
}
|
||||
|
||||
virtual void SetInsertionPoint(long pos) override;
|
||||
virtual long GetInsertionPoint() const override;
|
||||
virtual void SetSelection( long from, long to ) override;
|
||||
|
|
@ -68,10 +76,15 @@ public:
|
|||
|
||||
virtual void EmptyUndoBuffer() override;
|
||||
|
||||
virtual bool IsEditable() const override;
|
||||
virtual void SetEditable(bool editable) override;
|
||||
|
||||
virtual wxString DoGetValue() const override;
|
||||
virtual void DoSetValue(const wxString &text, int flags = 0) override;
|
||||
virtual void WriteText(const wxString& text) override;
|
||||
|
||||
virtual void SetMaxLength(unsigned long len) override;
|
||||
|
||||
virtual QWidget *GetHandle() const override;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@
|
|||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
#define wxHAS_QT_INPUTREJECTED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Abstract base class for wxQtSingleLineEdit and wxQtMultiLineEdit.
|
||||
* This splits the polymorphic behaviour into two separate classes, avoiding
|
||||
|
|
@ -37,8 +43,10 @@ public:
|
|||
virtual bool GetSelection(long *from, long *to) const = 0;
|
||||
virtual long XYToPosition(long x, long y) const = 0;
|
||||
virtual bool PositionToXY(long pos, long *x, long *y) const = 0;
|
||||
virtual wxTextCtrlHitTestResult HitTest(const wxPoint& pt, long *pos) const = 0;
|
||||
virtual QScrollArea *ScrollBarsContainer() const = 0;
|
||||
virtual void WriteText( const wxString &text ) = 0;
|
||||
virtual void SetMaxLength(unsigned long len) = 0;
|
||||
virtual void MarkDirty() = 0;
|
||||
virtual void DiscardEdits() = 0;
|
||||
virtual void blockSignals(bool block) = 0;
|
||||
|
|
@ -96,8 +104,16 @@ public:
|
|||
return GetHandler()->GetValue();
|
||||
}
|
||||
|
||||
// cursorRect() is protected in base class. Make it public
|
||||
// so it can be accessed by wxQtSingleLineEdit::HitTest()
|
||||
using QLineEdit::cursorRect;
|
||||
|
||||
private:
|
||||
void textChanged();
|
||||
|
||||
#ifdef wxHAS_QT_INPUTREJECTED
|
||||
void inputRejected();
|
||||
#endif
|
||||
};
|
||||
|
||||
class wxQtTextEdit : public wxQtEventSignalHandler< QTextEdit, wxTextCtrl >
|
||||
|
|
@ -241,6 +257,27 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual wxTextCtrlHitTestResult
|
||||
HitTest(const wxPoint& pt, long* pos) const override
|
||||
{
|
||||
auto qtEdit = static_cast<wxQtTextEdit* const>(m_edit);
|
||||
|
||||
auto cursor = qtEdit->cursorForPosition( wxQtConvertPoint(pt) );
|
||||
auto curRect = qtEdit->cursorRect(cursor);
|
||||
|
||||
if ( pos )
|
||||
*pos = cursor.position();
|
||||
|
||||
if ( pt.y > curRect.y() + qtEdit->fontMetrics().height() )
|
||||
return wxTE_HT_BELOW;
|
||||
|
||||
if ( pt.x > curRect.x() + qtEdit->fontMetrics().averageCharWidth() )
|
||||
return wxTE_HT_BEYOND;
|
||||
|
||||
return wxTE_HT_ON_TEXT;
|
||||
}
|
||||
|
||||
virtual void WriteText( const wxString &text ) override
|
||||
{
|
||||
m_edit->insertPlainText(wxQtConvertString( text ));
|
||||
|
|
@ -248,6 +285,11 @@ public:
|
|||
m_edit->ensureCursorVisible();
|
||||
}
|
||||
|
||||
virtual void SetMaxLength(unsigned long WXUNUSED(len)) override
|
||||
{
|
||||
wxMISSING_IMPLEMENTATION("not implemented for multiline control");
|
||||
}
|
||||
|
||||
virtual void MarkDirty() override
|
||||
{
|
||||
return m_edit->setWindowModified( true );
|
||||
|
|
@ -422,6 +464,15 @@ public:
|
|||
m_edit->insert(wxQtConvertString( text ));
|
||||
}
|
||||
|
||||
virtual void SetMaxLength(unsigned long len) override
|
||||
{
|
||||
// Notice that setMaxLength() takes an int and not an unsigned int
|
||||
m_edit->setMaxLength(
|
||||
len > std::numeric_limits<int>::max()
|
||||
? std::numeric_limits<int>::max() : len
|
||||
);
|
||||
}
|
||||
|
||||
virtual void MarkDirty() override
|
||||
{
|
||||
return m_edit->setModified( true );
|
||||
|
|
@ -489,6 +540,25 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual wxTextCtrlHitTestResult
|
||||
HitTest(const wxPoint& pt, long *pos) const override
|
||||
{
|
||||
auto qtEdit = static_cast<wxQtLineEdit* const>(m_edit);
|
||||
auto curPos = qtEdit->cursorPositionAt( wxQtConvertPoint(pt) );
|
||||
auto curRect = qtEdit->cursorRect();
|
||||
|
||||
if ( pos )
|
||||
*pos = curPos;
|
||||
|
||||
if ( pt.y > curRect.y() + qtEdit->fontMetrics().height() )
|
||||
return wxTE_HT_BELOW;
|
||||
|
||||
if ( pt.x > curRect.x() + qtEdit->fontMetrics().averageCharWidth() )
|
||||
return wxTE_HT_BEYOND;
|
||||
|
||||
return wxTE_HT_ON_TEXT;
|
||||
}
|
||||
|
||||
virtual QScrollArea *ScrollBarsContainer() const override
|
||||
{
|
||||
return nullptr;
|
||||
|
|
@ -515,6 +585,11 @@ wxQtLineEdit::wxQtLineEdit( wxWindow *parent, wxTextCtrl *handler )
|
|||
{
|
||||
connect(this, &QLineEdit::textChanged,
|
||||
this, &wxQtLineEdit::textChanged);
|
||||
|
||||
#ifdef wxHAS_QT_INPUTREJECTED
|
||||
connect(this, &QLineEdit::inputRejected,
|
||||
this, &wxQtLineEdit::inputRejected);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxQtLineEdit::textChanged()
|
||||
|
|
@ -526,6 +601,15 @@ void wxQtLineEdit::textChanged()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef wxHAS_QT_INPUTREJECTED
|
||||
void wxQtLineEdit::inputRejected()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_TEXT_MAXLEN, GetHandler()->GetId());
|
||||
event.SetString( GetHandler()->GetValue() );
|
||||
EmitEvent( event );
|
||||
}
|
||||
#endif // wxHAS_QT_INPUTREJECTED
|
||||
|
||||
wxQtTextEdit::wxQtTextEdit( wxWindow *parent, wxTextCtrl *handler )
|
||||
: wxQtEventSignalHandler< QTextEdit, wxTextCtrl >( parent, handler )
|
||||
{
|
||||
|
|
@ -676,6 +760,12 @@ void wxTextCtrl::ShowPosition(long WXUNUSED(pos))
|
|||
{
|
||||
}
|
||||
|
||||
wxTextCtrlHitTestResult
|
||||
wxTextCtrl::HitTest(const wxPoint& pt, long *pos) const
|
||||
{
|
||||
return m_qtEdit->HitTest(pt, pos);
|
||||
}
|
||||
|
||||
bool wxTextCtrl::DoLoadFile(const wxString& WXUNUSED(file), int WXUNUSED(fileType))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -726,6 +816,24 @@ void wxTextCtrl::EmptyUndoBuffer()
|
|||
m_qtEdit->EmptyUndoBuffer();
|
||||
}
|
||||
|
||||
bool wxTextCtrl::IsEditable() const
|
||||
{
|
||||
return HasFlag(wxTE_READONLY);
|
||||
}
|
||||
|
||||
void wxTextCtrl::SetEditable(bool editable)
|
||||
{
|
||||
long flags = GetWindowStyle();
|
||||
|
||||
if ( editable )
|
||||
flags &= ~wxTE_READONLY;
|
||||
else
|
||||
flags |= wxTE_READONLY;
|
||||
|
||||
SetWindowStyle(flags);
|
||||
m_qtEdit->SetStyleFlags(flags);
|
||||
}
|
||||
|
||||
void wxTextCtrl::SetInsertionPoint(long pos)
|
||||
{
|
||||
m_qtEdit->SetInsertionPoint(pos);
|
||||
|
|
@ -767,6 +875,11 @@ void wxTextCtrl::WriteText( const wxString &text )
|
|||
m_qtEdit->WriteText(text);
|
||||
}
|
||||
|
||||
void wxTextCtrl::SetMaxLength(unsigned long len)
|
||||
{
|
||||
m_qtEdit->SetMaxLength(len);
|
||||
}
|
||||
|
||||
void wxTextCtrl::DoSetValue( const wxString &text, int flags )
|
||||
{
|
||||
if ( text != DoGetValue() )
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "wx/dataobj.h"
|
||||
#endif // wxUSE_CLIPBOARD
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#if defined(__WXGTK__) || defined(__WXQT__)
|
||||
#include "waitfor.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -353,9 +353,6 @@ void TextCtrlTestCase::Redirector()
|
|||
|
||||
void TextCtrlTestCase::HitTestSingleLine()
|
||||
{
|
||||
#ifdef __WXQT__
|
||||
WARN("Does not work under WxQt");
|
||||
#else
|
||||
m_text->ChangeValue("Hit me");
|
||||
|
||||
// We don't know the size of the text borders, so we can't really do any
|
||||
|
|
@ -366,6 +363,21 @@ void TextCtrlTestCase::HitTestSingleLine()
|
|||
|
||||
long pos = -1;
|
||||
|
||||
#ifdef __WXQT__
|
||||
// Although it works fine interactively, testing HitTest() is not
|
||||
// straightforward under wxQt: We have to call SetInsertionPoint()
|
||||
// explicitly with the position returned by HitTest() before we call
|
||||
// it a second time (in the test below) to get the correct result.
|
||||
auto SetCursorPositionHack = [&](int n)
|
||||
{
|
||||
m_text->HitTest(wxPoint(n*sizeChar.x, yMid), &pos);
|
||||
m_text->SetInsertionPoint(pos);
|
||||
wxYield();
|
||||
};
|
||||
#else
|
||||
#define SetCursorPositionHack(n) // do nothing under the other ports
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK__
|
||||
wxYield();
|
||||
#endif
|
||||
|
|
@ -374,6 +386,7 @@ void TextCtrlTestCase::HitTestSingleLine()
|
|||
// first few characters under it.
|
||||
SECTION("Normal")
|
||||
{
|
||||
SetCursorPositionHack(2);
|
||||
REQUIRE( m_text->HitTest(wxPoint(2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
|
||||
CHECK( pos >= 0 );
|
||||
CHECK( pos < 3 );
|
||||
|
|
@ -383,6 +396,7 @@ void TextCtrlTestCase::HitTestSingleLine()
|
|||
// character.
|
||||
SECTION("Beyond")
|
||||
{
|
||||
SetCursorPositionHack(20);
|
||||
REQUIRE( m_text->HitTest(wxPoint(20*sizeChar.x, yMid), &pos) == wxTE_HT_BEYOND );
|
||||
CHECK( pos == m_text->GetLastPosition() );
|
||||
}
|
||||
|
|
@ -395,8 +409,8 @@ void TextCtrlTestCase::HitTestSingleLine()
|
|||
m_text->ChangeValue(wxString(200, 'X'));
|
||||
m_text->SetInsertionPointEnd();
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// wxGTK must be given an opportunity to lay the text out.
|
||||
#if defined(__WXGTK__) || defined(__WXQT__)
|
||||
// wxGTK and wxQt must be given an opportunity to lay the text out.
|
||||
YieldForAWhile();
|
||||
#endif
|
||||
|
||||
|
|
@ -404,13 +418,12 @@ void TextCtrlTestCase::HitTestSingleLine()
|
|||
CHECK( pos > 3 );
|
||||
|
||||
// Using negative coordinates works even under Xvfb, so test at least
|
||||
// for this -- however this only works in wxGTK, not wxMSW.
|
||||
#ifdef __WXGTK__
|
||||
// for this -- however this only works in wxGTK and wxQt, not wxMSW.
|
||||
#if defined(__WXGTK__) || defined(__WXQT__)
|
||||
REQUIRE( m_text->HitTest(wxPoint(-2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
|
||||
CHECK( pos > 3 );
|
||||
#endif // __WXGTK__
|
||||
#endif // __WXGTK__ || __WXQT__
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue