ScrollableLineEdit.cpp

Go to the documentation of this file.
00001 #include "ScrollableLineEdit.h"
00002 
00003 /**********************************************************************
00004 ** $Id: qt/src/widgets/qlineedit.cpp   2.3.2   edited 2001-10-19 $
00005 **
00006 ** Implementation of ScrollableLineEdit widget class
00007 **
00008 ** Created : 941011
00009 **
00010 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
00011 **
00012 ** This file is part of the widgets module of the Qt GUI Toolkit.
00013 **
00014 ** This file may be distributed under the terms of the Q Public License
00015 ** as defined by Trolltech AS of Norway and appearing in the file
00016 ** LICENSE.QPL included in the packaging of this file.
00017 **
00018 ** This file may be distributed and/or modified under the terms of the
00019 ** GNU General Public License version 2 as published by the Free Software
00020 ** Foundation and appearing in the file LICENSE.GPL included in the
00021 ** packaging of this file.
00022 **
00023 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00024 ** licenses may use this file in accordance with the Qt Commercial License
00025 ** Agreement provided with the Software.
00026 **
00027 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00028 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00029 **
00030 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00031 **   information about Qt Commercial License Agreements.
00032 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00033 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00034 **
00035 ** Contact info@trolltech.com if any conditions of this licensing are
00036 ** not clear to you.
00037 **
00038 **********************************************************************/
00039 
00040 #include "ScrollableLineEdit.h"
00041 #ifndef QT_NO_LINEEDIT
00042 #include "qpainter.h"
00043 #include "qdrawutil.h"
00044 #include "qfontmetrics.h"
00045 #include "qpixmap.h"
00046 #include "qclipboard.h"
00047 #include "qapplication.h"
00048 #include "qvalidator.h"
00049 #include "qdragobject.h"
00050 #include "qtimer.h"
00051 #include "qpopupmenu.h"
00052 #include "qstringlist.h"
00053 #include "qguardedptr.h"
00054 #include <ctype.h>
00055 
00056 
00057 struct ScrollableLineEditUndoItem
00058 {
00059     ScrollableLineEditUndoItem(){pos=0;};
00060     ScrollableLineEditUndoItem( const QString& s, int p )
00061     : str(s),pos(p){}
00062 #if defined(Q_FULL_TEMPLATE_INSTANTIATION)
00063     bool operator==( const ScrollableLineEditUndoItem& ) const { return FALSE; }
00064 #endif
00065     QString str;
00066     int pos;
00067 };
00068 
00069 enum {
00070     IdUndo,
00071     IdRedo,
00072 #ifndef QT_NO_CLIPBOARD
00073     IdCut,
00074     IdCopy,
00075     IdPaste,
00076 #endif
00077     IdClear,
00078     IdSelectAll
00079 };
00080 
00081 struct ScrollableLineEditPrivate {
00082     ScrollableLineEditPrivate( ScrollableLineEdit * l ):
00083     frame(TRUE), mode(ScrollableLineEdit::Normal),
00084     readonly(FALSE), validator( 0 ),
00085     pm(0), pmDirty( TRUE ),
00086     blinkTimer( l, "ScrollableLineEdit blink timer" ),
00087     dragTimer( l, "ScrollableLineEdit drag timer" ),
00088     dndTimer( l, "DnD Timer" ),
00089     inDoubleClick( FALSE ), offsetDirty( FALSE ),
00090     undo(TRUE), needundo( FALSE ), ignoreUndoWithDel( FALSE ),
00091     mousePressed( FALSE ), dnd_primed( FALSE ), passwordChar( '*' ) {}
00092 
00093     bool frame;
00094     ScrollableLineEdit::EchoMode mode;
00095     bool readonly;
00096     const QValidator * validator;
00097     QPixmap * pm;
00098     bool pmDirty;
00099     QTimer blinkTimer;
00100     QTimer dragTimer, dndTimer;
00101     QRect cursorRepaintRect;
00102     bool inDoubleClick;
00103     bool offsetDirty;
00104     QValueList<ScrollableLineEditUndoItem> undoList;
00105     QValueList<ScrollableLineEditUndoItem> redoList;
00106     bool undo;
00107     bool needundo;
00108     bool ignoreUndoWithDel;
00109     bool mousePressed;
00110     QPoint dnd_startpos;
00111     bool dnd_primed;
00112     QChar passwordChar;
00113 };
00114 
00115 
00116 // REVISED: arnt
00178 static const int scrollTime = 40;       // mark text scroll time
00179 
00180 
00191 ScrollableLineEdit::ScrollableLineEdit( QWidget *parent, const char *name )
00192     : QWidget( parent, name, WRepaintNoErase )
00193 {
00194     init();
00195 }
00196 
00197 
00209 ScrollableLineEdit::ScrollableLineEdit( const QString & contents,
00210               QWidget *parent, const char *name )
00211     : QWidget( parent, name )
00212 {
00213     init();
00214     setText( contents );
00215 }
00216 
00217 
00222 ScrollableLineEdit::~ScrollableLineEdit()
00223 {
00224     if ( d->pm )
00225     delete d->pm;
00226     delete d;
00227 }
00228 
00229 
00232 void ScrollableLineEdit::init()
00233 {
00234     d = new ScrollableLineEditPrivate( this );
00235     connect( &d->blinkTimer, SIGNAL(timeout()),
00236          this, SLOT(blinkSlot()) );
00237 //#ifndef QT_NO_DRAGANDDROP
00238 //    connect( &d->dragTimer, SIGNAL(timeout()),
00239 //         this, SLOT(dragScrollSlot()) );
00240 //    connect( &d->dndTimer, SIGNAL(timeout()),
00241 //         this, SLOT(doDrag()) );
00242 //#endif
00243     cursorPos = 0;
00244     offset = 0;
00245     maxLen = 32767;
00246     cursorOn = TRUE;
00247     markAnchor = 0;
00248     markDrag = 0;
00249     dragScrolling = FALSE;
00250     scrollingLeft = FALSE;
00251     tbuf = QString::fromLatin1("");
00252     setFocusPolicy( StrongFocus );
00253 #ifndef QT_NO_CURSOR
00254     setCursor( ibeamCursor );
00255 #endif
00256     setBackgroundMode( PaletteBase );
00257     setKeyCompression( TRUE );
00258     alignmentFlag = Qt::AlignLeft;
00259     setAcceptDrops( TRUE );
00260     //   Specifies that this widget can use more, but is able to survive on
00261     //   less, horizontal space; and is fixed vertically.
00262     setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
00263     ed = FALSE;
00264 }
00265 
00266 
00276 void ScrollableLineEdit::setText( const QString &text )
00277 {
00278     QString oldText( tbuf );
00279     tbuf = text;
00280     if ( (int)tbuf.length() > maxLen )
00281     tbuf.truncate( maxLen );
00282     offset    = 0;
00283     cursorPos = 0;
00284     markAnchor = 0;
00285     markDrag = 0;
00286     end( FALSE );
00287 #ifndef QT_NO_VALIDATOR
00288     if ( validator() )
00289     (void)validator()->validate( tbuf, cursorPos );
00290 #endif
00291     d->pmDirty = TRUE;
00292 
00293     update();
00294     if ( d->undo ) {
00295     d->undoList.clear();
00296     d->redoList.clear();
00297     d->needundo = TRUE;
00298      }
00299     if ( oldText != tbuf )
00300     emit textChanged( tbuf );
00301 }
00302 
00303 
00311 void ScrollableLineEdit::selectAll()
00312 {
00313     setSelection( 0, tbuf.length() );
00314     end( TRUE );
00315 }
00316 
00317 
00318 
00324 void ScrollableLineEdit::deselect()
00325 {
00326     setSelection( cursorPos, 0 );
00327 }
00328 
00329 
00335 QString ScrollableLineEdit::text() const
00336 {
00337     return tbuf;
00338 }
00339 
00340 
00341 
00349 QString ScrollableLineEdit::displayText() const
00350 {
00351     QString res;
00352 
00353     switch( echoMode() ) {
00354     case Normal:
00355     res = tbuf;
00356     break;
00357     case NoEcho:
00358     res = QString::fromLatin1("");
00359     break;
00360     case Password:
00361     res.fill( d->passwordChar, tbuf.length() );
00362     break;
00363     }
00364     return res;
00365 }
00366 
00367 
00368 
00376 bool ScrollableLineEdit::hasMarkedText() const
00377 {
00378     return markAnchor != markDrag;
00379 }
00380 
00388 QString ScrollableLineEdit::markedText() const
00389 {
00390     return tbuf.mid( minMark(), maxMark() - minMark() );
00391 }
00392 
00398 int ScrollableLineEdit::maxLength() const
00399 {
00400     return maxLen;
00401 }
00402 
00410 void ScrollableLineEdit::setMaxLength( int m )
00411 {
00412     maxLen = m;
00413     markAnchor = 0;
00414     markDrag = 0;
00415     if ( (int)tbuf.length() > maxLen ) {
00416     tbuf.truncate( maxLen );
00417     d->pmDirty = TRUE;
00418     }
00419     setCursorPosition( 0 );
00420     if ( d->pmDirty )
00421     update();
00422 }
00423 
00470 void ScrollableLineEdit::keyPressEvent( QKeyEvent *e )
00471 {
00472     if ( e->key() == Key_Enter || e->key() == Key_Return ) {
00473 #ifdef QT_NO_VALIDATOR
00474     emit returnPressed();
00475     e->ignore();
00476 #else
00477     const QValidator * v = validator();
00478     if ( !v || v->validate( tbuf, cursorPos ) == QValidator::Acceptable ) {
00479         emit returnPressed();
00480         e->ignore();
00481     }
00482     else if ( v ) {
00483         QString old( tbuf );
00484         v->fixup( tbuf );
00485         if ( old != tbuf ) {
00486         d->pmDirty = TRUE;
00487         if ( cursorPos > (int)tbuf.length() )
00488             cursorPos = tbuf.length();
00489         update();
00490         }
00491         if ( v->validate( tbuf, cursorPos ) == QValidator::Acceptable )
00492         emit returnPressed();
00493         e->ignore();
00494     }
00495 #endif
00496     return;
00497     }
00498     if ( !d->readonly ) {
00499     QString t = e->text();
00500     if ( !t.isEmpty() && (!e->ascii() || e->ascii()>=32) &&
00501          e->key() != Key_Delete &&
00502          e->key() != Key_Backspace ) {
00503         insert( t );
00504         return;
00505     }
00506     }
00507     bool needundo = d->needundo;
00508     d->needundo = TRUE;
00509     bool ignoreUndoWithDel = d->ignoreUndoWithDel;
00510     d->ignoreUndoWithDel = FALSE;
00511     int unknown = 0;
00512     if ( e->state() & ControlButton ) {
00513     switch ( e->key() ) {
00514     case Key_A:
00515         home( e->state() & ShiftButton );
00516         break;
00517     case Key_B:
00518         cursorLeft( e->state() & ShiftButton );
00519         break;
00520 #ifndef QT_NO_CLIPBOARD
00521     case Key_C:
00522         copy();
00523         break;
00524 #endif
00525     case Key_D:
00526         if ( !d->readonly ) {
00527         d->ignoreUndoWithDel = ignoreUndoWithDel;
00528         del();
00529         }
00530         break;
00531     case Key_E:
00532         end( e->state() & ShiftButton );
00533         break;
00534     case Key_F:
00535         cursorRight( e->state() & ShiftButton );
00536         break;
00537     case Key_H:
00538         if ( !d->readonly ) {
00539         d->ignoreUndoWithDel = ignoreUndoWithDel;
00540         backspace();
00541         }
00542         break;
00543     case Key_K:
00544         if ( !d->readonly && cursorPos < (int)tbuf.length() ) {
00545         QString t( tbuf );
00546         if ( d->undoList.isEmpty() || d->undoList.last().str != tbuf ) {
00547             d->undoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
00548             d->redoList.clear();
00549         }
00550         t.truncate( cursorPos );
00551         validateAndSet( t, cursorPos, cursorPos, cursorPos );
00552         }
00553         break;
00554 #ifndef QT_NO_CLIPBOARD
00555     case Key_V:
00556         if ( !d->readonly )
00557         insert( QApplication::clipboard()->text() );
00558         break;
00559     case Key_X:
00560         if ( !d->readonly && hasMarkedText() && echoMode() == Normal ) {
00561         copy();
00562         del();
00563         }
00564         break;
00565 #if defined (_WS_WIN_)
00566     case Key_Insert:
00567         copy();
00568         break;
00569 #endif
00570 #endif
00571     case Key_Right:
00572         cursorWordForward( e->state() & ShiftButton );
00573         break;
00574     case Key_Left:
00575         cursorWordBackward( e->state() & ShiftButton );
00576         break;
00577     case Key_Z:
00578         if ( !d->readonly )
00579         undoInternal();
00580         break;
00581     case Key_Y:
00582         if ( !d->readonly )
00583         redoInternal();
00584         break;
00585     default:
00586         unknown++;
00587     }
00588     } else {
00589     switch ( e->key() ) {
00590     case Key_Left:
00591         cursorLeft( e->state() & ShiftButton );
00592         break;
00593     case Key_Right:
00594         cursorRight( e->state() & ShiftButton );
00595         break;
00596     case Key_Backspace:
00597         if ( !d->readonly ) {
00598         d->ignoreUndoWithDel = ignoreUndoWithDel;
00599         backspace();
00600         }
00601         break;
00602     case Key_Home:
00603         home( e->state() & ShiftButton );
00604         break;
00605     case Key_End:
00606         end( e->state() & ShiftButton );
00607         break;
00608     case Key_Delete:
00609         if ( !d->readonly ) {
00610 #if defined (_WS_WIN_)
00611         if ( e->state() & ShiftButton ) {
00612             cut();
00613             break;
00614         }
00615 #endif
00616         d->ignoreUndoWithDel = ignoreUndoWithDel;
00617         del();
00618         }
00619         break;
00620 #if defined (_WS_WIN_)
00621     case Key_Insert:
00622         if ( !d->readonly && e->state() & ShiftButton )
00623         paste();
00624         else
00625         unknown++;
00626         break;
00627 #endif
00628     case Key_F14: // Undo key on Sun keyboards
00629         if ( !d->readonly )
00630         undoInternal();
00631         break;
00632 #ifndef QT_NO_CLIPBOARD
00633     case Key_F16: // Copy key on Sun keyboards
00634         copy();
00635         break;
00636     case Key_F18: // Paste key on Sun keyboards
00637         if ( !d->readonly )
00638         insert( QApplication::clipboard()->text() );
00639         break;
00640     case Key_F20: // Cut key on Sun keyboards
00641         if ( !d->readonly && hasMarkedText() && echoMode() == Normal ) {
00642         copy();
00643         del();
00644         }
00645         break;
00646 #endif
00647     default:
00648         unknown++;
00649     }
00650     }
00651 
00652     if ( unknown ) {                // unknown key
00653     d->needundo = needundo;
00654     e->ignore();
00655     return;
00656     }
00657 }
00658 
00662 void ScrollableLineEdit::focusInEvent( QFocusEvent * e)
00663 {
00664     d->pmDirty = TRUE;
00665     cursorOn = FALSE;
00666     blinkOn();
00667     if ( e->reason() == QFocusEvent::Tab )
00668     selectAll();
00669     d->pmDirty = TRUE;
00670     repaint( FALSE );
00671 }
00672 
00673 
00677 void ScrollableLineEdit::focusOutEvent( QFocusEvent * e )
00678 {
00679     if ( e->reason() != QFocusEvent::ActiveWindow
00680      && e->reason() != QFocusEvent::Popup )
00681     deselect();
00682     d->dragTimer.stop();
00683     if ( cursorOn )
00684     blinkSlot();
00685     d->pmDirty = TRUE;
00686     repaint( FALSE );
00687 }
00688 
00691 void ScrollableLineEdit::leaveEvent( QEvent * )
00692 {
00693 }
00694 
00695 
00699 void ScrollableLineEdit::paintEvent( QPaintEvent *e )
00700 {
00701     if ( d->offsetDirty )
00702     updateOffset();
00703     if ( !d->pm || d->pmDirty ) {
00704     makePixmap();
00705     if ( d->pm->isNull() ) {
00706         delete d->pm;
00707         d->pm = 0;
00708         return;
00709     }
00710 
00711     QPainter p( d->pm, this );
00712 
00713     const QColorGroup & g = colorGroup();
00714     QBrush bg = g.brush((isEnabled()) ? QColorGroup::Base :
00715                 QColorGroup::Background);
00716     QFontMetrics fm = fontMetrics();
00717     int markBegin = minMark();
00718     int markEnd = maxMark();
00719 
00720     p.fillRect( 0, 0, width(), height(), bg );
00721 
00722     QString display = displayText();
00723     QString before = display.mid( 0, markBegin );
00724     QString marked = display.mid( markBegin, markEnd - markBegin );
00725     QString after = display.mid( markEnd, display.length() );
00726 
00727     int y = (d->pm->height() + fm.height())/2 - fm.descent() - 1 ;
00728 
00729     int x = offset + 2;
00730     int w;
00731 
00732     w = fm.width( before );
00733     if ( x < d->pm->width() && x + w >= 0 ) {
00734         p.setPen( g.text() );
00735         p.drawText( x, y, before );
00736     }
00737     x += w;
00738 
00739     w = fm.width( marked );
00740     if ( x < d->pm->width() && x + w >= 0 ) {
00741         p.fillRect( x, y-fm.ascent()-1, w, fm.height()+2,
00742             g.brush( QColorGroup::Highlight ) );
00743         p.setPen( g.highlightedText() );
00744         p.drawText( x, y, marked );
00745     }
00746     x += w;
00747 
00748     w = fm.width( after );
00749     if ( x < d->pm->width() && x + w >= 0 ) {
00750         p.setPen( g.text() );
00751         p.drawText( x, y, after );
00752     }
00753     // ... x += w;
00754 
00755     p.setPen( g.text() );
00756 
00757     d->cursorRepaintRect.setTop( y + frameW() - fm.ascent() );
00758     d->cursorRepaintRect.setHeight( fm.height() );
00759     d->pmDirty = FALSE;
00760     }
00761 
00762     QPainter p( this );
00763 
00764     if ( frame() ) {
00765     style().drawPanel( &p, 0, 0, width(), height(), colorGroup(),
00766                TRUE, style().defaultFrameWidth() );
00767     p.drawPixmap( frameW(), frameW(), *d->pm );
00768     } else {
00769     p.drawPixmap( 0, 0, *d->pm );
00770     }
00771 
00772     if ( hasFocus() ) {
00773     d->cursorRepaintRect
00774         = QRect( offset + frameW() +
00775              fontMetrics().width( displayText().left( cursorPos ) ),
00776              d->cursorRepaintRect.top(),
00777              5, d->cursorRepaintRect.height() );
00778 
00779     int curYTop = d->cursorRepaintRect.y();
00780     int curYBot = d->cursorRepaintRect.bottom();
00781     int curXPos = d->cursorRepaintRect.x() + 2;
00782     if ( !d->readonly && cursorOn &&
00783          d->cursorRepaintRect.intersects( e->rect() ) ) {
00784         p.setPen( colorGroup().text() );
00785         p.drawLine( curXPos, curYTop, curXPos, curYBot );
00786         if ( style() != WindowsStyle ) {
00787         p.drawLine( curXPos - 2, curYTop, curXPos + 2, curYTop );
00788         p.drawLine( curXPos - 2, curYBot, curXPos + 2, curYBot );
00789         }
00790     }
00791     // Now is the optimal time to set this - all the repaint-minimization
00792     // then also reduces the number of calls to setMicroFocusHint().
00793     setMicroFocusHint( curXPos, curYTop, 1, curYBot-curYTop+1 );
00794     } else {
00795     delete d->pm;
00796     d->pm = 0;
00797     }
00798 
00799 }
00800 
00801 
00805 void ScrollableLineEdit::resizeEvent( QResizeEvent * )
00806 {
00807     delete d->pm;
00808     d->pm = 0;
00809     offset = 0;
00810     updateOffset();
00811 }
00812 
00813 
00816 bool ScrollableLineEdit::event( QEvent * e )
00817 {
00818     if ( e->type() == QEvent::AccelOverride && !d->readonly ) {
00819     QKeyEvent* ke = (QKeyEvent*) e;
00820     if ( ke->state() == NoButton ) {
00821         if ( ke->key() < Key_Escape ) {
00822         ke->accept();
00823         } else {
00824         switch ( ke->key() ) {
00825         case Key_Delete:
00826         case Key_Home:
00827         case Key_End:
00828         case Key_Backspace:
00829             ke->accept();
00830         default:
00831             break;
00832         }
00833         }
00834     } else if ( ke->state() & ControlButton ) {
00835         switch ( ke->key() ) {
00836 // Those are too frequently used for application functionality
00837 /*      case Key_A: 
00838         case Key_B:
00839         case Key_D:
00840         case Key_E:
00841         case Key_F:
00842         case Key_H:
00843         case Key_K:
00844 */
00845         case Key_C:
00846         case Key_V:
00847         case Key_X:     
00848         case Key_Y:
00849         case Key_Z:     
00850         case Key_Left:
00851         case Key_Right:
00852 #if defined (_WS_WIN_)
00853         case Key_Insert:
00854 #endif
00855         ke->accept();
00856         default:
00857         break;
00858         }
00859     }
00860     }
00861     return QWidget::event( e );
00862 }
00863 
00864 
00867 void ScrollableLineEdit::mousePressEvent( QMouseEvent *e )
00868 {
00869     d->dnd_startpos = e->pos();
00870     d->dnd_primed = FALSE;
00871 #ifndef QT_NO_POPUPMENU
00872     if ( e->button() == RightButton ) {
00873     QGuardedPtr<QPopupMenu> popup = new QPopupMenu( this );
00874     int id[ 7 ];
00875     id[ IdUndo ] = popup->insertItem( tr( "Undo" ) );
00876     id[ IdRedo ] = popup->insertItem( tr( "Redo" ) );
00877     popup->insertSeparator();
00878 #ifndef QT_NO_CLIPBOARD
00879     id[ IdCut ] = popup->insertItem( tr( "Cut" ) );
00880     id[ IdCopy ] = popup->insertItem( tr( "Copy" ) );
00881     id[ IdPaste ] = popup->insertItem( tr( "Paste" ) );
00882 #endif
00883     id[ IdClear ] = popup->insertItem( tr( "Clear" ) );
00884     popup->insertSeparator();
00885     id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) );
00886     popup->setItemEnabled( id[ IdUndo ],
00887                   !this->d->readonly && !this->d->undoList.isEmpty() );
00888     popup->setItemEnabled( id[ IdRedo ],
00889                   !this->d->readonly && !this->d->redoList.isEmpty() );
00890 #ifndef QT_NO_CLIPBOARD
00891     popup->setItemEnabled( id[ IdCut ],
00892                   !this->d->readonly && !this->d->readonly && hasMarkedText() );
00893     popup->setItemEnabled( id[ IdCopy ], hasMarkedText() );
00894     popup->setItemEnabled( id[ IdPaste ],
00895                   !this->d->readonly
00896                   && (bool)QApplication::clipboard()->text().length() );
00897 #endif
00898     popup->setItemEnabled( id[ IdClear ],
00899                   !this->d->readonly && (bool)text().length() );
00900     int allSelected = minMark() == 0 && maxMark() == (int)text().length();
00901     popup->setItemEnabled( id[ IdSelectAll ],
00902                   (bool)text().length() && !allSelected );
00903 
00904     int r = popup->exec( e->globalPos() );
00905     delete (QPopupMenu *) popup;
00906 
00907     if ( r == id[ IdUndo ] )
00908         undoInternal();
00909     else if ( r == id[ IdRedo ] )
00910         redoInternal();
00911 #ifndef QT_NO_CLIPBOARD
00912     else if ( r == id[ IdCut ] )
00913         cut();
00914     else if ( r == id[ IdCopy ] )
00915         copy();
00916     else if ( r == id[ IdPaste ] )
00917         paste();
00918 #endif
00919     else if ( r == id[ IdClear ] )
00920         clear();
00921     else if ( r == id[ IdSelectAll ] )
00922         selectAll();
00923     return;
00924     }
00925 #endif //QT_NO_POPUPMENU
00926     d->inDoubleClick = FALSE;
00927     int newCP = xPosToCursorPos( e->pos().x() );
00928     int m1 = minMark();
00929     int m2 = maxMark();
00930 #ifndef QT_NO_DRAGANDDROP
00931     if ( hasMarkedText() && echoMode() == Normal && !( e->state() & ShiftButton ) &&
00932      e->button() == LeftButton && m1 < newCP && m2 > newCP ) {
00933     d->dndTimer.start( QApplication::startDragTime(), TRUE );
00934     d->dnd_primed = TRUE;
00935     return;
00936     }
00937 #endif
00938 
00939     m1 = QMIN( m1, cursorPos );
00940     m2 = QMAX( m2, cursorPos );
00941     dragScrolling = FALSE;
00942     if ( e->state() & ShiftButton ) {
00943     newMark( newCP, FALSE );
00944     } else {
00945     markDrag = newCP;
00946     markAnchor = newCP;
00947     newMark( newCP, FALSE );
00948     }
00949     repaintArea( m1, m2 );
00950     d->mousePressed = TRUE;
00951 }
00952 
00953 #ifndef QT_NO_DRAGANDDROP
00954 
00955 /*
00956   \internal
00957 */
00958 
00959 //void ScrollableLineEdit::doDrag()
00960 //{
00961 //    d->dnd_primed = FALSE;
00962 //    QTextDrag *tdo = new QTextDrag( markedText(), this );
00963 //    tdo->drag();
00964 //}
00965 
00966 #endif // QT_NO_DRAGANDDROP
00967 
00970 void ScrollableLineEdit::mouseMoveEvent( QMouseEvent *e )
00971 {
00972 //#ifndef QT_NO_DRAGANDDROP
00973 //    if ( d->dndTimer.isActive() ) {
00974 //    d->dndTimer.stop();
00975 //    return;
00976 //    }
00977 //
00978 //    if ( d->dnd_primed ) {
00979 //    if ( ( d->dnd_startpos - e->pos() ).manhattanLength() > QApplication::startDragDistance() )
00980 //        doDrag();
00981 //    return;
00982 //    }
00983 //#endif
00984 
00985     if ( !(e->state() & LeftButton) )
00986     return;
00987 
00988     int margin = frame() ? frameW()*2 : 2;
00989 
00990     if ( e->pos().x() < margin || e->pos().x() > width() - margin ) {
00991     if ( !dragScrolling ) {
00992         dragScrolling = TRUE;
00993         scrollingLeft = e->pos().x() < margin;
00994         if ( scrollingLeft )
00995         newMark( xPosToCursorPos( 0 ), FALSE );
00996         else
00997         newMark( xPosToCursorPos( width() ), FALSE );
00998         d->dragTimer.start( scrollTime );
00999     }
01000     } else {
01001     dragScrolling = FALSE;
01002     int mousePos = xPosToCursorPos( e->pos().x() );
01003     int m1 = markDrag;
01004     newMark( mousePos, FALSE );
01005     repaintArea( m1, mousePos );
01006     }
01007 }
01008 
01011 void ScrollableLineEdit::mouseReleaseEvent( QMouseEvent * e )
01012 {
01013     dragScrolling = FALSE;
01014     d->dnd_primed = FALSE;
01015     if ( d->dndTimer.isActive() ) {
01016     d->dndTimer.stop();
01017     int ncp = xPosToCursorPos( e->pos().x() );
01018     setSelection( ncp, 0 );
01019     setCursorPosition( ncp );
01020     return;
01021     }
01022     if ( d->inDoubleClick ) {
01023     d->inDoubleClick = FALSE;
01024     return;
01025     }
01026 
01027     if ( !d->mousePressed )
01028     return;
01029     d->mousePressed = FALSE;
01030 
01031 #ifndef QT_NO_CLIPBOARD
01032 #if defined(_WS_X11_)
01033     copy();
01034 #endif
01035 
01036     if ( !d->readonly && e->button() == MidButton ) {
01037 #if defined(_WS_X11_)
01038     insert( QApplication::clipboard()->text() );
01039 #else
01040     if ( style() == MotifStyle )
01041         insert( QApplication::clipboard()->text() );
01042 #endif
01043     return;
01044     }
01045 #endif
01046 
01047     if ( e->button() != LeftButton )
01048     return;
01049 
01050     int margin = frame() ? frameW()*2 : 2;
01051     if ( !QRect( margin, margin,
01052          width() - 2*margin,
01053          height() - 2*margin ).contains( e->pos() ) )
01054     return;
01055 
01056     int mousePos = xPosToCursorPos( e->pos().x() );
01057     int m1 = markDrag;
01058     newMark( mousePos, FALSE );
01059     repaintArea( m1, mousePos );
01060 }
01061 
01062 
01065 void ScrollableLineEdit::mouseDoubleClickEvent( QMouseEvent * )
01066 {
01067     d->inDoubleClick = TRUE;
01068     dragScrolling = FALSE;
01069     if ( echoMode() == Password )
01070     selectAll();
01071     else
01072     markWord( cursorPos );
01073 }
01074 
01080 void ScrollableLineEdit::cursorLeft( bool mark, int steps )
01081 {
01082     cursorRight( mark, -steps );
01083 }
01084 
01090 void ScrollableLineEdit::cursorRight( bool mark, int steps )
01091 {
01092     int cp = cursorPos + steps;
01093     cp = QMAX( cp, 0 );
01094     cp = QMIN( cp, (int)tbuf.length() );
01095     if ( cp == cursorPos ) {
01096     if ( !mark )
01097         deselect();
01098     } else if ( mark ) {
01099     newMark( cp );
01100     blinkOn();
01101     } else {
01102     setCursorPosition( cp );
01103     setSelection( cp, 0 );
01104     }
01105 }
01106 
01114 void ScrollableLineEdit::backspace()
01115 {
01116     if ( hasMarkedText() ) {
01117     del();
01118     } else if ( cursorPos > 0 ) {
01119     if ( d->undo && d->needundo && !d->ignoreUndoWithDel ) {
01120         if ( d->undoList.isEmpty() || d->undoList.last().str != tbuf ) {
01121         d->undoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
01122         d->redoList.clear();
01123         }
01124     }
01125     cursorLeft( FALSE );
01126     del();
01127     }
01128 }
01129 
01137 void ScrollableLineEdit::del()
01138 {
01139     QString test( tbuf);
01140     d->ignoreUndoWithDel = TRUE;
01141     if ( d->undo && ( (d->needundo && !d->ignoreUndoWithDel) || hasMarkedText() ) ) {
01142     if ( d->undoList.isEmpty() || d->undoList.last().str != tbuf ) {
01143         d->undoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
01144         d->redoList.clear();
01145     }
01146     }
01147 
01148     if ( hasMarkedText() ) {
01149     test.remove( minMark(), maxMark() - minMark() );
01150     validateAndSet( test, minMark(), minMark(), minMark() );
01151     } else if ( cursorPos != (int)tbuf.length() ) {
01152     test.remove( cursorPos, 1 );
01153     validateAndSet( test, cursorPos, 0, 0 );
01154     }
01155 }
01156 
01163 void ScrollableLineEdit::home( bool mark )
01164 {
01165     cursorRight( mark, -cursorPos );
01166 }
01167 
01175 void ScrollableLineEdit::end( bool mark )
01176 {
01177     cursorRight( mark, tbuf.length()-cursorPos );
01178 }
01179 
01180 
01181 void ScrollableLineEdit::newMark( int pos, bool /*c*/ )
01182 {
01183     if ( markDrag != pos || cursorPos != pos )
01184     d->pmDirty = TRUE;
01185     markDrag = pos;
01186     setCursorPosition( pos );
01187 #ifndef QT_NO_CLIPBOARD
01188 #if defined(_WS_X11_)
01189     if ( c )
01190     copy();
01191 #endif
01192 #endif
01193 }
01194 
01195 
01196 void ScrollableLineEdit::markWord( int pos )
01197 {
01198     int i = pos - 1;
01199     while ( i >= 0 && tbuf[i].isPrint() && !tbuf[i].isSpace() )
01200     i--;
01201     i++;
01202     int newAnchor = i;
01203 
01204     i = pos;
01205     while ( tbuf[i].isPrint() && !tbuf[i].isSpace() )
01206     i++;
01207     if ( style() != MotifStyle ) {
01208     while( tbuf[i].isSpace() )
01209         i++;
01210     setCursorPosition( i );
01211     }
01212     int newDrag = i;
01213     setSelection( newAnchor, newDrag - newAnchor );
01214 
01215 #ifndef QT_NO_CLIPBOARD
01216 #if defined(_WS_X11_)
01217     copy();
01218 #endif
01219 #endif
01220 }
01221 
01222 #ifndef QT_NO_CLIPBOARD
01223 
01230 void ScrollableLineEdit::copy() const
01231 {
01232     QString t = markedText();
01233     if ( !t.isEmpty() && echoMode() == Normal ) {
01234     disconnect( QApplication::clipboard(), SIGNAL(dataChanged()), this, 0);
01235     QApplication::clipboard()->setText( t );
01236     connect( QApplication::clipboard(), SIGNAL(dataChanged()),
01237          this, SLOT(clipboardChanged()) );
01238     }
01239 }
01240 
01251 void ScrollableLineEdit::paste()
01252 {
01253     insert( QApplication::clipboard()->text() );
01254 }
01255 
01266 void ScrollableLineEdit::cut()
01267 {
01268     QString t = markedText();
01269     if ( !t.isEmpty() ) {
01270     copy();
01271     del();
01272     }
01273 }
01274 
01275 #endif
01276 
01282 void ScrollableLineEdit::setAlignment( int flag ){
01283     if ( flag == alignmentFlag )
01284     return;
01285     if ( flag == Qt::AlignRight ||
01286      flag == Qt::AlignCenter ||
01287      flag == Qt::AlignHCenter ||
01288      flag == Qt::AlignLeft ) {
01289     alignmentFlag = flag;
01290     updateOffset();
01291     update();
01292     }
01293 }
01294 
01302 int ScrollableLineEdit::alignment() const
01303 {
01304     return alignmentFlag;
01305 }
01306 
01312 void ScrollableLineEdit::clipboardChanged()
01313 {
01314 #if defined(_WS_X11_)
01315     disconnect( QApplication::clipboard(), SIGNAL(dataChanged()),
01316         this, SLOT(clipboardChanged()) );
01317     deselect();
01318 #endif
01319 }
01320 
01321 int ScrollableLineEdit::lastCharVisible() const
01322 {
01323     int tDispWidth = width() - (frameW()*2 + 4);
01324     return xPosToCursorPos( tDispWidth );
01325 }
01326 
01327 
01328 int ScrollableLineEdit::minMark() const
01329 {
01330     return markAnchor < markDrag ? markAnchor : markDrag;
01331 }
01332 
01333 
01334 int ScrollableLineEdit::maxMark() const
01335 {
01336     return markAnchor > markDrag ? markAnchor : markDrag;
01337 }
01338 
01339 
01340 
01350 void ScrollableLineEdit::setFrame( bool enable )
01351 {
01352     if ( d->frame == enable )
01353     return;
01354 
01355     d->frame = enable;
01356     d->pmDirty = TRUE;
01357     updateOffset();
01358     update();
01359 }
01360 
01361 
01370 bool ScrollableLineEdit::frame() const
01371 {
01372     return d ? d->frame : TRUE;
01373 }
01374 
01375 int ScrollableLineEdit::frameW() const
01376 {
01377     return frame() ? style().defaultFrameWidth() : 0;
01378 }
01379 
01399 void ScrollableLineEdit::setEchoMode( EchoMode mode )
01400 {
01401     if ( d->mode == mode )
01402     return;
01403 
01404     d->mode = mode;
01405     d->pmDirty = TRUE;
01406     updateOffset();
01407     update();
01408 }
01409 
01410 
01417 ScrollableLineEdit::EchoMode ScrollableLineEdit::echoMode() const
01418 {
01419     return d->mode;
01420 }
01421 
01429 void ScrollableLineEdit::setReadOnly( bool enable )
01430 {
01431     d->readonly = enable;
01432 }
01433 
01438 bool ScrollableLineEdit::isReadOnly() const
01439 {
01440     return d->readonly;
01441 }
01442 
01443 
01444 
01450 QSize ScrollableLineEdit::sizeHint() const
01451 {
01452     constPolish();
01453     QFontMetrics fm( font() );
01454     int h = fm.height();
01455     int w = fm.width( 'x' ) * 17; // "some"
01456     if ( frame() ) {
01457     h += 4 + frameW()*2;
01458     if ( style() == WindowsStyle && h < 26 )
01459         h = 22;
01460     return QSize( w + 4 + frameW()*2, h ).expandedTo( QApplication::globalStrut() );
01461     } else {
01462     return QSize( w + 4, h + 4 ).expandedTo( QApplication::globalStrut() );
01463     }
01464 }
01465 
01466 
01467 
01474 QSize ScrollableLineEdit::minimumSizeHint() const
01475 {
01476     constPolish();
01477     QFontMetrics fm( font() );
01478     int h = fm.height();
01479     int w = fm.maxWidth();
01480     if ( frame() ) {
01481     h += 4 + frameW()*2;
01482     if ( style() == WindowsStyle && h < 26 )
01483         h = 22;
01484     return QSize( w + 4 + frameW()*2, h );
01485     } else {
01486     return QSize( w + 4, h + 4 );
01487     }
01488 }
01489 
01490 
01491 
01494 QSizePolicy ScrollableLineEdit::sizePolicy() const
01495 {
01496     //### removeme 3.0
01497     return QWidget::sizePolicy();
01498 }
01499 
01500 
01511 void ScrollableLineEdit::setValidator( const QValidator * v )
01512 {
01513     d->validator = v;
01514 }
01515 
01523 const QValidator * ScrollableLineEdit::validator() const
01524 {
01525     return d ? d->validator : 0;
01526 }
01527 
01528 
01531 void ScrollableLineEdit::clearValidator()
01532 {
01533     setValidator( 0 );
01534 }
01535 
01536 #ifndef QT_NO_DRAGANDDROP
01537 
01540 void ScrollableLineEdit::dragEnterEvent( QDragEnterEvent *e )
01541 {
01542     if ( !d->readonly && QTextDrag::canDecode(e) )
01543     e->accept( rect() );
01544 }
01545 
01546 
01549 void ScrollableLineEdit::dropEvent( QDropEvent *e )
01550 {
01551     QString str;
01552     QCString plain = "plain";
01553 
01554     // try text/plain
01555     bool decoded = QTextDrag::decode(e, str, plain);
01556     // otherwise we'll accept any kind of text (like text/uri-list)
01557     if (! decoded) decoded = QTextDrag::decode(e, str);
01558 
01559     if ( !d->readonly && decoded) {
01560     if ( e->source() == this && hasMarkedText() )
01561         del();
01562     if ( !hasMarkedText() )
01563         setCursorPosition( xPosToCursorPos(e->pos().x()) );
01564     insert( str );
01565     e->accept();
01566     } else {
01567     e->ignore();
01568     }
01569 }
01570 
01571 #endif // QT_NO_DRAGANDDROP
01572 
01575 void ScrollableLineEdit::blinkSlot()
01576 {
01577     if ( hasFocus() || cursorOn ) {
01578     cursorOn = !cursorOn;
01579     if ( d->pm && !d->pmDirty && d->cursorRepaintRect.isValid() )
01580         repaint( d->cursorRepaintRect, FALSE );
01581     else
01582         repaint( FALSE );
01583     }
01584     if ( hasFocus() )
01585     d->blinkTimer.start( QApplication::cursorFlashTime()/2, TRUE );
01586     else
01587     d->blinkTimer.stop();
01588 }
01589 
01590 
01593 void ScrollableLineEdit::dragScrollSlot()
01594 {
01595     if ( !hasFocus() || !dragScrolling )
01596     d->dragTimer.stop();
01597     else if ( scrollingLeft )
01598     cursorLeft( TRUE );
01599     else
01600     cursorRight( TRUE );
01601 }
01602 
01603 
01615 bool ScrollableLineEdit::validateAndSet( const QString &newText, int newPos,
01616                 int newMarkAnchor, int newMarkDrag )
01617 {
01618     QString t( newText );
01619     for ( uint i=0; i<t.length(); i++ ) {
01620     if ( t[(int)i] < ' ' )  // unprintable/linefeed becomes space
01621         t[(int)i] = ' ';
01622     }
01623     t.truncate( maxLength() );
01624 #ifndef QT_NO_VALIDATOR
01625     const QValidator * v = validator();
01626 
01627     if ( v && v->validate( t, newPos ) == QValidator::Invalid &&
01628      v->validate( tbuf, cursorPos ) != QValidator::Invalid ) {
01629     return FALSE;
01630     }
01631 #endif
01632     bool tc = ( t != tbuf );
01633 
01634     // okay, it succeeded
01635     if ( newMarkDrag != markDrag ||
01636      newMarkAnchor != markAnchor ||
01637      newPos != cursorPos ||
01638      tc ) {
01639     int minP = QMIN( cursorPos, minMark() );
01640     int maxP = QMAX( cursorPos, maxMark() );
01641 
01642     cursorPos = newPos;
01643     markAnchor = newMarkAnchor;
01644     markDrag = newMarkDrag;
01645 
01646     minP = QMIN( minP, QMIN( cursorPos, minMark() ) );
01647     int i = 0;
01648     while( i < minP && t[i] == tbuf[i] )
01649         i++;
01650     minP = i;
01651 
01652     maxP = QMAX( maxP, QMAX( cursorPos, maxMark() ) );
01653     if ( fontMetrics().width( t ) < fontMetrics().width( tbuf ) )
01654         maxP = t.length();
01655     tbuf = t;
01656 
01657     if ( cursorPos < (int)text().length() && maxP < (int)text().length() )
01658         maxP = text().length();
01659 
01660     repaintArea( minP, maxP );
01661     }
01662     if ( tc ) {
01663     ed = TRUE;
01664     emit textChanged( tbuf );
01665     }
01666     return TRUE;
01667 }
01668 
01669 
01676 void ScrollableLineEdit::insert( const QString &newText )
01677 {
01678     QString t( newText );
01679     if ( t.isEmpty() && !hasMarkedText() )
01680     return;
01681 
01682     for ( int i=0; i<(int)t.length(); i++ )
01683     if ( t[i] < ' ' )  // unprintable/linefeed becomes space
01684         t[i] = ' ';
01685 
01686     QString test( tbuf );
01687     int cp = cursorPos;
01688     if ( d->undo && ( d->needundo || hasMarkedText() ) ) {
01689     if ( d->undoList.isEmpty() || d->undoList.last().str != tbuf ) {
01690         d->undoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
01691         d->redoList.clear();
01692         d->needundo = FALSE;
01693     }
01694     }
01695     if ( hasMarkedText() ) {
01696     test.remove( minMark(), maxMark() - minMark() );
01697     cp = minMark();
01698     }
01699     test.insert( cp, t );
01700     int ncp = QMIN( cp+t.length(), (uint)maxLength() );
01701     blinkOn();
01702     validateAndSet( test, ncp, ncp, ncp );
01703 }
01704 
01705 
01709 void ScrollableLineEdit::repaintArea( int from, int to )
01710 {
01711     QString buf = displayText();
01712 
01713     int a, b;
01714     if ( from < to ) {
01715     a = from;
01716     b = to;
01717     } else {
01718     a = to;
01719     b = from;
01720     }
01721 
01722     d->pmDirty = TRUE;
01723     int old = offset;
01724     if ( d->offsetDirty || cursorPos >= a && cursorPos <= b )
01725     updateOffset();
01726     if ( !d->pmDirty ) {
01727     return;
01728     } else if ( old != offset ) {
01729     repaint( FALSE );
01730     return;
01731     }
01732 
01733     QFontMetrics fm = fontMetrics();
01734     int x = fm.width( buf.left( a ) ) + offset - 2 + frameW();
01735     QRect r( x, 0, fm.width( buf.mid( a, b-a ) ) + 5, height() );
01736     r = r.intersect( rect() );
01737     if ( !r.isValid() )
01738     return;
01739     if ( b >= (int)buf.length() )
01740     r.setRight( width() );
01741     repaint( r, FALSE );
01742 }
01743 
01744 
01747 void ScrollableLineEdit::setEnabled( bool e )
01748 {
01749     d->pmDirty = TRUE;
01750     QWidget::setEnabled( e );
01751 }
01752 
01753 
01756 void ScrollableLineEdit::setFont( const QFont & f )
01757 {
01758     d->pmDirty     = TRUE;
01759     d->offsetDirty = TRUE;
01760     QWidget::setFont( f );
01761 }
01762 
01763 
01768 void ScrollableLineEdit::clear()
01769 {
01770     setText( QString::fromLatin1("") );
01771 }
01772 
01773 
01777 void ScrollableLineEdit::setSelection( int start, int length )
01778 {
01779     int b, e;
01780     b = QMIN( markAnchor, markDrag );
01781     e = QMAX( markAnchor, markDrag );
01782     b = QMIN( b, start );
01783     e = QMAX( e, start + length );
01784     markAnchor = start;
01785     markDrag = start + length;
01786     repaintArea( b, e );
01787 }
01788 
01789 
01793 void ScrollableLineEdit::setCursorPosition( int newPos )
01794 {
01795     if ( newPos == cursorPos )
01796     return;
01797     newPos = QMIN( newPos, (int)tbuf.length() );
01798     newPos = QMAX( newPos, 0 );
01799     int b, e;
01800     b = QMIN( newPos, cursorPos );
01801     e = QMAX( newPos, cursorPos );
01802     cursorPos = newPos;
01803     blinkOn();
01804     repaintArea( b, e );
01805 }
01806 
01807 
01811 int ScrollableLineEdit::cursorPosition() const
01812 {
01813     return cursorPos;
01814 }
01815 
01816 
01819 void ScrollableLineEdit::setPalette( const QPalette & p )
01820 {
01821     d->pmDirty = TRUE;
01822     QWidget::setPalette( p );
01823 }
01824 
01825 
01839 void ScrollableLineEdit::setEdited( bool on )
01840 {
01841     ed = on;
01842 }
01843 
01844 
01854 bool ScrollableLineEdit::edited() const
01855 {
01856     return ed;
01857 }
01858 
01864 void ScrollableLineEdit::cursorWordForward( bool mark )
01865 {
01866     int i = cursorPos;
01867     while ( i < (int) tbuf.length() && !tbuf[i].isSpace() )
01868     ++i;
01869     while ( i < (int) tbuf.length() && tbuf[i].isSpace() )
01870     ++i;
01871     cursorRight( mark, i - cursorPos );
01872 }
01873 
01874 
01880 void ScrollableLineEdit::cursorWordBackward( bool mark )
01881 {
01882     int i = cursorPos;
01883     while ( i > 0 && tbuf[i-1].isSpace() )
01884     --i;
01885     while ( i > 0 && !tbuf[i-1].isSpace() )
01886     --i;
01887     cursorLeft( mark, cursorPos - i );
01888 }
01889 
01890 
01891 void ScrollableLineEdit::updateOffset()
01892 { // must not call repaint() - paintEvent() calls this
01893     if ( !isVisible() ) {
01894     d->offsetDirty = TRUE;
01895     return;
01896     }
01897     d->offsetDirty = FALSE;
01898     makePixmap();
01899     QFontMetrics fm = fontMetrics();
01900     int textWidth = fm.width( displayText() )+4;
01901     int w = d->pm->width();
01902     int old = offset;
01903 
01904     if ( textWidth > w ) {
01905     // may need to scroll.
01906     QString dt = displayText();
01907     dt += QString::fromLatin1( "  " );
01908     dt = dt.left( cursorPos + 2 );
01909     if ( cursorPos < 3 )
01910         offset = 0;
01911     else if ( fm.width( dt.left( cursorPos - 2 ) ) + offset < 0 )
01912         offset = -fm.width( dt.left( cursorPos - 2 ) );
01913     else if ( fm.width( dt ) + offset > w )
01914         offset = w - fm.width( dt );
01915     } else {
01916     if ( textWidth < 5 ) {
01917         // nothing is to be drawn.  okay.
01918         textWidth = QMIN( 5, w );
01919     }
01920     if ( alignmentFlag == Qt::AlignRight ) {
01921         // right-aligned text, space for all of it
01922         offset = w - textWidth;
01923     } else if ( alignmentFlag == Qt::AlignCenter || alignmentFlag == Qt::AlignHCenter ) {
01924         // center-aligned text, space for all of it
01925         offset = (w - textWidth)/2;
01926     } else {
01927         // default: left-aligned, space for all of it
01928         offset = 0;
01929     }
01930     }
01931 
01932     if ( old == offset && !d->pmDirty )
01933     return;
01934 
01935     d->pmDirty = TRUE;
01936 }
01937 
01938 
01943 int ScrollableLineEdit::xPosToCursorPos( int goalx ) const
01944 {
01945     int x1, x2;
01946     x1 = offset;
01947     int i = 0;
01948     QFontMetrics fm = fontMetrics();
01949     QString s = displayText();
01950     goalx -= (frameW() + 2);
01951 
01952     while( i < (int) s.length() ) {
01953     x2 = x1 + fm.width( s[i] );
01954     if ( QABS( x1 - goalx ) < QABS( x2 - goalx ) )
01955         return i;
01956     i++;
01957     x1 = x2;
01958     }
01959     return i;
01960 }
01961 
01962 
01965 void ScrollableLineEdit::blinkOn()
01966 {
01967     if ( !hasFocus() )
01968     return;
01969 
01970     d->blinkTimer.start( cursorOn?QApplication::cursorFlashTime() / 2 : 0, TRUE );
01971     blinkSlot();
01972 }
01973 
01974 
01975 void ScrollableLineEdit::makePixmap() const
01976 {
01977     if ( d->pm )
01978     return;
01979 
01980     QSize s( width() - frameW()*2, height() - frameW()*2 );
01981     if ( s.width() < 0 )
01982     s.setWidth( 0 );
01983     if ( s.height() < 0 )
01984     s.setHeight( 0 );
01985     d->pm = new QPixmap( s );
01986     d->pmDirty = TRUE;
01987 }
01988 
01989 
01990 void ScrollableLineEdit::undoInternal()
01991 {
01992     if ( d->undoList.isEmpty() )
01993     return;
01994     d->undo = FALSE;
01995 
01996     d->redoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
01997     setText( d->undoList.last().str );
01998     setCursorPosition( d->undoList.last().pos );
01999     markAnchor = cursorPos;
02000     d->undoList.remove( d->undoList.fromLast() );
02001     if ( d->undoList.count() > 10 )
02002     d->undoList.remove( d->undoList.begin() );
02003     d->undo = TRUE;
02004     d->needundo = TRUE;
02005 }
02006 
02007 void ScrollableLineEdit::redoInternal()
02008 {
02009     if ( d->redoList.isEmpty() )
02010     return;
02011     d->undo = FALSE;
02012     d->undoList += ScrollableLineEditUndoItem(tbuf, cursorPos );
02013     setText( d->redoList.last().str );
02014     setCursorPosition( d->redoList.last().pos );
02015     markAnchor = cursorPos;
02016     d->redoList.remove( d->redoList.fromLast() );
02017     d->undo = TRUE;
02018     d->needundo = TRUE;
02019 }
02020 #endif
02021 
02022 
02023 #if defined(Q_INCOMPATIBLE_3_0_ADDONS)
02024 bool ScrollableLineEdit::getSelection( int *start, int *end )
02025 {
02026     if( !hasMarkedText() )
02027     return false;
02028 
02029     *start = minMark();
02030     *end = maxMark();
02031     return true;
02032 }
02033 
02034 void ScrollableLineEdit::setPasswordChar( QChar c )
02035 {
02036     d->passwordChar = c;
02037 }
02038 
02039 QChar ScrollableLineEdit::passwordChar() const
02040 {
02041     return d->passwordChar;
02042 }
02043 
02044 #endif
02045 
02046 // Added methods for toMOTko.
02047 void ScrollableLineEdit::scrollLeft() {
02048     int firstCharPos = xPosToCursorPos( 0 );
02049     setCursorPosition( firstCharPos /*- 1*/ );
02050 }
02051 
02052 void ScrollableLineEdit::scrollRight() {
02053     int lastCharPos = lastCharVisible();
02054     setCursorPosition( lastCharPos /*+ 1*/ );
02055 }
02056 
02057 void ScrollableLineEdit::keyReleaseEvent( QKeyEvent *e ) {
02058     if ( e->state() & ControlButton ) {
02059         switch ( e->key() ) {
02060 #ifndef QT_NO_CLIPBOARD
02061             case Key_C:
02062                 copy();
02063                 break;
02064             case Key_V:
02065                 if ( !d->readonly )
02066                     insert( QApplication::clipboard()->text() );
02067                 break;
02068             case Key_X:
02069                 if ( !d->readonly && hasMarkedText() && echoMode() == Normal ) {
02070                     copy();
02071                     del();
02072                 }
02073                 break;
02074 #endif
02075         }
02076     }
02077     QWidget::keyReleaseEvent( e );
02078 }

Generated on Sun Mar 1 17:30:47 2009 for toMOTko by  doxygen 1.5.6