diff options
Diffstat (limited to 'tqtinterface/qt4/src/widgets/tqlineedit.cpp')
-rw-r--r-- | tqtinterface/qt4/src/widgets/tqlineedit.cpp | 108 |
1 files changed, 100 insertions, 8 deletions
diff --git a/tqtinterface/qt4/src/widgets/tqlineedit.cpp b/tqtinterface/qt4/src/widgets/tqlineedit.cpp index 2d41152..10c1be8 100644 --- a/tqtinterface/qt4/src/widgets/tqlineedit.cpp +++ b/tqtinterface/qt4/src/widgets/tqlineedit.cpp @@ -40,6 +40,12 @@ #include "tqlineedit.h" #ifndef TQT_NO_LINEEDIT + +// Keep this position to avoid patch rejection +#ifndef TQT_NO_IM +#include "tqinputcontext.h" +#endif + #include "tqpainter.h" #include "tqdrawutil.h" #include "tqfontmetrics.h" @@ -248,12 +254,17 @@ struct TQLineEditPrivate : public TQt // input methods int imstart, imend, imselstart, imselend; + bool composeMode() const { return preeditLength(); } + bool hasIMSelection() const { return imSelectionLength(); } + int preeditLength() const { return ( imend - imstart ); } + int imSelectionLength() const { return ( imselend - imselstart ); } // complex text tqlayout TQTextLayout textLayout; void updateTextLayout(); void moveCursor( int pos, bool mark = FALSE ); void setText( const TQString& txt ); + int xToPosInternal( int x, TQTextItem::CursorPosition ) const; int xToPos( int x, TQTextItem::CursorPosition = TQTextItem::BetweenCharacters ) const; inline int visualAlignment() const { return tqalignment ? tqalignment : int( isRightToLeft() ? TQt::AlignRight : TQt::AlignLeft ); } TQRect cursorRect() const; @@ -591,6 +602,7 @@ void TQLineEdit::setEchoMode( EchoMode mode ) return; d->echoMode = mode; d->updateTextLayout(); + setInputMethodEnabled( mode == Normal ); update(); } @@ -1422,6 +1434,8 @@ bool TQLineEdit::event( TQEvent * e ) */ void TQLineEdit::mousePressEvent( TQMouseEvent* e ) { + if ( sendMouseEventToInputContext( e ) ) + return; if ( e->button() == Qt::RightButton ) return; if ( d->tripleClickTimer && ( e->pos() - d->tripleClick ).manhattanLength() < @@ -1451,7 +1465,8 @@ void TQLineEdit::mousePressEvent( TQMouseEvent* e ) */ void TQLineEdit::mouseMoveEvent( TQMouseEvent * e ) { - + if ( sendMouseEventToInputContext( e ) ) + return; #ifndef TQT_NO_CURSOR if ( ( e->state() & Qt::MouseButtonMask ) == 0 ) { if ( !d->readOnly && d->dragEnabled @@ -1480,6 +1495,8 @@ void TQLineEdit::mouseMoveEvent( TQMouseEvent * e ) */ void TQLineEdit::mouseReleaseEvent( TQMouseEvent* e ) { + if ( sendMouseEventToInputContext( e ) ) + return; #ifndef TQT_NO_DRAGANDDROP if ( e->button() == Qt::LeftButton ) { if ( d->dndTimer ) { @@ -1506,6 +1523,8 @@ void TQLineEdit::mouseReleaseEvent( TQMouseEvent* e ) */ void TQLineEdit::mouseDoubleClickEvent( TQMouseEvent* e ) { + if ( sendMouseEventToInputContext( e ) ) + return; if ( e->button() == Qt::LeftButton ) { deselect(); d->cursor = d->xToPos( e->pos().x() ); @@ -1775,6 +1794,33 @@ void TQLineEdit::keyPressEvent( TQKeyEvent * e ) e->ignore(); } + +/*! + This function is not intended as polymorphic usage. Just a shared code + fragment that calls TQWidget::sendMouseEventToInputContext() easily for this + class. + */ +bool TQLineEdit::sendMouseEventToInputContext( TQMouseEvent *e ) +{ +#ifndef TQT_NO_IM + if ( d->composeMode() ) { + int cursor = d->xToPosInternal( e->pos().x(), TQTextItem::OnCharacters ); + int mousePos = cursor - d->imstart; + if ( mousePos >= 0 && mousePos < d->preeditLength() ) { + TQWidget::sendMouseEventToInputContext( mousePos, e->type(), + e->button(), e->state() ); + } else if ( e->type() != TQEvent::MouseMove ) { + // send button events on out of preedit + TQWidget::sendMouseEventToInputContext( -1, e->type(), + e->button(), e->state() ); + } + return TRUE; + } +#endif + return FALSE; +} + + /*! \reimp */ void TQLineEdit::imStartEvent( TQIMEvent *e ) @@ -1841,6 +1887,8 @@ void TQLineEdit::focusInEvent( TQFocusEvent* tqfe ) } if( !hasSelectedText() || tqstyle().tqstyleHint( TQStyle::SH_BlinkCursorWhenTextSelected ) ) d->setCursorVisible( TRUE ); + if ( d->hasIMSelection() ) + d->cursor = d->imselstart; d->updateMicroFocusHint(); } @@ -1934,6 +1982,14 @@ void TQLineEdit::drawContents( TQPainter *p ) } else if (d->hscroll < 0) { d->hscroll = 0; } + // This updateMicroFocusHint() is corresponding to update() at + // IMCompose event. Although the function is invoked from various + // other points, some situations such as "candidate selection on + // AlignHCenter'ed text" need this invocation because + // updateMicroFocusHint() requires updated contentsRect(), and + // there are no other chances in such situation that invoke the + // function. + d->updateMicroFocusHint(); // the y offset is there to keep the baseline constant in case we have script changes in the text. TQPoint topLeft = lineRect.topLeft() - TQPoint(d->hscroll, d->ascent-fm.ascent()); @@ -1974,7 +2030,7 @@ void TQLineEdit::drawContents( TQPainter *p ) } // input method edit area - if ( d->imstart < d->imend && (last >= d->imstart && first < d->imend ) ) { + if ( d->composeMode() && (last >= d->imstart && first < d->imend ) ) { TQRect highlight = TQRect( TQPoint( tix + ti.cursorToX( TQMAX( d->imstart - first, 0 ) ), lineRect.top() ), TQPoint( tix + ti.cursorToX( TQMIN( d->imend - first, last - first + 1 ) )-1, lineRect.bottom() ) ).normalize(); p->save(); @@ -1987,11 +2043,16 @@ void TQLineEdit::drawContents( TQPainter *p ) imCol.setHsv( h1, s1, ( v1 + v2 ) / 2 ); p->fillRect( highlight, imCol ); p->tqdrawTextItem( topLeft, ti, textflags ); + // draw preedit's underline + if (d->imend - d->imstart > 0) { + p->setPen( cg.text() ); + p->drawLine( highlight.bottomLeft(), highlight.bottomRight() ); + } p->restore(); } // input method selection - if ( d->imselstart < d->imselend && (last >= d->imselstart && first < d->imselend ) ) { + if ( d->hasIMSelection() && (last >= d->imselstart && first < d->imselend ) ) { TQRect highlight = TQRect( TQPoint( tix + ti.cursorToX( TQMAX( d->imselstart - first, 0 ) ), lineRect.top() ), TQPoint( tix + ti.cursorToX( TQMIN( d->imselend - first, last - first + 1 ) )-1, lineRect.bottom() ) ).normalize(); p->save(); @@ -2019,7 +2080,11 @@ void TQLineEdit::drawContents( TQPainter *p ) } // draw cursor - if ( d->cursorVisible && !supressCursor ) { + // + // Asian users regard IM selection text as cursor on candidate + // selection phase of input method, so ordinary cursor should be + // invisible if IM selection text exists. + if ( d->cursorVisible && !supressCursor && !d->hasIMSelection() ) { TQPoint from( topLeft.x() + cix, lineRect.top() ); TQPoint to = from + TQPoint( 0, lineRect.height() ); p->drawLine( from, to ); @@ -2134,6 +2199,10 @@ enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelect void TQLineEdit::contextMenuEvent( TQContextMenuEvent * e ) { #ifndef TQT_NO_POPUPMENU +#ifndef TQT_NO_IM + if ( d->composeMode() ) + return; +#endif d->separate(); TQPopupMenu *menu = createPopupMenu(); if (!menu) @@ -2187,6 +2256,13 @@ TQPopupMenu *TQLineEdit::createPopupMenu() + ACCEL_KEY( A ) #endif ); + +#ifndef TQT_NO_IM + TQInputContext *qic = getInputContext(); + if ( qic ) + qic->addMenusTo( popup ); +#endif + popup->setItemEnabled( id - IdUndo, d->isUndoAvailable() ); popup->setItemEnabled( id - IdRedo, d->isRedoAvailable() ); #ifndef TQT_NO_CLIPBOARD @@ -2320,7 +2396,7 @@ void TQLineEditPrivate::updateTextLayout() textLayout.endLine(0, 0, TQt::AlignLeft|TQt::SingleLine, &ascent); } -int TQLineEditPrivate::xToPos( int x, TQTextItem::CursorPosition betweenOrOn ) const +int TQLineEditPrivate::xToPosInternal( int x, TQTextItem::CursorPosition betweenOrOn ) const { x-= q->contentsRect().x() - hscroll + innerMargin; for ( int i = 0; i < textLayout.numItems(); ++i ) { @@ -2329,7 +2405,13 @@ int TQLineEditPrivate::xToPos( int x, TQTextItem::CursorPosition betweenOrOn ) c if ( x >= tir.left() && x <= tir.right() ) return ti.xToCursor( x - tir.x(), betweenOrOn ) + ti.from(); } - return x < 0 ? 0 : text.length(); + return x < 0 ? -1 : text.length(); +} + +int TQLineEditPrivate::xToPos( int x, TQTextItem::CursorPosition betweenOrOn ) const +{ + int pos = xToPosInternal( x, betweenOrOn ); + return ( pos < 0 ) ? 0 : pos; } @@ -2350,9 +2432,19 @@ TQRect TQLineEditPrivate::cursorRect() const void TQLineEditPrivate::updateMicroFocusHint() { + // To reduce redundant microfocus update notification, we remember + // the old rect and update the microfocus if actual update is + // required. The rect o is intentionally static because some + // notifyee requires the microfocus information as global update + // rather than per notifyee update to place shared widget around + // microfocus. + static TQRect o; if ( q->hasFocus() ) { - TQRect r = cursorRect(); - q->setMicroFocusHint( r.x(), r.y(), r.width(), r.height() ); + TQRect r = cursorRect(); + if ( o != r ) { + o = r; + q->setMicroFocusHint( r.x(), r.y(), r.width(), r.height() ); + } } } |