util/src/gui/widgets/qlinecontrol.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qlinecontrol_p.h"
       
    43 
       
    44 #ifndef QT_NO_LINEEDIT
       
    45 
       
    46 #include "qabstractitemview.h"
       
    47 #include "qclipboard.h"
       
    48 #ifndef QT_NO_ACCESSIBILITY
       
    49 #include "qaccessible.h"
       
    50 #endif
       
    51 #ifndef QT_NO_IM
       
    52 #include "qinputcontext.h"
       
    53 #include "qlist.h"
       
    54 #endif
       
    55 #include "qapplication.h"
       
    56 #ifndef QT_NO_GRAPHICSVIEW
       
    57 #include "qgraphicssceneevent.h"
       
    58 #endif
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 /*!
       
    63     \internal
       
    64 
       
    65     Updates the display text based of the current edit text
       
    66     If the text has changed will emit displayTextChanged()
       
    67 */
       
    68 void QLineControl::updateDisplayText(bool forceUpdate)
       
    69 {
       
    70     QString orig = m_textLayout.text();
       
    71     QString str;
       
    72     if (m_echoMode == QLineEdit::NoEcho)
       
    73         str = QString::fromLatin1("");
       
    74     else
       
    75         str = m_text;
       
    76 
       
    77     if (m_echoMode == QLineEdit::Password || (m_echoMode == QLineEdit::PasswordEchoOnEdit
       
    78                 && !m_passwordEchoEditing))
       
    79         str.fill(m_passwordCharacter);
       
    80 
       
    81     // replace certain non-printable characters with spaces (to avoid
       
    82     // drawing boxes when using fonts that don't have glyphs for such
       
    83     // characters)
       
    84     QChar* uc = str.data();
       
    85     for (int i = 0; i < (int)str.length(); ++i) {
       
    86         if ((uc[i] < 0x20 && uc[i] != 0x09)
       
    87             || uc[i] == QChar::LineSeparator
       
    88             || uc[i] == QChar::ParagraphSeparator
       
    89             || uc[i] == QChar::ObjectReplacementCharacter)
       
    90             uc[i] = QChar(0x0020);
       
    91     }
       
    92 
       
    93     m_textLayout.setText(str);
       
    94 
       
    95     QTextOption option;
       
    96     option.setTextDirection(m_layoutDirection);
       
    97     option.setFlags(QTextOption::IncludeTrailingSpaces);
       
    98     m_textLayout.setTextOption(option);
       
    99 
       
   100     m_textLayout.beginLayout();
       
   101     QTextLine l = m_textLayout.createLine();
       
   102     m_textLayout.endLayout();
       
   103     m_ascent = qRound(l.ascent());
       
   104 
       
   105     if (str != orig || forceUpdate)
       
   106         emit displayTextChanged(str);
       
   107 }
       
   108 
       
   109 #ifndef QT_NO_CLIPBOARD
       
   110 /*!
       
   111     \internal
       
   112 
       
   113     Copies the currently selected text into the clipboard using the given
       
   114     \a mode.
       
   115   
       
   116     \note If the echo mode is set to a mode other than Normal then copy
       
   117     will not work.  This is to prevent using copy as a method of bypassing
       
   118     password features of the line control.
       
   119 */
       
   120 void QLineControl::copy(QClipboard::Mode mode) const
       
   121 {
       
   122     QString t = selectedText();
       
   123     if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) {
       
   124         disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
       
   125         QApplication::clipboard()->setText(t, mode);
       
   126         connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
       
   127                    this, SLOT(_q_clipboardChanged()));
       
   128     }
       
   129 }
       
   130 
       
   131 /*!
       
   132     \internal
       
   133 
       
   134     Inserts the text stored in the application clipboard into the line
       
   135     control.
       
   136 
       
   137     \sa insert()
       
   138 */
       
   139 void QLineControl::paste()
       
   140 {
       
   141     QString clip = QApplication::clipboard()->text(QClipboard::Clipboard);
       
   142     if (!clip.isEmpty() || hasSelectedText()) {
       
   143         separate(); //make it a separate undo/redo command
       
   144         insert(clip);
       
   145         separate();
       
   146     }
       
   147 }
       
   148 
       
   149 #endif // !QT_NO_CLIPBOARD
       
   150 
       
   151 /*!
       
   152     \internal
       
   153 
       
   154     Handles the behavior for the backspace key or function.
       
   155     Removes the current selection if there is a selection, otherwise
       
   156     removes the character prior to the cursor position.
       
   157 
       
   158     \sa del()
       
   159 */
       
   160 void QLineControl::backspace()
       
   161 {
       
   162     int priorState = m_undoState;
       
   163     if (hasSelectedText()) {
       
   164         removeSelectedText();
       
   165     } else if (m_cursor) {
       
   166             --m_cursor;
       
   167             if (m_maskData)
       
   168                 m_cursor = prevMaskBlank(m_cursor);
       
   169             QChar uc = m_text.at(m_cursor);
       
   170             if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
       
   171                 // second half of a surrogate, check if we have the first half as well,
       
   172                 // if yes delete both at once
       
   173                 uc = m_text.at(m_cursor - 1);
       
   174                 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
       
   175                     internalDelete(true);
       
   176                     --m_cursor;
       
   177                 }
       
   178             }
       
   179             internalDelete(true);
       
   180     }
       
   181     finishChange(priorState);
       
   182 }
       
   183 
       
   184 /*!
       
   185     \internal
       
   186 
       
   187     Handles the behavior for the delete key or function.
       
   188     Removes the current selection if there is a selection, otherwise
       
   189     removes the character after the cursor position.
       
   190 
       
   191     \sa del()
       
   192 */
       
   193 void QLineControl::del()
       
   194 {
       
   195     int priorState = m_undoState;
       
   196     if (hasSelectedText()) {
       
   197         removeSelectedText();
       
   198     } else {
       
   199         int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
       
   200         while (n--)
       
   201             internalDelete();
       
   202     }
       
   203     finishChange(priorState);
       
   204 }
       
   205 
       
   206 /*!
       
   207     \internal
       
   208 
       
   209     Inserts the given \a newText at the current cursor position.
       
   210     If there is any selected text it is removed prior to insertion of
       
   211     the new text.
       
   212 */
       
   213 void QLineControl::insert(const QString &newText)
       
   214 {
       
   215     int priorState = m_undoState;
       
   216     removeSelectedText();
       
   217     internalInsert(newText);
       
   218     finishChange(priorState);
       
   219 }
       
   220 
       
   221 /*!
       
   222     \internal
       
   223 
       
   224     Clears the line control text.
       
   225 */
       
   226 void QLineControl::clear()
       
   227 {
       
   228     int priorState = m_undoState;
       
   229     m_selstart = 0;
       
   230     m_selend = m_text.length();
       
   231     removeSelectedText();
       
   232     separate();
       
   233     finishChange(priorState, /*update*/false, /*edited*/false);
       
   234 }
       
   235 
       
   236 /*!
       
   237     \internal
       
   238 
       
   239     Sets \a length characters from the given \a start position as selected.
       
   240     The given \a start position must be within the current text for
       
   241     the line control.  If \a length characters cannot be selected, then
       
   242     the selection will extend to the end of the current text.
       
   243 */
       
   244 void QLineControl::setSelection(int start, int length)
       
   245 {
       
   246     if(start < 0 || start > (int)m_text.length()){
       
   247         qWarning("QLineControl::setSelection: Invalid start position");
       
   248         return;
       
   249     }
       
   250 
       
   251     if (length > 0) {
       
   252         if (start == m_selstart && start + length == m_selend)
       
   253             return;
       
   254         m_selstart = start;
       
   255         m_selend = qMin(start + length, (int)m_text.length());
       
   256         m_cursor = m_selend;
       
   257     } else {
       
   258         if (start == m_selend && start + length == m_selstart)
       
   259             return;
       
   260         m_selstart = qMax(start + length, 0);
       
   261         m_selend = start;
       
   262         m_cursor = m_selstart;
       
   263     }
       
   264     emit selectionChanged();
       
   265     emitCursorPositionChanged();
       
   266 }
       
   267 
       
   268 void QLineControl::_q_clipboardChanged()
       
   269 {
       
   270 }
       
   271 
       
   272 void QLineControl::_q_deleteSelected()
       
   273 {
       
   274     if (!hasSelectedText())
       
   275         return;
       
   276 
       
   277     int priorState = m_undoState;
       
   278     emit resetInputContext();
       
   279     removeSelectedText();
       
   280     separate();
       
   281     finishChange(priorState);
       
   282 }
       
   283 
       
   284 /*!
       
   285     \internal
       
   286 
       
   287     Initializes the line control with a starting text value of \a txt.
       
   288 */
       
   289 void QLineControl::init(const QString &txt)
       
   290 {
       
   291     m_text = txt;
       
   292     updateDisplayText();
       
   293     m_cursor = m_text.length();
       
   294 }
       
   295 
       
   296 /*!
       
   297     \internal
       
   298 
       
   299     Sets the password echo editing to \a editing.  If password echo editing
       
   300     is true, then the text of the password is displayed even if the echo
       
   301     mode is set to QLineEdit::PasswordEchoOnEdit.  Password echoing editing
       
   302     does not affect other echo modes.
       
   303 */
       
   304 void QLineControl::updatePasswordEchoEditing(bool editing)
       
   305 {
       
   306     m_passwordEchoEditing = editing;
       
   307     updateDisplayText();
       
   308 }
       
   309 
       
   310 /*!
       
   311     \internal
       
   312 
       
   313     Returns the cursor position of the given \a x pixel value in relation
       
   314     to the displayed text.  The given \a betweenOrOn specified what kind
       
   315     of cursor position is requested.
       
   316 */
       
   317 int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
       
   318 {
       
   319     return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
       
   320 }
       
   321 
       
   322 /*!
       
   323     \internal
       
   324 
       
   325     Returns the bounds of the current cursor, as defined as a
       
   326     between characters cursor.
       
   327 */
       
   328 QRect QLineControl::cursorRect() const
       
   329 {
       
   330     QTextLine l = m_textLayout.lineAt(0);
       
   331     int c = m_cursor;
       
   332     if (m_preeditCursor != -1)
       
   333         c += m_preeditCursor;
       
   334     int cix = qRound(l.cursorToX(c));
       
   335     int w = m_cursorWidth;
       
   336     int ch = l.height() + 1;
       
   337 
       
   338     return QRect(cix-5, 0, w+9, ch);
       
   339 }
       
   340 
       
   341 /*!
       
   342     \internal
       
   343 
       
   344     Fixes the current text so that it is valid given any set validators.
       
   345 
       
   346     Returns true if the text was changed.  Otherwise returns false.
       
   347 */
       
   348 bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable
       
   349 {
       
   350 #ifndef QT_NO_VALIDATOR
       
   351     if (m_validator) {
       
   352         QString textCopy = m_text;
       
   353         int cursorCopy = m_cursor;
       
   354         m_validator->fixup(textCopy);
       
   355         if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
       
   356             if (textCopy != m_text || cursorCopy != m_cursor)
       
   357                 internalSetText(textCopy, cursorCopy);
       
   358             return true;
       
   359         }
       
   360     }
       
   361 #endif
       
   362     return false;
       
   363 }
       
   364 
       
   365 /*!
       
   366     \internal
       
   367 
       
   368     Moves the cursor to the given position \a pos.   If \a mark is true will
       
   369     adjust the currently selected text.
       
   370 */
       
   371 void QLineControl::moveCursor(int pos, bool mark)
       
   372 {
       
   373     if (pos != m_cursor) {
       
   374         separate();
       
   375         if (m_maskData)
       
   376             pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
       
   377     }
       
   378     if (mark) {
       
   379         int anchor;
       
   380         if (m_selend > m_selstart && m_cursor == m_selstart)
       
   381             anchor = m_selend;
       
   382         else if (m_selend > m_selstart && m_cursor == m_selend)
       
   383             anchor = m_selstart;
       
   384         else
       
   385             anchor = m_cursor;
       
   386         m_selstart = qMin(anchor, pos);
       
   387         m_selend = qMax(anchor, pos);
       
   388         updateDisplayText();
       
   389     } else {
       
   390         internalDeselect();
       
   391     }
       
   392     m_cursor = pos;
       
   393     if (mark || m_selDirty) {
       
   394         m_selDirty = false;
       
   395         emit selectionChanged();
       
   396     }
       
   397     emitCursorPositionChanged();
       
   398 }
       
   399 
       
   400 /*!
       
   401     \internal
       
   402 
       
   403     Applies the given input method event \a event to the text of the line
       
   404     control
       
   405 */
       
   406 void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
       
   407 {
       
   408     int priorState = 0;
       
   409     bool isGettingInput = !event->commitString().isEmpty()
       
   410             || event->preeditString() != preeditAreaText()
       
   411             || event->replacementLength() > 0;
       
   412     bool cursorPositionChanged = false;
       
   413 
       
   414     if (isGettingInput) {
       
   415         // If any text is being input, remove selected text.
       
   416         priorState = m_undoState;
       
   417         removeSelectedText();
       
   418     }
       
   419 
       
   420 
       
   421     int c = m_cursor; // cursor position after insertion of commit string
       
   422     if (event->replacementStart() == 0)
       
   423         c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength());
       
   424 
       
   425     m_cursor += event->replacementStart();
       
   426 
       
   427     // insert commit string
       
   428     if (event->replacementLength()) {
       
   429         m_selstart = m_cursor;
       
   430         m_selend = m_selstart + event->replacementLength();
       
   431         removeSelectedText();
       
   432     }
       
   433     if (!event->commitString().isEmpty()) {
       
   434         insert(event->commitString());
       
   435         cursorPositionChanged = true;
       
   436     }
       
   437 
       
   438     m_cursor = qMin(c, m_text.length());
       
   439 
       
   440     for (int i = 0; i < event->attributes().size(); ++i) {
       
   441         const QInputMethodEvent::Attribute &a = event->attributes().at(i);
       
   442         if (a.type == QInputMethodEvent::Selection) {
       
   443             m_cursor = qBound(0, a.start + a.length, m_text.length());
       
   444             if (a.length) {
       
   445                 m_selstart = qMax(0, qMin(a.start, m_text.length()));
       
   446                 m_selend = m_cursor;
       
   447                 if (m_selend < m_selstart) {
       
   448                     qSwap(m_selstart, m_selend);
       
   449                 }
       
   450             } else {
       
   451                 m_selstart = m_selend = 0;
       
   452             }
       
   453             cursorPositionChanged = true;
       
   454         }
       
   455     }
       
   456 #ifndef QT_NO_IM
       
   457     setPreeditArea(m_cursor, event->preeditString());
       
   458 #endif //QT_NO_IM
       
   459     m_preeditCursor = event->preeditString().length();
       
   460     m_hideCursor = false;
       
   461     QList<QTextLayout::FormatRange> formats;
       
   462     for (int i = 0; i < event->attributes().size(); ++i) {
       
   463         const QInputMethodEvent::Attribute &a = event->attributes().at(i);
       
   464         if (a.type == QInputMethodEvent::Cursor) {
       
   465             m_preeditCursor = a.start;
       
   466             m_hideCursor = !a.length;
       
   467         } else if (a.type == QInputMethodEvent::TextFormat) {
       
   468             QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
       
   469             if (f.isValid()) {
       
   470                 QTextLayout::FormatRange o;
       
   471                 o.start = a.start + m_cursor;
       
   472                 o.length = a.length;
       
   473                 o.format = f;
       
   474                 formats.append(o);
       
   475             }
       
   476         }
       
   477     }
       
   478     m_textLayout.setAdditionalFormats(formats);
       
   479     updateDisplayText(/*force*/ true);
       
   480     if (cursorPositionChanged)
       
   481         emitCursorPositionChanged();
       
   482     if (isGettingInput)
       
   483         finishChange(priorState);
       
   484 }
       
   485 
       
   486 /*!
       
   487     \internal
       
   488 
       
   489     Draws the display text for the line control using the given 
       
   490     \a painter, \a clip, and \a offset.  Which aspects of the display text
       
   491     are drawn is specified by the given \a flags.
       
   492 
       
   493     If the flags contain DrawSelections, then the selection or input mask
       
   494     backgrounds and foregrounds will be applied before drawing the text.
       
   495 
       
   496     If the flags contain DrawCursor a cursor of the current cursorWidth()
       
   497     will be drawn after drawing the text.
       
   498 
       
   499     The display text will only be drawn if the flags contain DrawText
       
   500 */
       
   501 void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags)
       
   502 {
       
   503     QVector<QTextLayout::FormatRange> selections;
       
   504     if (flags & DrawSelections) {
       
   505         QTextLayout::FormatRange o;
       
   506         if (m_selstart < m_selend) {
       
   507             o.start = m_selstart;
       
   508             o.length = m_selend - m_selstart;
       
   509             o.format.setBackground(m_palette.brush(QPalette::Highlight));
       
   510             o.format.setForeground(m_palette.brush(QPalette::HighlightedText));
       
   511         } else {
       
   512             // mask selection
       
   513             if(!m_blinkPeriod || m_blinkStatus){
       
   514                 o.start = m_cursor;
       
   515                 o.length = 1;
       
   516                 o.format.setBackground(m_palette.brush(QPalette::Text));
       
   517                 o.format.setForeground(m_palette.brush(QPalette::Window));
       
   518             }
       
   519         }
       
   520         selections.append(o);
       
   521     }
       
   522 
       
   523     if (flags & DrawText)
       
   524         m_textLayout.draw(painter, offset, selections, clip);
       
   525 
       
   526     if (flags & DrawCursor){
       
   527         int cursor = m_cursor;
       
   528         if (m_preeditCursor != -1)
       
   529             cursor += m_preeditCursor;
       
   530         if(!m_blinkPeriod || m_blinkStatus)
       
   531             m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth);
       
   532     }
       
   533 }
       
   534 
       
   535 /*!
       
   536     \internal
       
   537 
       
   538     Sets the selection to cover the word at the given cursor position.
       
   539     The word boundries is defined by the behavior of QTextLayout::SkipWords
       
   540     cursor mode.
       
   541 */
       
   542 void QLineControl::selectWordAtPos(int cursor)
       
   543 {
       
   544     int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords);
       
   545     moveCursor(c, false);
       
   546     // ## text layout should support end of words.
       
   547     int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords);
       
   548     while (end > cursor && m_text[end-1].isSpace())
       
   549         --end;
       
   550     moveCursor(end, true);
       
   551 }
       
   552 
       
   553 /*!
       
   554     \internal
       
   555 
       
   556     Completes a change to the line control text.  If the change is not valid
       
   557     will undo the line control state back to the given \a validateFromState.
       
   558 
       
   559     If \a edited is true and the change is valid, will emit textEdited() in
       
   560     addition to textChanged().  Otherwise only emits textChanged() on a valid
       
   561     change.
       
   562 
       
   563     The \a update value is currently unused.
       
   564 */
       
   565 bool QLineControl::finishChange(int validateFromState, bool update, bool edited)
       
   566 {
       
   567     Q_UNUSED(update)
       
   568     bool lineDirty = m_selDirty;
       
   569     if (m_textDirty) {
       
   570         // do validation
       
   571         bool wasValidInput = m_validInput;
       
   572         m_validInput = true;
       
   573 #ifndef QT_NO_VALIDATOR
       
   574         if (m_validator) {
       
   575             m_validInput = false;
       
   576             QString textCopy = m_text;
       
   577             int cursorCopy = m_cursor;
       
   578             m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
       
   579             if (m_validInput) {
       
   580                 if (m_text != textCopy) {
       
   581                     internalSetText(textCopy, cursorCopy);
       
   582                     return true;
       
   583                 }
       
   584                 m_cursor = cursorCopy;
       
   585             }
       
   586         }
       
   587 #endif
       
   588         if (validateFromState >= 0 && wasValidInput && !m_validInput) {
       
   589             if (m_transactions.count())
       
   590                 return false;
       
   591             internalUndo(validateFromState);
       
   592             m_history.resize(m_undoState);
       
   593             if (m_modifiedState > m_undoState)
       
   594                 m_modifiedState = -1;
       
   595             m_validInput = true;
       
   596             m_textDirty = false;
       
   597         }
       
   598         updateDisplayText();
       
   599         lineDirty |= m_textDirty;
       
   600         if (m_textDirty) {
       
   601             m_textDirty = false;
       
   602             QString actualText = text();
       
   603             if (edited)
       
   604                 emit textEdited(actualText);
       
   605             emit textChanged(actualText);
       
   606         }
       
   607     }
       
   608     if (m_selDirty) {
       
   609         m_selDirty = false;
       
   610         emit selectionChanged();
       
   611     }
       
   612     emitCursorPositionChanged();
       
   613     return true;
       
   614 }
       
   615 
       
   616 /*!
       
   617     \internal
       
   618 
       
   619     An internal function for setting the text of the line control.
       
   620 */
       
   621 void QLineControl::internalSetText(const QString &txt, int pos, bool edited)
       
   622 {
       
   623     internalDeselect();
       
   624     emit resetInputContext();
       
   625     QString oldText = m_text;
       
   626     if (m_maskData) {
       
   627         m_text = maskString(0, txt, true);
       
   628         m_text += clearString(m_text.length(), m_maxLength - m_text.length());
       
   629     } else {
       
   630         m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
       
   631     }
       
   632     m_history.clear();
       
   633     m_modifiedState =  m_undoState = 0;
       
   634     m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
       
   635     m_textDirty = (oldText != m_text);
       
   636     finishChange(-1, true, edited);
       
   637 }
       
   638 
       
   639 
       
   640 /*!
       
   641     \internal
       
   642 
       
   643     Adds the given \a command to the undo history
       
   644     of the line control.  Does not apply the command.
       
   645 */
       
   646 void QLineControl::addCommand(const Command &cmd)
       
   647 {
       
   648     if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
       
   649         m_history.resize(m_undoState + 2);
       
   650         m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
       
   651     } else {
       
   652         m_history.resize(m_undoState + 1);
       
   653     }
       
   654     m_separator = false;
       
   655     m_history[m_undoState++] = cmd;
       
   656 }
       
   657 
       
   658 /*!
       
   659     \internal
       
   660 
       
   661     Inserts the given string \a s into the line
       
   662     control.
       
   663 
       
   664     Also adds the appropriate commands into the undo history.
       
   665     This function does not call finishChange(), and may leave the text
       
   666     in an invalid state.
       
   667 */
       
   668 void QLineControl::internalInsert(const QString &s)
       
   669 {
       
   670     if (hasSelectedText())
       
   671         addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
       
   672     if (m_maskData) {
       
   673         QString ms = maskString(m_cursor, s);
       
   674         for (int i = 0; i < (int) ms.length(); ++i) {
       
   675             addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
       
   676             addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
       
   677         }
       
   678         m_text.replace(m_cursor, ms.length(), ms);
       
   679         m_cursor += ms.length();
       
   680         m_cursor = nextMaskBlank(m_cursor);
       
   681         m_textDirty = true;
       
   682     } else {
       
   683         int remaining = m_maxLength - m_text.length();
       
   684         if (remaining != 0) {
       
   685             m_text.insert(m_cursor, s.left(remaining));
       
   686             for (int i = 0; i < (int) s.left(remaining).length(); ++i)
       
   687                addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
       
   688             m_textDirty = true;
       
   689         }
       
   690     }
       
   691 }
       
   692 
       
   693 /*!
       
   694     \internal
       
   695 
       
   696     deletes a single character from the current text.  If \a wasBackspace,
       
   697     the character prior to the cursor is removed.  Otherwise the character
       
   698     after the cursor is removed.
       
   699 
       
   700     Also adds the appropriate commands into the undo history.
       
   701     This function does not call finishChange(), and may leave the text
       
   702     in an invalid state.
       
   703 */
       
   704 void QLineControl::internalDelete(bool wasBackspace)
       
   705 {
       
   706     if (m_cursor < (int) m_text.length()) {
       
   707         if (hasSelectedText())
       
   708             addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
       
   709         addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
       
   710                    m_cursor, m_text.at(m_cursor), -1, -1));
       
   711         if (m_maskData) {
       
   712             m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
       
   713             addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
       
   714         } else {
       
   715             m_text.remove(m_cursor, 1);
       
   716         }
       
   717         m_textDirty = true;
       
   718     }
       
   719 }
       
   720 
       
   721 /*!
       
   722     \internal
       
   723 
       
   724     removes the currently selected text from the line control.
       
   725 
       
   726     Also adds the appropriate commands into the undo history.
       
   727     This function does not call finishChange(), and may leave the text
       
   728     in an invalid state.
       
   729 */
       
   730 void QLineControl::removeSelectedText()
       
   731 {
       
   732     if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
       
   733         separate();
       
   734         int i ;
       
   735         addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
       
   736         if (m_selstart <= m_cursor && m_cursor < m_selend) {
       
   737             // cursor is within the selection. Split up the commands
       
   738             // to be able to restore the correct cursor position
       
   739             for (i = m_cursor; i >= m_selstart; --i)
       
   740                 addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1));
       
   741             for (i = m_selend - 1; i > m_cursor; --i)
       
   742                 addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1));
       
   743         } else {
       
   744             for (i = m_selend-1; i >= m_selstart; --i)
       
   745                 addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
       
   746         }
       
   747         if (m_maskData) {
       
   748             m_text.replace(m_selstart, m_selend - m_selstart,  clearString(m_selstart, m_selend - m_selstart));
       
   749             for (int i = 0; i < m_selend - m_selstart; ++i)
       
   750                 addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1));
       
   751         } else {
       
   752             m_text.remove(m_selstart, m_selend - m_selstart);
       
   753         }
       
   754         if (m_cursor > m_selstart)
       
   755             m_cursor -= qMin(m_cursor, m_selend) - m_selstart;
       
   756         internalDeselect();
       
   757         m_textDirty = true;
       
   758     }
       
   759 }
       
   760 
       
   761 /*!
       
   762     \internal
       
   763 
       
   764     Parses the input mask specified by \a maskFields to generate
       
   765     the mask data used to handle input masks.
       
   766 */
       
   767 void QLineControl::parseInputMask(const QString &maskFields)
       
   768 {
       
   769     int delimiter = maskFields.indexOf(QLatin1Char(';'));
       
   770     if (maskFields.isEmpty() || delimiter == 0) {
       
   771         if (m_maskData) {
       
   772             delete [] m_maskData;
       
   773             m_maskData = 0;
       
   774             m_maxLength = 32767;
       
   775             internalSetText(QString());
       
   776         }
       
   777         return;
       
   778     }
       
   779 
       
   780     if (delimiter == -1) {
       
   781         m_blank = QLatin1Char(' ');
       
   782         m_inputMask = maskFields;
       
   783     } else {
       
   784         m_inputMask = maskFields.left(delimiter);
       
   785         m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
       
   786     }
       
   787 
       
   788     // calculate m_maxLength / m_maskData length
       
   789     m_maxLength = 0;
       
   790     QChar c = 0;
       
   791     for (int i=0; i<m_inputMask.length(); i++) {
       
   792         c = m_inputMask.at(i);
       
   793         if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
       
   794             m_maxLength++;
       
   795             continue;
       
   796         }
       
   797         if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
       
   798              c != QLatin1Char('<') && c != QLatin1Char('>') &&
       
   799              c != QLatin1Char('{') && c != QLatin1Char('}') &&
       
   800              c != QLatin1Char('[') && c != QLatin1Char(']'))
       
   801             m_maxLength++;
       
   802     }
       
   803 
       
   804     delete [] m_maskData;
       
   805     m_maskData = new MaskInputData[m_maxLength];
       
   806 
       
   807     MaskInputData::Casemode m = MaskInputData::NoCaseMode;
       
   808     c = 0;
       
   809     bool s;
       
   810     bool escape = false;
       
   811     int index = 0;
       
   812     for (int i = 0; i < m_inputMask.length(); i++) {
       
   813         c = m_inputMask.at(i);
       
   814         if (escape) {
       
   815             s = true;
       
   816             m_maskData[index].maskChar = c;
       
   817             m_maskData[index].separator = s;
       
   818             m_maskData[index].caseMode = m;
       
   819             index++;
       
   820             escape = false;
       
   821         } else if (c == QLatin1Char('<')) {
       
   822                 m = MaskInputData::Lower;
       
   823         } else if (c == QLatin1Char('>')) {
       
   824             m = MaskInputData::Upper;
       
   825         } else if (c == QLatin1Char('!')) {
       
   826             m = MaskInputData::NoCaseMode;
       
   827         } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
       
   828             switch (c.unicode()) {
       
   829             case 'A':
       
   830             case 'a':
       
   831             case 'N':
       
   832             case 'n':
       
   833             case 'X':
       
   834             case 'x':
       
   835             case '9':
       
   836             case '0':
       
   837             case 'D':
       
   838             case 'd':
       
   839             case '#':
       
   840             case 'H':
       
   841             case 'h':
       
   842             case 'B':
       
   843             case 'b':
       
   844                 s = false;
       
   845                 break;
       
   846             case '\\':
       
   847                 escape = true;
       
   848             default:
       
   849                 s = true;
       
   850                 break;
       
   851             }
       
   852 
       
   853             if (!escape) {
       
   854                 m_maskData[index].maskChar = c;
       
   855                 m_maskData[index].separator = s;
       
   856                 m_maskData[index].caseMode = m;
       
   857                 index++;
       
   858             }
       
   859         }
       
   860     }
       
   861     internalSetText(m_text);
       
   862 }
       
   863 
       
   864 
       
   865 /*!
       
   866     \internal
       
   867 
       
   868     checks if the key is valid compared to the inputMask
       
   869 */
       
   870 bool QLineControl::isValidInput(QChar key, QChar mask) const
       
   871 {
       
   872     switch (mask.unicode()) {
       
   873     case 'A':
       
   874         if (key.isLetter())
       
   875             return true;
       
   876         break;
       
   877     case 'a':
       
   878         if (key.isLetter() || key == m_blank)
       
   879             return true;
       
   880         break;
       
   881     case 'N':
       
   882         if (key.isLetterOrNumber())
       
   883             return true;
       
   884         break;
       
   885     case 'n':
       
   886         if (key.isLetterOrNumber() || key == m_blank)
       
   887             return true;
       
   888         break;
       
   889     case 'X':
       
   890         if (key.isPrint())
       
   891             return true;
       
   892         break;
       
   893     case 'x':
       
   894         if (key.isPrint() || key == m_blank)
       
   895             return true;
       
   896         break;
       
   897     case '9':
       
   898         if (key.isNumber())
       
   899             return true;
       
   900         break;
       
   901     case '0':
       
   902         if (key.isNumber() || key == m_blank)
       
   903             return true;
       
   904         break;
       
   905     case 'D':
       
   906         if (key.isNumber() && key.digitValue() > 0)
       
   907             return true;
       
   908         break;
       
   909     case 'd':
       
   910         if ((key.isNumber() && key.digitValue() > 0) || key == m_blank)
       
   911             return true;
       
   912         break;
       
   913     case '#':
       
   914         if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
       
   915             return true;
       
   916         break;
       
   917     case 'B':
       
   918         if (key == QLatin1Char('0') || key == QLatin1Char('1'))
       
   919             return true;
       
   920         break;
       
   921     case 'b':
       
   922         if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
       
   923             return true;
       
   924         break;
       
   925     case 'H':
       
   926         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
       
   927             return true;
       
   928         break;
       
   929     case 'h':
       
   930         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
       
   931             return true;
       
   932         break;
       
   933     default:
       
   934         break;
       
   935     }
       
   936     return false;
       
   937 }
       
   938 
       
   939 /*!
       
   940     \internal
       
   941 
       
   942     Returns true if the given text \a str is valid for any
       
   943     validator or input mask set for the line control.
       
   944 
       
   945     Otherwise returns false
       
   946 */
       
   947 bool QLineControl::hasAcceptableInput(const QString &str) const
       
   948 {
       
   949 #ifndef QT_NO_VALIDATOR
       
   950     QString textCopy = str;
       
   951     int cursorCopy = m_cursor;
       
   952     if (m_validator && m_validator->validate(textCopy, cursorCopy)
       
   953         != QValidator::Acceptable)
       
   954         return false;
       
   955 #endif
       
   956 
       
   957     if (!m_maskData)
       
   958         return true;
       
   959 
       
   960     if (str.length() != m_maxLength)
       
   961         return false;
       
   962 
       
   963     for (int i=0; i < m_maxLength; ++i) {
       
   964         if (m_maskData[i].separator) {
       
   965             if (str.at(i) != m_maskData[i].maskChar)
       
   966                 return false;
       
   967         } else {
       
   968             if (!isValidInput(str.at(i), m_maskData[i].maskChar))
       
   969                 return false;
       
   970         }
       
   971     }
       
   972     return true;
       
   973 }
       
   974 
       
   975 /*!
       
   976     \internal
       
   977 
       
   978     Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
       
   979     specifies from where characters should be gotten when a separator is met in \a str - true means
       
   980     that blanks will be used, false that previous input is used.
       
   981     Calling this when no inputMask is set is undefined.
       
   982 */
       
   983 QString QLineControl::maskString(uint pos, const QString &str, bool clear) const
       
   984 {
       
   985     if (pos >= (uint)m_maxLength)
       
   986         return QString::fromLatin1("");
       
   987 
       
   988     QString fill;
       
   989     fill = clear ? clearString(0, m_maxLength) : m_text;
       
   990 
       
   991     int strIndex = 0;
       
   992     QString s = QString::fromLatin1("");
       
   993     int i = pos;
       
   994     while (i < m_maxLength) {
       
   995         if (strIndex < str.length()) {
       
   996             if (m_maskData[i].separator) {
       
   997                 s += m_maskData[i].maskChar;
       
   998                 if (str[(int)strIndex] == m_maskData[i].maskChar)
       
   999                     strIndex++;
       
  1000                 ++i;
       
  1001             } else {
       
  1002                 if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
       
  1003                     switch (m_maskData[i].caseMode) {
       
  1004                     case MaskInputData::Upper:
       
  1005                         s += str[(int)strIndex].toUpper();
       
  1006                         break;
       
  1007                     case MaskInputData::Lower:
       
  1008                         s += str[(int)strIndex].toLower();
       
  1009                         break;
       
  1010                     default:
       
  1011                         s += str[(int)strIndex];
       
  1012                     }
       
  1013                     ++i;
       
  1014                 } else {
       
  1015                     // search for separator first
       
  1016                     int n = findInMask(i, true, true, str[(int)strIndex]);
       
  1017                     if (n != -1) {
       
  1018                         if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
       
  1019                             s += fill.mid(i, n-i+1);
       
  1020                             i = n + 1; // update i to find + 1
       
  1021                         }
       
  1022                     } else {
       
  1023                         // search for valid m_blank if not
       
  1024                         n = findInMask(i, true, false, str[(int)strIndex]);
       
  1025                         if (n != -1) {
       
  1026                             s += fill.mid(i, n-i);
       
  1027                             switch (m_maskData[n].caseMode) {
       
  1028                             case MaskInputData::Upper:
       
  1029                                 s += str[(int)strIndex].toUpper();
       
  1030                                 break;
       
  1031                             case MaskInputData::Lower:
       
  1032                                 s += str[(int)strIndex].toLower();
       
  1033                                 break;
       
  1034                             default:
       
  1035                                 s += str[(int)strIndex];
       
  1036                             }
       
  1037                             i = n + 1; // updates i to find + 1
       
  1038                         }
       
  1039                     }
       
  1040                 }
       
  1041                 ++strIndex;
       
  1042             }
       
  1043         } else
       
  1044             break;
       
  1045     }
       
  1046 
       
  1047     return s;
       
  1048 }
       
  1049 
       
  1050 
       
  1051 
       
  1052 /*!
       
  1053     \internal
       
  1054 
       
  1055     Returns a "cleared" string with only separators and blank chars.
       
  1056     Calling this when no inputMask is set is undefined.
       
  1057 */
       
  1058 QString QLineControl::clearString(uint pos, uint len) const
       
  1059 {
       
  1060     if (pos >= (uint)m_maxLength)
       
  1061         return QString();
       
  1062 
       
  1063     QString s;
       
  1064     int end = qMin((uint)m_maxLength, pos + len);
       
  1065     for (int i = pos; i < end; ++i)
       
  1066         if (m_maskData[i].separator)
       
  1067             s += m_maskData[i].maskChar;
       
  1068         else
       
  1069             s += m_blank;
       
  1070 
       
  1071     return s;
       
  1072 }
       
  1073 
       
  1074 /*!
       
  1075     \internal
       
  1076 
       
  1077     Strips blank parts of the input in a QLineControl when an inputMask is set,
       
  1078     separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
       
  1079 */
       
  1080 QString QLineControl::stripString(const QString &str) const
       
  1081 {
       
  1082     if (!m_maskData)
       
  1083         return str;
       
  1084 
       
  1085     QString s;
       
  1086     int end = qMin(m_maxLength, (int)str.length());
       
  1087     for (int i = 0; i < end; ++i)
       
  1088         if (m_maskData[i].separator)
       
  1089             s += m_maskData[i].maskChar;
       
  1090         else
       
  1091             if (str[i] != m_blank)
       
  1092                 s += str[i];
       
  1093 
       
  1094     return s;
       
  1095 }
       
  1096 
       
  1097 /*!
       
  1098     \internal
       
  1099     searches forward/backward in m_maskData for either a separator or a m_blank
       
  1100 */
       
  1101 int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
       
  1102 {
       
  1103     if (pos >= m_maxLength || pos < 0)
       
  1104         return -1;
       
  1105 
       
  1106     int end = forward ? m_maxLength : -1;
       
  1107     int step = forward ? 1 : -1;
       
  1108     int i = pos;
       
  1109 
       
  1110     while (i != end) {
       
  1111         if (findSeparator) {
       
  1112             if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar)
       
  1113                 return i;
       
  1114         } else {
       
  1115             if (!m_maskData[i].separator) {
       
  1116                 if (searchChar.isNull())
       
  1117                     return i;
       
  1118                 else if (isValidInput(searchChar, m_maskData[i].maskChar))
       
  1119                     return i;
       
  1120             }
       
  1121         }
       
  1122         i += step;
       
  1123     }
       
  1124     return -1;
       
  1125 }
       
  1126 
       
  1127 void QLineControl::internalUndo(int until)
       
  1128 {
       
  1129     if (!isUndoAvailable())
       
  1130         return;
       
  1131     internalDeselect();
       
  1132     while (m_undoState && m_undoState > until) {
       
  1133         Command& cmd = m_history[--m_undoState];
       
  1134         switch (cmd.type) {
       
  1135         case Insert:
       
  1136             m_text.remove(cmd.pos, 1);
       
  1137             m_cursor = cmd.pos;
       
  1138             break;
       
  1139         case SetSelection:
       
  1140             m_selstart = cmd.selStart;
       
  1141             m_selend = cmd.selEnd;
       
  1142             m_cursor = cmd.pos;
       
  1143             break;
       
  1144         case Remove:
       
  1145         case RemoveSelection:
       
  1146             m_text.insert(cmd.pos, cmd.uc);
       
  1147             m_cursor = cmd.pos + 1;
       
  1148             break;
       
  1149         case Delete:
       
  1150         case DeleteSelection:
       
  1151             m_text.insert(cmd.pos, cmd.uc);
       
  1152             m_cursor = cmd.pos;
       
  1153             break;
       
  1154         case Separator:
       
  1155             continue;
       
  1156         }
       
  1157         if (until < 0 && m_undoState) {
       
  1158             Command& next = m_history[m_undoState-1];
       
  1159             if (next.type != cmd.type && next.type < RemoveSelection
       
  1160                  && (cmd.type < RemoveSelection || next.type == Separator))
       
  1161                 break;
       
  1162         }
       
  1163     }
       
  1164     m_textDirty = true;
       
  1165     emitCursorPositionChanged();
       
  1166 }
       
  1167 
       
  1168 void QLineControl::internalRedo()
       
  1169 {
       
  1170     if (!isRedoAvailable())
       
  1171         return;
       
  1172     internalDeselect();
       
  1173     while (m_undoState < (int)m_history.size()) {
       
  1174         Command& cmd = m_history[m_undoState++];
       
  1175         switch (cmd.type) {
       
  1176         case Insert:
       
  1177             m_text.insert(cmd.pos, cmd.uc);
       
  1178             m_cursor = cmd.pos + 1;
       
  1179             break;
       
  1180         case SetSelection:
       
  1181             m_selstart = cmd.selStart;
       
  1182             m_selend = cmd.selEnd;
       
  1183             m_cursor = cmd.pos;
       
  1184             break;
       
  1185         case Remove:
       
  1186         case Delete:
       
  1187         case RemoveSelection:
       
  1188         case DeleteSelection:
       
  1189             m_text.remove(cmd.pos, 1);
       
  1190             m_selstart = cmd.selStart;
       
  1191             m_selend = cmd.selEnd;
       
  1192             m_cursor = cmd.pos;
       
  1193             break;
       
  1194         case Separator:
       
  1195             m_selstart = cmd.selStart;
       
  1196             m_selend = cmd.selEnd;
       
  1197             m_cursor = cmd.pos;
       
  1198             break;
       
  1199         }
       
  1200         if (m_undoState < (int)m_history.size()) {
       
  1201             Command& next = m_history[m_undoState];
       
  1202             if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
       
  1203                  && (next.type < RemoveSelection || cmd.type == Separator))
       
  1204                 break;
       
  1205         }
       
  1206     }
       
  1207     m_textDirty = true;
       
  1208     emitCursorPositionChanged();
       
  1209 }
       
  1210 
       
  1211 /*!
       
  1212     \internal
       
  1213 
       
  1214     If the current cursor position differs from the last emited cursor
       
  1215     position, emits cursorPositionChanged().
       
  1216 */
       
  1217 void QLineControl::emitCursorPositionChanged()
       
  1218 {
       
  1219     if (m_cursor != m_lastCursorPos) {
       
  1220         const int oldLast = m_lastCursorPos;
       
  1221         m_lastCursorPos = m_cursor;
       
  1222         cursorPositionChanged(oldLast, m_cursor);
       
  1223     }
       
  1224 }
       
  1225 
       
  1226 #ifndef QT_NO_COMPLETER
       
  1227 // iterating forward(dir=1)/backward(dir=-1) from the
       
  1228 // current row based. dir=0 indicates a new completion prefix was set.
       
  1229 bool QLineControl::advanceToEnabledItem(int dir)
       
  1230 {
       
  1231     int start = m_completer->currentRow();
       
  1232     if (start == -1)
       
  1233         return false;
       
  1234     int i = start + dir;
       
  1235     if (dir == 0) dir = 1;
       
  1236     do {
       
  1237         if (!m_completer->setCurrentRow(i)) {
       
  1238             if (!m_completer->wrapAround())
       
  1239                 break;
       
  1240             i = i > 0 ? 0 : m_completer->completionCount() - 1;
       
  1241         } else {
       
  1242             QModelIndex currentIndex = m_completer->currentIndex();
       
  1243             if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
       
  1244                 return true;
       
  1245             i += dir;
       
  1246         }
       
  1247     } while (i != start);
       
  1248 
       
  1249     m_completer->setCurrentRow(start); // restore
       
  1250     return false;
       
  1251 }
       
  1252 
       
  1253 void QLineControl::complete(int key)
       
  1254 {
       
  1255     if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal)
       
  1256         return;
       
  1257 
       
  1258     QString text = this->text();
       
  1259     if (m_completer->completionMode() == QCompleter::InlineCompletion) {
       
  1260         if (key == Qt::Key_Backspace)
       
  1261             return;
       
  1262         int n = 0;
       
  1263         if (key == Qt::Key_Up || key == Qt::Key_Down) {
       
  1264             if (textAfterSelection().length())
       
  1265                 return;
       
  1266             QString prefix = hasSelectedText() ? textBeforeSelection()
       
  1267                 : text;
       
  1268             if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0
       
  1269                 || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) {
       
  1270                 m_completer->setCompletionPrefix(prefix);
       
  1271             } else {
       
  1272                 n = (key == Qt::Key_Up) ? -1 : +1;
       
  1273             }
       
  1274         } else {
       
  1275             m_completer->setCompletionPrefix(text);
       
  1276         }
       
  1277         if (!advanceToEnabledItem(n))
       
  1278             return;
       
  1279     } else {
       
  1280 #ifndef QT_KEYPAD_NAVIGATION
       
  1281         if (text.isEmpty()) {
       
  1282             m_completer->popup()->hide();
       
  1283             return;
       
  1284         }
       
  1285 #endif
       
  1286         m_completer->setCompletionPrefix(text);
       
  1287     }
       
  1288 
       
  1289     m_completer->complete();
       
  1290 }
       
  1291 #endif
       
  1292 
       
  1293 void QLineControl::setCursorBlinkPeriod(int msec)
       
  1294 {
       
  1295     if (msec == m_blinkPeriod)
       
  1296         return;
       
  1297     if (m_blinkTimer) {
       
  1298         killTimer(m_blinkTimer);
       
  1299     }
       
  1300     if (msec) {
       
  1301         m_blinkTimer = startTimer(msec / 2);
       
  1302         m_blinkStatus = 1;
       
  1303     } else {
       
  1304         m_blinkTimer = 0;
       
  1305         if (m_blinkStatus == 1)
       
  1306             emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
       
  1307     }
       
  1308     m_blinkPeriod = msec;
       
  1309 }
       
  1310 
       
  1311 void QLineControl::timerEvent(QTimerEvent *event)
       
  1312 {
       
  1313     if (event->timerId() == m_blinkTimer) {
       
  1314         m_blinkStatus = !m_blinkStatus;
       
  1315         emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
       
  1316     } else if (event->timerId() == m_deleteAllTimer) {
       
  1317         killTimer(m_deleteAllTimer);
       
  1318         m_deleteAllTimer = 0;
       
  1319         clear();
       
  1320     } else if (event->timerId() == m_tripleClickTimer) {
       
  1321         killTimer(m_tripleClickTimer);
       
  1322         m_tripleClickTimer = 0;
       
  1323     }
       
  1324 }
       
  1325 
       
  1326 bool QLineControl::processEvent(QEvent* ev)
       
  1327 {
       
  1328 #ifdef QT_KEYPAD_NAVIGATION
       
  1329     if (QApplication::keypadNavigationEnabled()) {
       
  1330         if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) {
       
  1331             QKeyEvent *ke = (QKeyEvent *)ev;
       
  1332             if (ke->key() == Qt::Key_Back) {
       
  1333                 if (ke->isAutoRepeat()) {
       
  1334                     // Swallow it. We don't want back keys running amok.
       
  1335                     ke->accept();
       
  1336                     return true;
       
  1337                 }
       
  1338                 if ((ev->type() == QEvent::KeyRelease)
       
  1339                     && !isReadOnly()
       
  1340                     && m_deleteAllTimer) {
       
  1341                     killTimer(m_deleteAllTimer);
       
  1342                     m_deleteAllTimer = 0;
       
  1343                     backspace();
       
  1344                     ke->accept();
       
  1345                     return true;
       
  1346                 }
       
  1347             }
       
  1348         }
       
  1349     }
       
  1350 #endif
       
  1351     switch(ev->type()){
       
  1352 #ifndef QT_NO_GRAPHICSVIEW
       
  1353         case QEvent::GraphicsSceneMouseMove:
       
  1354         case QEvent::GraphicsSceneMouseRelease:
       
  1355         case QEvent::GraphicsSceneMousePress:{
       
  1356                QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
       
  1357                QMouseEvent* mouse = new QMouseEvent(ev->type(),
       
  1358                     gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
       
  1359                processMouseEvent(mouse); break;
       
  1360         }
       
  1361 #endif
       
  1362         case QEvent::MouseButtonPress:
       
  1363         case QEvent::MouseButtonRelease:
       
  1364         case QEvent::MouseButtonDblClick:
       
  1365         case QEvent::MouseMove:
       
  1366             processMouseEvent(static_cast<QMouseEvent*>(ev)); break;
       
  1367         case QEvent::KeyPress:
       
  1368         case QEvent::KeyRelease:
       
  1369             processKeyEvent(static_cast<QKeyEvent*>(ev)); break;
       
  1370         case QEvent::InputMethod:
       
  1371             processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break;
       
  1372 #ifndef QT_NO_SHORTCUT
       
  1373         case QEvent::ShortcutOverride:{
       
  1374             if (isReadOnly())
       
  1375                 return false;
       
  1376             QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
       
  1377             if (ke == QKeySequence::Copy
       
  1378                 || ke == QKeySequence::Paste
       
  1379                 || ke == QKeySequence::Cut
       
  1380                 || ke == QKeySequence::Redo
       
  1381                 || ke == QKeySequence::Undo
       
  1382                 || ke == QKeySequence::MoveToNextWord
       
  1383                 || ke == QKeySequence::MoveToPreviousWord
       
  1384                 || ke == QKeySequence::MoveToStartOfDocument
       
  1385                 || ke == QKeySequence::MoveToEndOfDocument
       
  1386                 || ke == QKeySequence::SelectNextWord
       
  1387                 || ke == QKeySequence::SelectPreviousWord
       
  1388                 || ke == QKeySequence::SelectStartOfLine
       
  1389                 || ke == QKeySequence::SelectEndOfLine
       
  1390                 || ke == QKeySequence::SelectStartOfBlock
       
  1391                 || ke == QKeySequence::SelectEndOfBlock
       
  1392                 || ke == QKeySequence::SelectStartOfDocument
       
  1393                 || ke == QKeySequence::SelectAll
       
  1394                 || ke == QKeySequence::SelectEndOfDocument) {
       
  1395                 ke->accept();
       
  1396             } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
       
  1397                        || ke->modifiers() == Qt::KeypadModifier) {
       
  1398                 if (ke->key() < Qt::Key_Escape) {
       
  1399                     ke->accept();
       
  1400                 } else {
       
  1401                     switch (ke->key()) {
       
  1402                     case Qt::Key_Delete:
       
  1403                     case Qt::Key_Home:
       
  1404                     case Qt::Key_End:
       
  1405                     case Qt::Key_Backspace:
       
  1406                     case Qt::Key_Left:
       
  1407                     case Qt::Key_Right:
       
  1408                         ke->accept();
       
  1409                     default:
       
  1410                         break;
       
  1411                     }
       
  1412                 }
       
  1413             }
       
  1414         }
       
  1415 #endif
       
  1416         default:
       
  1417             return false;
       
  1418     }
       
  1419     return true;
       
  1420 }
       
  1421 
       
  1422 void QLineControl::processMouseEvent(QMouseEvent* ev)
       
  1423 {
       
  1424 
       
  1425     switch (ev->type()) {
       
  1426         case QEvent::GraphicsSceneMousePress:
       
  1427         case QEvent::MouseButtonPress:{
       
  1428             if (m_tripleClickTimer
       
  1429                 && (ev->pos() - m_tripleClick).manhattanLength()
       
  1430                     < QApplication::startDragDistance()) {
       
  1431                 selectAll();
       
  1432                 return;
       
  1433             }
       
  1434             if (ev->button() == Qt::RightButton)
       
  1435                 return;
       
  1436 
       
  1437             bool mark = ev->modifiers() & Qt::ShiftModifier;
       
  1438             int cursor = xToPos(ev->pos().x());
       
  1439             moveCursor(cursor, mark);
       
  1440             break;
       
  1441         }
       
  1442         case QEvent::MouseButtonDblClick:
       
  1443             if (ev->button() == Qt::LeftButton) {
       
  1444                 selectWordAtPos(xToPos(ev->pos().x()));
       
  1445                 if (m_tripleClickTimer)
       
  1446                     killTimer(m_tripleClickTimer);
       
  1447                 m_tripleClickTimer = startTimer(QApplication::doubleClickInterval());
       
  1448                 m_tripleClick = ev->pos();
       
  1449             }
       
  1450             break;
       
  1451         case QEvent::GraphicsSceneMouseRelease:
       
  1452         case QEvent::MouseButtonRelease:
       
  1453 #ifndef QT_NO_CLIPBOARD
       
  1454             if (QApplication::clipboard()->supportsSelection()) {
       
  1455                 if (ev->button() == Qt::LeftButton) {
       
  1456                     copy(QClipboard::Selection);
       
  1457                 } else if (!isReadOnly() && ev->button() == Qt::MidButton) {
       
  1458                     deselect();
       
  1459                     insert(QApplication::clipboard()->text(QClipboard::Selection));
       
  1460                 }
       
  1461             }
       
  1462 #endif
       
  1463             break;
       
  1464         case QEvent::GraphicsSceneMouseMove:
       
  1465         case QEvent::MouseMove:
       
  1466             if (ev->buttons() & Qt::LeftButton) {
       
  1467                 moveCursor(xToPos(ev->pos().x()), true);
       
  1468             }
       
  1469             break;
       
  1470         default:
       
  1471             break;
       
  1472     }
       
  1473 }
       
  1474 
       
  1475 void QLineControl::processKeyEvent(QKeyEvent* event)
       
  1476 {
       
  1477     bool inlineCompletionAccepted = false;
       
  1478 
       
  1479 #ifndef QT_NO_COMPLETER
       
  1480     if (m_completer) {
       
  1481         QCompleter::CompletionMode completionMode = m_completer->completionMode();
       
  1482         if ((completionMode == QCompleter::PopupCompletion
       
  1483              || completionMode == QCompleter::UnfilteredPopupCompletion)
       
  1484             && m_completer->popup()
       
  1485             && m_completer->popup()->isVisible()) {
       
  1486             // The following keys are forwarded by the completer to the widget
       
  1487             // Ignoring the events lets the completer provide suitable default behavior
       
  1488             switch (event->key()) {
       
  1489             case Qt::Key_Escape:
       
  1490                 event->ignore();
       
  1491                 return;
       
  1492             case Qt::Key_Enter:
       
  1493             case Qt::Key_Return:
       
  1494             case Qt::Key_F4:
       
  1495 #ifdef QT_KEYPAD_NAVIGATION
       
  1496             case Qt::Key_Select:
       
  1497                 if (!QApplication::keypadNavigationEnabled())
       
  1498                     break;
       
  1499 #endif
       
  1500                 m_completer->popup()->hide(); // just hide. will end up propagating to parent
       
  1501             default:
       
  1502                 break; // normal key processing
       
  1503             }
       
  1504         } else if (completionMode == QCompleter::InlineCompletion) {
       
  1505             switch (event->key()) {
       
  1506             case Qt::Key_Enter:
       
  1507             case Qt::Key_Return:
       
  1508             case Qt::Key_F4:
       
  1509 #ifdef QT_KEYPAD_NAVIGATION
       
  1510             case Qt::Key_Select:
       
  1511                 if (!QApplication::keypadNavigationEnabled())
       
  1512                     break;
       
  1513 #endif
       
  1514                 if (!m_completer->currentCompletion().isEmpty() && hasSelectedText()
       
  1515                     && textAfterSelection().isEmpty()) {
       
  1516                     setText(m_completer->currentCompletion());
       
  1517                     inlineCompletionAccepted = true;
       
  1518                 }
       
  1519             default:
       
  1520                 break; // normal key processing
       
  1521             }
       
  1522         }
       
  1523     }
       
  1524 #endif // QT_NO_COMPLETER
       
  1525 
       
  1526     if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
       
  1527         if (hasAcceptableInput() || fixup()) {
       
  1528             emit accepted();
       
  1529             emit editingFinished();
       
  1530         }
       
  1531         if (inlineCompletionAccepted)
       
  1532             event->accept();
       
  1533         else
       
  1534             event->ignore();
       
  1535         return;
       
  1536     }
       
  1537 
       
  1538     if (echoMode() == QLineEdit::PasswordEchoOnEdit
       
  1539         && !passwordEchoEditing()
       
  1540         && !isReadOnly()
       
  1541         && !event->text().isEmpty()
       
  1542 #ifdef QT_KEYPAD_NAVIGATION
       
  1543         && event->key() != Qt::Key_Select
       
  1544         && event->key() != Qt::Key_Up
       
  1545         && event->key() != Qt::Key_Down
       
  1546         && event->key() != Qt::Key_Back
       
  1547 #endif
       
  1548         && !(event->modifiers() & Qt::ControlModifier)) {
       
  1549         // Clear the edit and reset to normal echo mode while editing; the
       
  1550         // echo mode switches back when the edit loses focus
       
  1551         // ### resets current content.  dubious code; you can
       
  1552         // navigate with keys up, down, back, and select(?), but if you press
       
  1553         // "left" or "right" it clears?
       
  1554         updatePasswordEchoEditing(true);
       
  1555         clear();
       
  1556     }
       
  1557 
       
  1558     bool unknown = false;
       
  1559 
       
  1560     if (false) {
       
  1561     }
       
  1562 #ifndef QT_NO_SHORTCUT
       
  1563     else if (event == QKeySequence::Undo) {
       
  1564         if (!isReadOnly())
       
  1565             undo();
       
  1566     }
       
  1567     else if (event == QKeySequence::Redo) {
       
  1568         if (!isReadOnly())
       
  1569             redo();
       
  1570     }
       
  1571     else if (event == QKeySequence::SelectAll) {
       
  1572         selectAll();
       
  1573     }
       
  1574 #ifndef QT_NO_CLIPBOARD
       
  1575     else if (event == QKeySequence::Copy) {
       
  1576         copy();
       
  1577     }
       
  1578     else if (event == QKeySequence::Paste) {
       
  1579         if (!isReadOnly())
       
  1580             paste();
       
  1581     }
       
  1582     else if (event == QKeySequence::Cut) {
       
  1583         if (!isReadOnly()) {
       
  1584             copy();
       
  1585             del();
       
  1586         }
       
  1587     }
       
  1588     else if (event == QKeySequence::DeleteEndOfLine) {
       
  1589         if (!isReadOnly()) {
       
  1590             setSelection(cursor(), end());
       
  1591             copy();
       
  1592             del();
       
  1593         }
       
  1594     }
       
  1595 #endif //QT_NO_CLIPBOARD
       
  1596     else if (event == QKeySequence::MoveToStartOfLine || event == QKeySequence::MoveToStartOfBlock) {
       
  1597         home(0);
       
  1598     }
       
  1599     else if (event == QKeySequence::MoveToEndOfLine || event == QKeySequence::MoveToEndOfBlock) {
       
  1600         end(0);
       
  1601     }
       
  1602     else if (event == QKeySequence::SelectStartOfLine || event == QKeySequence::SelectStartOfBlock) {
       
  1603         home(1);
       
  1604     }
       
  1605     else if (event == QKeySequence::SelectEndOfLine || event == QKeySequence::SelectEndOfBlock) {
       
  1606         end(1);
       
  1607     }
       
  1608     else if (event == QKeySequence::MoveToNextChar) {
       
  1609 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
       
  1610         if (hasSelectedText()) {
       
  1611 #else
       
  1612         if (hasSelectedText() && m_completer
       
  1613             && m_completer->completionMode() == QCompleter::InlineCompletion) {
       
  1614 #endif
       
  1615             moveCursor(selectionEnd(), false);
       
  1616         } else {
       
  1617             cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
       
  1618         }
       
  1619     }
       
  1620     else if (event == QKeySequence::SelectNextChar) {
       
  1621         cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
       
  1622     }
       
  1623     else if (event == QKeySequence::MoveToPreviousChar) {
       
  1624 #if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
       
  1625         if (hasSelectedText()) {
       
  1626 #else
       
  1627         if (hasSelectedText() && m_completer
       
  1628             && m_completer->completionMode() == QCompleter::InlineCompletion) {
       
  1629 #endif
       
  1630             moveCursor(selectionStart(), false);
       
  1631         } else {
       
  1632             cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1);
       
  1633         }
       
  1634     }
       
  1635     else if (event == QKeySequence::SelectPreviousChar) {
       
  1636         cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1);
       
  1637     }
       
  1638     else if (event == QKeySequence::MoveToNextWord) {
       
  1639         if (echoMode() == QLineEdit::Normal)
       
  1640             layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
       
  1641         else
       
  1642             layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
       
  1643     }
       
  1644     else if (event == QKeySequence::MoveToPreviousWord) {
       
  1645         if (echoMode() == QLineEdit::Normal)
       
  1646             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
       
  1647         else if (!isReadOnly()) {
       
  1648             layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
       
  1649         }
       
  1650     }
       
  1651     else if (event == QKeySequence::SelectNextWord) {
       
  1652         if (echoMode() == QLineEdit::Normal)
       
  1653             layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
       
  1654         else
       
  1655             layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
       
  1656     }
       
  1657     else if (event == QKeySequence::SelectPreviousWord) {
       
  1658         if (echoMode() == QLineEdit::Normal)
       
  1659             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
       
  1660         else
       
  1661             layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
       
  1662     }
       
  1663     else if (event == QKeySequence::Delete) {
       
  1664         if (!isReadOnly())
       
  1665             del();
       
  1666     }
       
  1667     else if (event == QKeySequence::DeleteEndOfWord) {
       
  1668         if (!isReadOnly()) {
       
  1669             cursorWordForward(true);
       
  1670             del();
       
  1671         }
       
  1672     }
       
  1673     else if (event == QKeySequence::DeleteStartOfWord) {
       
  1674         if (!isReadOnly()) {
       
  1675             cursorWordBackward(true);
       
  1676             del();
       
  1677         }
       
  1678     }
       
  1679 #endif // QT_NO_SHORTCUT
       
  1680     else {
       
  1681         bool handled = false;
       
  1682 #ifdef Q_WS_MAC
       
  1683         if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
       
  1684             Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
       
  1685             if (myModifiers & Qt::ShiftModifier) {
       
  1686                 if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
       
  1687                         || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
       
  1688                         || myModifiers == Qt::ShiftModifier) {
       
  1689 
       
  1690                     event->key() == Qt::Key_Up ? home(1) : end(1);
       
  1691                 }
       
  1692             } else {
       
  1693                 if ((myModifiers == Qt::ControlModifier
       
  1694                      || myModifiers == Qt::AltModifier
       
  1695                      || myModifiers == Qt::NoModifier)) {
       
  1696                     event->key() == Qt::Key_Up ? home(0) : end(0);
       
  1697                 }
       
  1698             }
       
  1699             handled = true;
       
  1700         }
       
  1701 #endif
       
  1702         if (event->modifiers() & Qt::ControlModifier) {
       
  1703             switch (event->key()) {
       
  1704             case Qt::Key_Backspace:
       
  1705                 if (!isReadOnly()) {
       
  1706                     cursorWordBackward(true);
       
  1707                     del();
       
  1708                 }
       
  1709                 break;
       
  1710 #ifndef QT_NO_COMPLETER
       
  1711             case Qt::Key_Up:
       
  1712             case Qt::Key_Down:
       
  1713                 complete(event->key());
       
  1714                 break;
       
  1715 #endif
       
  1716 #if defined(Q_WS_X11)
       
  1717             case Qt::Key_E:
       
  1718                 end(0);
       
  1719                 break;
       
  1720 
       
  1721             case Qt::Key_U:
       
  1722                 if (!isReadOnly()) {
       
  1723                     setSelection(0, text().size());
       
  1724 #ifndef QT_NO_CLIPBOARD
       
  1725                     copy();
       
  1726 #endif
       
  1727                     del();
       
  1728                 }
       
  1729             break;
       
  1730 #endif
       
  1731             default:
       
  1732                 if (!handled)
       
  1733                     unknown = true;
       
  1734             }
       
  1735         } else { // ### check for *no* modifier
       
  1736             switch (event->key()) {
       
  1737             case Qt::Key_Backspace:
       
  1738                 if (!isReadOnly()) {
       
  1739                     backspace();
       
  1740 #ifndef QT_NO_COMPLETER
       
  1741                     complete(Qt::Key_Backspace);
       
  1742 #endif
       
  1743                 }
       
  1744                 break;
       
  1745 #ifdef QT_KEYPAD_NAVIGATION
       
  1746             case Qt::Key_Back:
       
  1747                 if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
       
  1748                     && !isReadOnly()) {
       
  1749                     if (text().length() == 0) {
       
  1750                         setText(m_cancelText);
       
  1751 
       
  1752                         if (passwordEchoEditing())
       
  1753                             updatePasswordEchoEditing(false);
       
  1754 
       
  1755                         emit editFocusChange(false);
       
  1756                     } else if (!m_deleteAllTimer) {
       
  1757                         m_deleteAllTimer = startTimer(750);
       
  1758                     }
       
  1759                 } else {
       
  1760                     unknown = true;
       
  1761                 }
       
  1762                 break;
       
  1763 #endif
       
  1764 
       
  1765             default:
       
  1766                 if (!handled)
       
  1767                     unknown = true;
       
  1768             }
       
  1769         }
       
  1770     }
       
  1771 
       
  1772     if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
       
  1773         setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
       
  1774         unknown = false;
       
  1775     }
       
  1776 
       
  1777     if (unknown && !isReadOnly()) {
       
  1778         QString t = event->text();
       
  1779         if (!t.isEmpty() && t.at(0).isPrint()) {
       
  1780             insert(t);
       
  1781 #ifndef QT_NO_COMPLETER
       
  1782             complete(event->key());
       
  1783 #endif
       
  1784             event->accept();
       
  1785             return;
       
  1786         }
       
  1787     }
       
  1788 
       
  1789     if (unknown)
       
  1790         event->ignore();
       
  1791     else
       
  1792         event->accept();
       
  1793 }
       
  1794 
       
  1795 
       
  1796 QT_END_NAMESPACE
       
  1797 
       
  1798 #endif