From 22ff3df15cc3143e6410b02f39b967d1d76cf2d6 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 17:37:43 +1000 Subject: Manual cherrypick of QLineControl from kinetic-declarativeui-qfxlineedit Splits out the control logic of QLineEdit into QLineControl, which is somewhat similar to QTextEdit. This was originally worked on in the ianws-qt-lineedit-textedit-research repository, and then further developed in kinetic in the kinetic-declarativeui-qfxlineedit branch. Note that this also includes a tiny change to qvalidator.h which allows validators to be used in qml. --- src/gui/widgets/qlinecontrol.cpp | 1707 ++++++++++++++++++++++++++++++++ src/gui/widgets/qlinecontrol_p.h | 715 ++++++++++++++ src/gui/widgets/qlinecontrol_p_p.h | 105 ++ src/gui/widgets/qlineedit.cpp | 1885 ++++-------------------------------- src/gui/widgets/qlineedit.h | 2 + src/gui/widgets/qlineedit_p.cpp | 253 +++++ src/gui/widgets/qlineedit_p.h | 174 +--- src/gui/widgets/qvalidator.h | 6 +- src/gui/widgets/widgets.pri | 3 + 9 files changed, 3010 insertions(+), 1840 deletions(-) create mode 100644 src/gui/widgets/qlinecontrol.cpp create mode 100644 src/gui/widgets/qlinecontrol_p.h create mode 100644 src/gui/widgets/qlinecontrol_p_p.h create mode 100644 src/gui/widgets/qlineedit_p.cpp diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp new file mode 100644 index 0000000..b762a00 --- /dev/null +++ b/src/gui/widgets/qlinecontrol.cpp @@ -0,0 +1,1707 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlinecontrol_p.h" + +#ifndef QT_NO_LINEEDIT + +#include "qabstractitemview.h" +#include "qclipboard.h" +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qlist.h" +#endif +#include "qapplication.h" +#ifndef QT_NO_GRAPHICSVIEW +#include "qgraphicssceneevent.h" +#endif + +QT_BEGIN_NAMESPACE + +/* + Updates the display text based of the current edit text + If the text has changed will emit displayTextChanged() +*/ +void QLineControl::updateDisplayText() +{ + QString orig = textLayout.text(); + QString str; + if (m_echoMode == QLineEdit::NoEcho) + str = QString::fromLatin1(""); + else + str = m_text; + + if (m_echoMode == QLineEdit::Password || (m_echoMode == QLineEdit::PasswordEchoOnEdit + && !m_passwordEchoEditing)) + str.fill(m_passwordCharacter); + + // replace certain non-printable characters with spaces (to avoid + // drawing boxes when using fonts that don't have glyphs for such + // characters) + QChar* uc = str.data(); + for (int i = 0; i < (int)str.length(); ++i) { + if ((uc[i] < 0x20 && uc[i] != 0x09) + || uc[i] == QChar::LineSeparator + || uc[i] == QChar::ParagraphSeparator + || uc[i] == QChar::ObjectReplacementCharacter) + uc[i] = QChar(0x0020); + } + + textLayout.setText(str); + + QTextOption option; + option.setTextDirection(m_layoutDirection); + option.setFlags(QTextOption::IncludeTrailingSpaces); + textLayout.setTextOption(option); + + textLayout.beginLayout(); + QTextLine l = textLayout.createLine(); + textLayout.endLayout(); + m_ascent = qRound(l.ascent()); + + if (str != orig) + emit displayTextChanged(str); +} + +#ifndef QT_NO_CLIPBOARD +/* + Copies the currently selected text into the clipboard using the given + \a mode. + + \note If the echo mode is set to a mode other than Normal then copy + will not work. This is to prevent using copy as a method of bypassing + password features of the line control. +*/ +void QLineControl::copy(QClipboard::Mode mode) const +{ + QString t = selectedText(); + if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) { + disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0); + QApplication::clipboard()->setText(t, mode); + connect(QApplication::clipboard(), SIGNAL(selectionChanged()), + this, SLOT(_q_clipboardChanged())); + } +} + +/* + Inserts the text stored in the application clipboard into the line + control. + + \sa insert() +*/ +void QLineControl::paste() +{ + insert(QApplication::clipboard()->text(QClipboard::Clipboard)); +} + +#endif // !QT_NO_CLIPBOARD + +/* + Handles the behavior for the backspace key or function. + Removes the current selection if there is a selection, otherwise + removes the character prior to the cursor position. + + \sa del() +*/ +void QLineControl::backspace() +{ + int priorState = undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else if (m_cursor) { + --m_cursor; + if (maskData) + m_cursor = prevMaskBlank(m_cursor); + QChar uc = m_text.at(m_cursor); + if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { + // second half of a surrogate, check if we have the first half as well, + // if yes delete both at once + uc = m_text.at(m_cursor - 1); + if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { + p_del(true); + --m_cursor; + } + } + p_del(true); + } + finishChange(priorState); +} + +/* + Handles the behavior for the delete key or function. + Removes the current selection if there is a selection, otherwise + removes the character after the cursor position. + + \sa del() +*/ +void QLineControl::del() +{ + int priorState = undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else { + int n = textLayout.nextCursorPosition(m_cursor) - m_cursor; + while (n--) + p_del(); + } + finishChange(priorState); +} + +/* + Inserts the given \a newText at the current cursor position. + If there is any selected text it is removed prior to insertion of + the new text. +*/ +void QLineControl::insert(const QString &newText) +{ + int priorState = undoState; + removeSelectedText(); + p_insert(newText); + finishChange(priorState); +} + +/* + Clears the line control text. +*/ +void QLineControl::clear() +{ + int priorState = undoState; + selstart = 0; + selend = m_text.length(); + removeSelectedText(); + separate(); + finishChange(priorState, /*update*/false, /*edited*/false); +} + +/* + Sets \a length characters from the given \a start position as selected. + The given \a start position must be within the current text for + the line control. If \a length characters cannot be selected, then + the selection will extend to the end of the current text. +*/ +void QLineControl::setSelection(int start, int length) +{ + Q_ASSERT_X(start >= 0 && start <= (int)m_text.length(), + "QLineControl::setSelection", "Invalid start position"); + + if (length > 0) { + selstart = start; + selend = qMin(start + length, (int)m_text.length()); + m_cursor = selend; + } else { + selstart = qMax(start + length, 0); + selend = start; + m_cursor = selstart; + } +} + +void QLineControl::_q_clipboardChanged() +{ +} + +void QLineControl::_q_deleteSelected() +{ + if (!hasSelectedText()) + return; + + int priorState = undoState; + emit resetInputContext(); + removeSelectedText(); + separate(); + finishChange(priorState); +} + +/* + Initializes the line control with a starting text value of \a txt. +*/ +void QLineControl::init(const QString& txt) +{ + m_text = txt; + updateDisplayText(); + m_cursor = m_text.length(); +} + +/* + Sets the password echo editing to \a editing. If password echo editing + is true, then the text of the password is displayed even if the echo + mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing + does not affect other echo modes. +*/ +void QLineControl::updatePasswordEchoEditing(bool editing) +{ + m_passwordEchoEditing = editing; + updateDisplayText(); +} + +/* + Returns the cursor position of the given \a x pixel value in relation + to the displayed text. The given \a betweenOrOn specified what kind + of cursor position is requested. +*/ +int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + return textLayout.lineAt(0).xToCursor(x, betweenOrOn); +} + +/* + Returns the bounds of the current cursor, as defined as a + between characters cursor. +*/ +QRect QLineControl::cursorRect() const +{ + QTextLine l = textLayout.lineAt(0); + int c = m_cursor; + if (m_preeditCursor != -1) + c += m_preeditCursor; + int cix = qRound(l.cursorToX(c)); + int w = m_cursorWidth; + int ch = l.height() + 1; + + return QRect(cix-5, 0, w+9, ch); +} + +/* + Fixes the current text so that it is valid given any set validators. + + Returns true if the text was changed. Otherwise returns false. +*/ +bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable +{ +#ifndef QT_NO_VALIDATOR + if (m_validator) { + QString textCopy = m_text; + int cursorCopy = m_cursor; + m_validator->fixup(textCopy); + if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { + if (textCopy != m_text || cursorCopy != m_cursor) + p_setText(textCopy, cursorCopy); + return true; + } + } +#endif + return false; +} + +/* + Moves the cursor to the given position \a pos. If \a mark is true will + adjust the currently selected text. +*/ +void QLineControl::moveCursor(int pos, bool mark) +{ + if (pos != m_cursor) { + separate(); + if (maskData) + pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); + } + if (mark) { + int anchor; + if (selend > selstart && m_cursor == selstart) + anchor = selend; + else if (selend > selstart && m_cursor == selend) + anchor = selstart; + else + anchor = m_cursor; + selstart = qMin(anchor, pos); + selend = qMax(anchor, pos); + updateDisplayText(); + } else { + p_deselect(); + } + m_cursor = pos; + if (mark || selDirty) { + selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); +} + +/* + Applies the given input method event \a event to the text of the line + control +*/ +void QLineControl::processInputMethodEvent(QInputMethodEvent *event) +{ + int priorState = undoState; + removeSelectedText(); + + int c = m_cursor; // cursor position after insertion of commit string + if (event->replacementStart() <= 0) + c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); + + m_cursor += event->replacementStart(); + + // insert commit string + if (event->replacementLength()) { + selstart = m_cursor; + selend = selstart + event->replacementLength(); + removeSelectedText(); + } + if (!event->commitString().isEmpty()) + insert(event->commitString()); + + m_cursor = qMin(c, m_text.length()); + + setPreeditArea(m_cursor, event->preeditString()); + m_preeditCursor = event->preeditString().length(); + hideCursor = false; + QList formats; + for (int i = 0; i < event->attributes().size(); ++i) { + const QInputMethodEvent::Attribute &a = event->attributes().at(i); + if (a.type == QInputMethodEvent::Cursor) { + m_preeditCursor = a.start; + hideCursor = !a.length; + } else if (a.type == QInputMethodEvent::TextFormat) { + QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); + if (f.isValid()) { + QTextLayout::FormatRange o; + o.start = a.start + m_cursor; + o.length = a.length; + o.format = f; + formats.append(o); + } + } + } + textLayout.setAdditionalFormats(formats); + updateDisplayText(); + if (!event->commitString().isEmpty()) + emitCursorPositionChanged(); + finishChange(priorState); +} + +/* + Draws the display text for the line control using the given + \a painter, \a clip, and \a offset. Which aspects of the display text + are drawn is specified by the given \a flags. + + If the flags contain DrawSelections, then the selection or input mask + backgrounds and foregrounds will be applied before drawing the text. + + If the flags contain DrawCursor a cursor of the current cursorWidth() + will be drawn after drawing the text. + + The display text will only be drawn if the flags contain DrawText +*/ +void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags) +{ + QVector selections; + if (flags & DrawSelections) { + QTextLayout::FormatRange o; + if (selstart < selend) { + o.start = selstart; + o.length = selend - selstart; + o.format.setBackground(m_palette.brush(QPalette::Highlight)); + o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); + } else { + // mask selection + o.start = m_cursor; + o.length = 1; + o.format.setBackground(m_palette.brush(QPalette::Text)); + o.format.setForeground(m_palette.brush(QPalette::Window)); + } + selections.append(o); + } + + if (flags & DrawText) + textLayout.draw(painter, offset, selections, clip); + + if (flags & DrawCursor){ + if(!m_blinkPeriod || m_blinkStatus) + textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + } +} + +/* + Sets the selection to cover the word at the given cursor position. + The word boundries is defined by the behavior of QTextLayout::SkipWords + cursor mode. +*/ +void QLineControl::selectWordAtPos(int cursor) +{ + int c = textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + moveCursor(c, false); + // ## text layout should support end of words. + int end = textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + while (end > cursor && m_text[end-1].isSpace()) + --end; + moveCursor(end, true); +} + +/* + Completes a change to the line control text. If the change is not valid + will undo the line control state back to the given \a validateFromState. + + If \a edited is true and the change is valid, will emit textEdited() in + addition to textChanged(). Otherwise only emits textChanged() on a valid + change. + + The \a update value is currently unused. +*/ + +bool QLineControl::finishChange(int validateFromState, bool update, bool edited) +{ + Q_UNUSED(update) + bool lineDirty = selDirty; + if (textDirty) { + // do validation + bool wasValidInput = validInput; + validInput = true; +#ifndef QT_NO_VALIDATOR + if (m_validator) { + validInput = false; + QString textCopy = m_text; + int cursorCopy = m_cursor; + validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (validInput) { + if (m_text != textCopy) { + p_setText(textCopy, cursorCopy); + return true; + } + m_cursor = cursorCopy; + } + } +#endif + if (validateFromState >= 0 && wasValidInput && !validInput) { + if (transactions.count()) + return false; + p_undo(validateFromState); + history.resize(undoState); + if (modifiedState > undoState) + modifiedState = -1; + validInput = true; + textDirty = false; + } + updateDisplayText(); + lineDirty |= textDirty; + if (textDirty) { + textDirty = false; + QString actualText = text(); + if (edited) + emit textEdited(actualText); + emit textChanged(actualText); + } + } + if (selDirty) { + selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); + return true; +} + +/* + An internal function for setting the text of the line control. +*/ +void QLineControl::p_setText(const QString& txt, int pos, bool edited) +{ + p_deselect(); + emit resetInputContext(); + QString oldText = m_text; + if (maskData) { + m_text = maskString(0, txt, true); + m_text += clearString(m_text.length(), m_maxLength - m_text.length()); + } else { + m_text = txt.isEmpty() ? txt : txt.left(m_maxLength); + } + history.clear(); + modifiedState = undoState = 0; + m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; + textDirty = (oldText != m_text); + finishChange(-1, true, edited); +} + + +/* + Adds the given \a command to the undo history + of the line control. Does not apply the command. +*/ +void QLineControl::addCommand(const Command& cmd) +{ + if (separator && undoState && history[undoState-1].type != Separator) { + history.resize(undoState + 2); + history[undoState++] = Command(Separator, m_cursor, 0, selstart, selend); + } else { + history.resize(undoState + 1); + } + separator = false; + history[undoState++] = cmd; +} + +/* + Inserts the given string \a s into the line + control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::p_insert(const QString& s) +{ + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + if (maskData) { + QString ms = maskString(m_cursor, s); + for (int i = 0; i < (int) ms.length(); ++i) { + addCommand (Command(DeleteSelection, m_cursor+i, m_text.at(m_cursor+i), -1, -1)); + addCommand(Command(Insert, m_cursor+i, ms.at(i), -1, -1)); + } + m_text.replace(m_cursor, ms.length(), ms); + m_cursor += ms.length(); + m_cursor = nextMaskBlank(m_cursor); + textDirty = true; + } else { + int remaining = m_maxLength - m_text.length(); + if (remaining != 0) { + m_text.insert(m_cursor, s.left(remaining)); + for (int i = 0; i < (int) s.left(remaining).length(); ++i) + addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); + textDirty = true; + } + } +} + +/* + \internal + deletes a single character from the current text. If \a wasBackspace, + the character prior to the cursor is removed. Otherwise the character + after the cursor is removed. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::p_del(bool wasBackspace) +{ + if (m_cursor < (int) m_text.length()) { + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); + if (maskData) { + m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); + addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); + } else { + m_text.remove(m_cursor, 1); + } + textDirty = true; + } +} + +/* + \internal + removes the currently selected text from the line control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::removeSelectedText() +{ + if (selstart < selend && selend <= (int) m_text.length()) { + separate(); + int i ; + addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); + if (selstart <= m_cursor && m_cursor < selend) { + // cursor is within the selection. Split up the commands + // to be able to restore the correct cursor position + for (i = m_cursor; i >= selstart; --i) + addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1)); + for (i = selend - 1; i > m_cursor; --i) + addCommand (Command(DeleteSelection, i - m_cursor + selstart - 1, m_text.at(i), -1, -1)); + } else { + for (i = selend-1; i >= selstart; --i) + addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); + } + if (maskData) { + m_text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); + for (int i = 0; i < selend - selstart; ++i) + addCommand(Command(Insert, selstart + i, m_text.at(selstart + i), -1, -1)); + } else { + m_text.remove(selstart, selend - selstart); + } + if (m_cursor > selstart) + m_cursor -= qMin(m_cursor, selend) - selstart; + p_deselect(); + textDirty = true; + } +} + +/* + Parses the input mask specified by \a maskFields to generate + the mask data used to handle input masks. +*/ +void QLineControl::parseInputMask(const QString &maskFields) +{ + int delimiter = maskFields.indexOf(QLatin1Char(';')); + if (maskFields.isEmpty() || delimiter == 0) { + if (maskData) { + delete [] maskData; + maskData = 0; + m_maxLength = 32767; + p_setText(QString()); + } + return; + } + + if (delimiter == -1) { + blank = QLatin1Char(' '); + m_inputMask = maskFields; + } else { + m_inputMask = maskFields.left(delimiter); + blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + } + + // calculate m_maxLength / maskData length + m_maxLength = 0; + QChar c = 0; + for (int i=0; i 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) { + m_maxLength++; + continue; + } + if (c != QLatin1Char('\\') && c != QLatin1Char('!') && + c != QLatin1Char('<') && c != QLatin1Char('>') && + c != QLatin1Char('{') && c != QLatin1Char('}') && + c != QLatin1Char('[') && c != QLatin1Char(']')) + m_maxLength++; + } + + delete [] maskData; + maskData = new MaskInputData[m_maxLength]; + + MaskInputData::Casemode m = MaskInputData::NoCaseMode; + c = 0; + bool s; + bool escape = false; + int index = 0; + for (int i = 0; i < m_inputMask.length(); i++) { + c = m_inputMask.at(i); + if (escape) { + s = true; + maskData[index].maskChar = c; + maskData[index].separator = s; + maskData[index].caseMode = m; + index++; + escape = false; + } else if (c == QLatin1Char('<')) { + m = MaskInputData::Lower; + } else if (c == QLatin1Char('>')) { + m = MaskInputData::Upper; + } else if (c == QLatin1Char('!')) { + m = MaskInputData::NoCaseMode; + } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { + switch (c.unicode()) { + case 'A': + case 'a': + case 'N': + case 'n': + case 'X': + case 'x': + case '9': + case '0': + case 'D': + case 'd': + case '#': + case 'H': + case 'h': + case 'B': + case 'b': + s = false; + break; + case '\\': + escape = true; + default: + s = true; + break; + } + + if (!escape) { + maskData[index].maskChar = c; + maskData[index].separator = s; + maskData[index].caseMode = m; + index++; + } + } + } + p_setText(m_text); +} + + +/* checks if the key is valid compared to the inputMask */ +bool QLineControl::isValidInput(QChar key, QChar mask) const +{ + switch (mask.unicode()) { + case 'A': + if (key.isLetter()) + return true; + break; + case 'a': + if (key.isLetter() || key == blank) + return true; + break; + case 'N': + if (key.isLetterOrNumber()) + return true; + break; + case 'n': + if (key.isLetterOrNumber() || key == blank) + return true; + break; + case 'X': + if (key.isPrint()) + return true; + break; + case 'x': + if (key.isPrint() || key == blank) + return true; + break; + case '9': + if (key.isNumber()) + return true; + break; + case '0': + if (key.isNumber() || key == blank) + return true; + break; + case 'D': + if (key.isNumber() && key.digitValue() > 0) + return true; + break; + case 'd': + if ((key.isNumber() && key.digitValue() > 0) || key == blank) + return true; + break; + case '#': + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) + return true; + break; + case 'B': + if (key == QLatin1Char('0') || key == QLatin1Char('1')) + return true; + break; + case 'b': + if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) + return true; + break; + case 'H': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) + return true; + break; + case 'h': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) + return true; + break; + default: + break; + } + return false; +} + +/* + Returns true if the given text \a str is valid for any + validator or input mask set for the line control. + + Otherwise returns false +*/ +bool QLineControl::hasAcceptableInput(const QString &str) const +{ +#ifndef QT_NO_VALIDATOR + QString textCopy = str; + int cursorCopy = m_cursor; + if (m_validator && m_validator->validate(textCopy, cursorCopy) + != QValidator::Acceptable) + return false; +#endif + + if (!maskData) + return true; + + if (str.length() != m_maxLength) + return false; + + for (int i=0; i < m_maxLength; ++i) { + if (maskData[i].separator) { + if (str.at(i) != maskData[i].maskChar) + return false; + } else { + if (!isValidInput(str.at(i), maskData[i].maskChar)) + return false; + } + } + return true; +} + +/* + Applies the inputMask on \a str starting from position \a pos in the mask. \a clear + specifies from where characters should be gotten when a separator is met in \a str - true means + that blanks will be used, false that previous input is used. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::maskString(uint pos, const QString &str, bool clear) const +{ + if (pos >= (uint)m_maxLength) + return QString::fromLatin1(""); + + QString fill; + fill = clear ? clearString(0, m_maxLength) : m_text; + + int strIndex = 0; + QString s = QString::fromLatin1(""); + int i = pos; + while (i < m_maxLength) { + if (strIndex < str.length()) { + if (maskData[i].separator) { + s += maskData[i].maskChar; + if (str[(int)strIndex] == maskData[i].maskChar) + strIndex++; + ++i; + } else { + if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { + switch (maskData[i].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + ++i; + } else { + // search for separator first + int n = findInMask(i, true, true, str[(int)strIndex]); + if (n != -1) { + if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { + s += fill.mid(i, n-i+1); + i = n + 1; // update i to find + 1 + } + } else { + // search for valid blank if not + n = findInMask(i, true, false, str[(int)strIndex]); + if (n != -1) { + s += fill.mid(i, n-i); + switch (maskData[n].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + i = n + 1; // updates i to find + 1 + } + } + } + strIndex++; + } + } else + break; + } + + return s; +} + + + +/* + Returns a "cleared" string with only separators and blank chars. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::clearString(uint pos, uint len) const +{ + if (pos >= (uint)m_maxLength) + return QString(); + + QString s; + int end = qMin((uint)m_maxLength, pos + len); + for (int i=pos; i= m_maxLength || pos < 0) + return -1; + + int end = forward ? m_maxLength : -1; + int step = forward ? 1 : -1; + int i = pos; + + while (i != end) { + if (findSeparator) { + if (maskData[i].separator && maskData[i].maskChar == searchChar) + return i; + } else { + if (!maskData[i].separator) { + if (searchChar.isNull()) + return i; + else if (isValidInput(searchChar, maskData[i].maskChar)) + return i; + } + } + i += step; + } + return -1; +} + +void QLineControl::p_undo(int until) +{ + if (!isUndoAvailable()) + return; + p_deselect(); + while (undoState && undoState > until) { + Command& cmd = history[--undoState]; + switch (cmd.type) { + case Insert: + m_text.remove(cmd.pos, 1); + m_cursor = cmd.pos; + break; + case SetSelection: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case RemoveSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case Delete: + case DeleteSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos; + break; + case Separator: + continue; + } + if (until < 0 && undoState) { + Command& next = history[undoState-1]; + if (next.type != cmd.type && next.type < RemoveSelection + && (cmd.type < RemoveSelection || next.type == Separator)) + break; + } + } + textDirty = true; + emitCursorPositionChanged(); +} + +void QLineControl::p_redo() { + if (!isRedoAvailable()) + return; + p_deselect(); + while (undoState < (int)history.size()) { + Command& cmd = history[undoState++]; + switch (cmd.type) { + case Insert: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case SetSelection: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case Delete: + case RemoveSelection: + case DeleteSelection: + m_text.remove(cmd.pos, 1); + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Separator: + selstart = cmd.selStart; + selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + } + if (undoState < (int)history.size()) { + Command& next = history[undoState]; + if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator + && (next.type < RemoveSelection || cmd.type == Separator)) + break; + } + } + textDirty = true; + emitCursorPositionChanged(); +} + +/* + If the current cursor position differs from the last emited cursor + position, emits cursorPositionChanged(). +*/ +void QLineControl::emitCursorPositionChanged() +{ + if (m_cursor != lastCursorPos) { + const int oldLast = lastCursorPos; + lastCursorPos = m_cursor; + cursorPositionChanged(oldLast, m_cursor); + } +} + +#ifndef QT_NO_COMPLETER +// iterating forward(dir=1)/backward(dir=-1) from the +// current row based. dir=0 indicates a new completion prefix was set. +bool QLineControl::advanceToEnabledItem(int dir) +{ + int start = m_completer->currentRow(); + if (start == -1) + return false; + int i = start + dir; + if (dir == 0) dir = 1; + do { + if (!m_completer->setCurrentRow(i)) { + if (!m_completer->wrapAround()) + break; + i = i > 0 ? 0 : m_completer->completionCount() - 1; + } else { + QModelIndex currentIndex = m_completer->currentIndex(); + if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled) + return true; + i += dir; + } + } while (i != start); + + m_completer->setCurrentRow(start); // restore + return false; +} + +void QLineControl::complete(int key) +{ + if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal) + return; + + QString text = this->text(); + if (m_completer->completionMode() == QCompleter::InlineCompletion) { + if (key == Qt::Key_Backspace) + return; + int n = 0; + if (key == Qt::Key_Up || key == Qt::Key_Down) { + if (textAfterSelection().length()) + return; + QString prefix = hasSelectedText() ? textBeforeSelection() + : text; + if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0 + || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) { + m_completer->setCompletionPrefix(prefix); + } else { + n = (key == Qt::Key_Up) ? -1 : +1; + } + } else { + m_completer->setCompletionPrefix(text); + } + if (!advanceToEnabledItem(n)) + return; + } else { +#ifndef QT_KEYPAD_NAVIGATION + if (text.isEmpty()) { + m_completer->popup()->hide(); + return; + } +#endif + m_completer->setCompletionPrefix(text); + } + + m_completer->complete(); +} +#endif + +void QLineControl::setCursorBlinkPeriod(int msec) +{ + if(msec == m_blinkPeriod) + return; + if(m_blinkTimer){ + killTimer(m_blinkTimer); + } + if(msec){ + m_blinkTimer = startTimer(msec/2); + m_blinkStatus = 1; + }else{ + m_blinkTimer = 0; + if(m_blinkStatus == 0) + emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); + } + m_blinkPeriod = msec; +} + +void QLineControl::timerEvent ( QTimerEvent * event ) +{ + if(event->timerId() == m_blinkTimer) { + m_blinkStatus = !m_blinkStatus; + emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); + }else if(event->timerId() == m_deleteAllTimer){ + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + clear(); + }else if(event->timerId() == m_tripleClickTimer){ + killTimer(m_tripleClickTimer); + m_tripleClickTimer = 0; + } +} + +bool QLineControl::processEvent(QEvent* ev) +{ +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + //TODO: Needs a call to processKeyEvent? + } else if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false);//!!! + control->setCursorBlinkPeriod(0); + if (!m_emitingEditingFinished) { + if (hasAcceptableInput() || fixup()) { + m_emitingEditingFinished = true; + emit editingFinished(); + m_emitingEditingFinished = false; + } + } + } + return; + } +#endif + switch(ev->type()){ +#ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMousePress:{ + QGraphicsSceneMouseEvent *gvEv = static_cast(ev); + QMouseEvent* mouse = new QMouseEvent(ev->type(), + gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers()); + processMouseEvent(mouse); break; + } +#endif + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + processMouseEvent(static_cast(ev)); break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + processKeyEvent(static_cast(ev)); break; + case QEvent::InputMethod: + processInputMethodEvent(static_cast(ev)); break; +#ifndef QT_NO_SHORTCUT + case QEvent::ShortcutOverride:{ + QKeyEvent* ke = static_cast(ev); + if (ke == QKeySequence::Copy + || ke == QKeySequence::Paste + || ke == QKeySequence::Cut + || ke == QKeySequence::Redo + || ke == QKeySequence::Undo + || ke == QKeySequence::MoveToNextWord + || ke == QKeySequence::MoveToPreviousWord + || ke == QKeySequence::MoveToStartOfDocument + || ke == QKeySequence::MoveToEndOfDocument + || ke == QKeySequence::SelectNextWord + || ke == QKeySequence::SelectPreviousWord + || ke == QKeySequence::SelectStartOfLine + || ke == QKeySequence::SelectEndOfLine + || ke == QKeySequence::SelectStartOfBlock + || ke == QKeySequence::SelectEndOfBlock + || ke == QKeySequence::SelectStartOfDocument + || ke == QKeySequence::SelectAll + || ke == QKeySequence::SelectEndOfDocument) { + ke->accept(); + } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier + || ke->modifiers() == Qt::KeypadModifier) { + if (ke->key() < Qt::Key_Escape) { + ke->accept(); + } else { + switch (ke->key()) { + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + ke->accept(); + default: + break; + } + } + } + } +#endif + default: + return false; + } + return true; +} + +void QLineControl::processMouseEvent(QMouseEvent* ev) +{ + + switch (ev->type()){ + case QEvent::GraphicsSceneMousePress: + case QEvent::MouseButtonPress:{ + if (m_tripleClickTimer && (ev->pos() - m_tripleClick).manhattanLength() < + QApplication::startDragDistance()) { + selectAll(); + return; + } + if (ev->button() == Qt::RightButton) + return; +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + setEditFocus(true); + // Get the completion list to pop up. + if (m_completer) + m_completer->complete(); + } +#endif + + bool mark = ev->modifiers() & Qt::ShiftModifier; + int cursor = xToPos(ev->pos().x()); + moveCursor(cursor, mark); + break; + } + case QEvent::MouseButtonDblClick: + if (ev->button() == Qt::LeftButton) { + selectWordAtPos(xToPos(ev->pos().x())); + if(m_tripleClickTimer) + killTimer(m_tripleClickTimer); + m_tripleClickTimer = startTimer(QApplication::doubleClickInterval()); + m_tripleClick = ev->pos(); + } + break; + case QEvent::GraphicsSceneMouseRelease: + case QEvent::MouseButtonRelease: +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + if (ev->button() == Qt::LeftButton) { + copy(QClipboard::Selection); + } else if (!isReadOnly() && ev->button() == Qt::MidButton) { + deselect(); + insert(QApplication::clipboard()->text(QClipboard::Selection)); + } + } +#endif + break; + case QEvent::GraphicsSceneMouseMove: + case QEvent::MouseMove: + if (ev->buttons() & Qt::LeftButton) { + moveCursor(xToPos(ev->pos().x()), true); + } + break; + default: + break; + } +} + +void QLineControl::processKeyEvent(QKeyEvent* event) +{ + + bool inlineCompletionAccepted = false; + +#ifndef QT_NO_COMPLETER + if (m_completer) { + QCompleter::CompletionMode completionMode = m_completer->completionMode(); + if ((completionMode == QCompleter::PopupCompletion + || completionMode == QCompleter::UnfilteredPopupCompletion) + && m_completer->popup() + && m_completer->popup()->isVisible()) { + // The following keys are forwarded by the completer to the widget + // Ignoring the events lets the completer provide suitable default behavior + switch (event->key()) { + case Qt::Key_Escape: + event->ignore(); + return; + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_F4: +#ifdef QT_KEYPAD_NAVIGATION + case Qt::Key_Select: + if (!QApplication::keypadNavigationEnabled()) + break; +#endif + m_completer->popup()->hide(); // just hide. will end up propagating to parent + default: + break; // normal key processing + } + } else if (completionMode == QCompleter::InlineCompletion) { + switch (event->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_F4: +#ifdef QT_KEYPAD_NAVIGATION + case Qt::Key_Select: + if (!QApplication::keypadNavigationEnabled()) + break; +#endif + if (!m_completer->currentCompletion().isEmpty() && hasSelectedText() + && textAfterSelection().isEmpty()) { + setText(m_completer->currentCompletion()); + inlineCompletionAccepted = true; + } + default: + break; // normal key processing + } + } + } +#endif // QT_NO_COMPLETER + + + + if (echoMode() == QLineEdit::PasswordEchoOnEdit + && !passwordEchoEditing() + && !isReadOnly() + && !event->text().isEmpty() +#ifdef QT_KEYPAD_NAVIGATION + && event->key() != Qt::Key_Select + && event->key() != Qt::Key_Up + && event->key() != Qt::Key_Down + && event->key() != Qt::Key_Back +#endif + && !(event->modifiers() & Qt::ControlModifier)) { + // Clear the edit and reset to normal echo mode while editing; the + // echo mode switches back when the edit loses focus + // ### resets current content. dubious code; you can + // navigate with keys up, down, back, and select(?), but if you press + // "left" or "right" it clears? + updatePasswordEchoEditing(true);//TODO: used to set a WA too + clear(); + } + + //setCursorVisible(true);TODO: Who handles this? + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + if (hasAcceptableInput() || fixup()) { + emit accepted(); + emitingEditingFinished = true; + emit editingFinished(); + emitingEditingFinished = false; + } + if (inlineCompletionAccepted) + event->accept(); + else + event->ignore(); + return; + } + bool unknown = false; + + if (false) { + } +#ifndef QT_NO_SHORTCUT + else if (event == QKeySequence::Undo) { + if (!isReadOnly()) + undo(); + } + else if (event == QKeySequence::Redo) { + if (!isReadOnly()) + redo(); + } + else if (event == QKeySequence::SelectAll) { + selectAll(); + } +#ifndef QT_NO_CLIPBOARD + else if (event == QKeySequence::Copy) { + copy(); + } + else if (event == QKeySequence::Paste) { + if (!isReadOnly()) + paste(); + } + else if (event == QKeySequence::Cut) { + if (!isReadOnly()) { + copy(); + del(); + } + } + else if (event == QKeySequence::DeleteEndOfLine) { + if (!isReadOnly()) { + setSelection(cursor(), end()); + copy(); + del(); + } + } +#endif //QT_NO_CLIPBOARD + else if (event == QKeySequence::MoveToStartOfLine) { + home(0); + } + else if (event == QKeySequence::MoveToEndOfLine) { + end(0); + } + else if (event == QKeySequence::SelectStartOfLine) { + home(1); + } + else if (event == QKeySequence::SelectEndOfLine) { + end(1); + } + else if (event == QKeySequence::MoveToNextChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionEnd(), false); + } else { + cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); + } + } + else if (event == QKeySequence::SelectNextChar) { + cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); + } + else if (event == QKeySequence::MoveToPreviousChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionStart(), false); + } else { + cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1); + } + } + else if (event == QKeySequence::SelectPreviousChar) { + cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1); + } + else if (event == QKeySequence::MoveToNextWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); + else + layoutDirection() == Qt::LeftToRight ? end(0) : home(0); + } + else if (event == QKeySequence::MoveToPreviousWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); + else if (!isReadOnly()) { + layoutDirection() == Qt::LeftToRight ? home(0) : end(0); + } + } + else if (event == QKeySequence::SelectNextWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); + else + layoutDirection() == Qt::LeftToRight ? end(1) : home(1); + } + else if (event == QKeySequence::SelectPreviousWord) { + if (echoMode() == QLineEdit::Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); + else + layoutDirection() == Qt::LeftToRight ? home(1) : end(1); + } + else if (event == QKeySequence::Delete) { + if (!isReadOnly()) + del(); + } + else if (event == QKeySequence::DeleteEndOfWord) { + if (!isReadOnly()) { + cursorWordForward(true); + del(); + } + } + else if (event == QKeySequence::DeleteStartOfWord) { + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + } +#endif // QT_NO_SHORTCUT + else { +#ifdef Q_WS_MAC + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { + Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); + if (myModifiers & Qt::ShiftModifier) { + if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) + || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) + || myModifiers == Qt::ShiftModifier) { + + event->key() == Qt::Key_Up ? home(1) : end(1); + } + } else { + if ((myModifiers == Qt::ControlModifier + || myModifiers == Qt::AltModifier + || myModifiers == Qt::NoModifier)) { + event->key() == Qt::Key_Up ? home(0) : end(0); + } + } + } +#endif + if (event->modifiers() & Qt::ControlModifier) { + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + break; +#ifndef QT_NO_COMPLETER + case Qt::Key_Up: + case Qt::Key_Down: + complete(event->key()); + break; +#endif +#if defined(Q_WS_X11) + case Qt::Key_E: + end(0); + break; + + case Qt::Key_U: + if (!isReadOnly()) { + setSelection(0, text().size()); +#ifndef QT_NO_CLIPBOARD + copy(); +#endif + del(); + } + break; +#endif + default: + unknown = true; + } + } else { // ### check for *no* modifier + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + backspace(); +#ifndef QT_NO_COMPLETER + complete(Qt::Key_Backspace); +#endif + } + break; +#ifdef QT_KEYPAD_NAVIGATION//TODO: This section + case Qt::Key_Back: + if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() + && !isReadOnly()) { + if (text().length() == 0) { + setText(d->origText); + + if (d->passwordEchoEditing) + d->updatePasswordEchoEditing(false); + + setEditFocus(false); + } else if (!d->deleteAllTimer.isActive()) { + d->deleteAllTimer.start(750, this); + } + } else { + unknown = true; + } + break; +#endif + + default: + unknown = true; + } + } + } + + if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { + setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); + unknown = false; + } + + if (unknown && !isReadOnly()) { + QString t = event->text(); + if (!t.isEmpty() && t.at(0).isPrint()) { + insert(t); +#ifndef QT_NO_COMPLETER + complete(event->key()); +#endif + event->accept(); + return; + } + } + + if (unknown) + event->ignore(); + else + event->accept(); +} + + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h new file mode 100644 index 0000000..bb27778 --- /dev/null +++ b/src/gui/widgets/qlinecontrol_p.h @@ -0,0 +1,715 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINECONTROL_P_H +#define QLINECONTROL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +#ifndef QT_NO_LINEEDIT +#include "private/qwidget_p.h" +#include "QtGui/qlineedit.h" +#include "QtGui/qtextlayout.h" +#include "QtGui/qstyleoption.h" +#include "QtCore/qpointer.h" +#include "QtGui/qlineedit.h" +#include "QtGui/qclipboard.h" +#include "QtCore/qpoint.h" +#include "QtGui/qcompleter.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QLineControl : public QObject +{ + Q_OBJECT +public: + + QLineControl(const QString &txt = QString()) + : emitingEditingFinished(0), + m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), + hideCursor(false), separator(0), readOnly(0), + dragEnabled(0), m_echoMode(0), textDirty(0), selDirty(0), + validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_ascent(0), m_maxLength(32767), lastCursorPos(-1), + m_tripleClickTimer(0), maskData(0), modifiedState(0), undoState(0), + selstart(0), selend(0), m_passwordEchoEditing(false) + { + init(txt); + } + + ~QLineControl() + { + delete [] maskData; + } + + int nextMaskBlank(int pos); + int prevMaskBlank(int pos); + + bool isUndoAvailable() const; + bool isRedoAvailable() const; + void clearUndo(); + bool isModified() const; + void setModified(bool modified); + + bool allSelected() const; + bool hasSelectedText() const; + + int width() const; + int height() const; + int ascent() const; + + void setSelection(int start, int length); + + QString selectedText() const; + QString textBeforeSelection() const; + QString textAfterSelection() const; + + int selectionStart() const; + int selectionEnd() const; + bool inSelection(int x) const; + + void removeSelection(); + + int start() const; + int end() const; + +#ifndef QT_NO_CLIPBOARD + void copy(QClipboard::Mode mode = QClipboard::Clipboard) const; + void paste(); +#endif + + int cursor() const; + int preeditCursor() const; + + int cursorWidth() const; + void setCursorWidth(int value); + + void moveCursor(int pos, bool mark = false); + void cursorForward(bool mark, int steps); + void cursorWordForward(bool mark); + void cursorWordBackward(bool mark); + void home(bool mark); + void end(bool mark); + + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect cursorRect() const; + + qreal cursorToX(int cursor) const; + qreal cursorToX() const; + + bool isReadOnly() const; + void setReadOnly(bool enable); + + QString text() const; + void setText(const QString &); + + QString displayText() const; + + void backspace(); + void del(); + void deselect(); + void selectAll(); + void insert(const QString &); + void clear(); + void undo(); + void redo(); + void selectWordAtPos(int); + + uint echoMode() const; + void setEchoMode(uint mode); + + void setMaxLength(int maxLength); + int maxLength() const; + + const QValidator *validator() const; + void setValidator(const QValidator *); + +#ifndef QT_NO_COMPLETER + QCompleter *completer() const; + void setCompleter(const QCompleter*); + void complete(int key); +#endif + + void setCursorPosition(int pos); + int cursorPosition() const; + + bool hasAcceptableInput() const; + bool fixup(); + + QString inputMask() const; + void setInputMask(const QString &mask); + + // input methods +#ifndef QT_NO_IM + bool composeMode() const; + void setPreeditArea(int cursor, const QString &text); +#endif + + QString preeditAreaText() const; + + void updatePasswordEchoEditing(bool editing); + bool passwordEchoEditing() const; + + QChar passwordCharacter() const; + void setPasswordCharacter(const QChar &character); + + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection(Qt::LayoutDirection direction); + void setFont(const QFont &font); + + void processInputMethodEvent(QInputMethodEvent *event); + void processMouseEvent(QMouseEvent* ev); + void processKeyEvent(QKeyEvent* ev); + + int cursorBlinkPeriod() const; + void setCursorBlinkPeriod(int msec); + + enum DrawFlags { + DrawText = 0x01, + DrawSelections = 0x02, + DrawCursor = 0x04, + DrawAll = DrawText | DrawSelections | DrawCursor + }; + void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll); + + bool processEvent(QEvent* ev); + + bool emitingEditingFinished;//Needed in QLineEdit FocusOut event +private: + void init(const QString&); + void removeSelectedText(); + void p_setText(const QString& txt, int pos = -1, bool edited = true); + void updateDisplayText(); + + void p_insert(const QString& s); + void p_del(bool wasBackspace = false); + void p_remove(int pos); + inline void p_deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } + void p_undo(int until = -1); + void p_redo(); + + QString m_text; + QPalette m_palette; + int m_cursor; + int m_preeditCursor; + int m_cursorWidth; + Qt::LayoutDirection m_layoutDirection; + uint hideCursor : 1; // used to hide the m_cursor inside preedit areas + uint separator : 1; + uint readOnly : 1; + uint dragEnabled : 1; + uint m_echoMode : 2; + uint textDirty : 1; + uint selDirty : 1; + uint validInput : 1; + int m_blinkPeriod; // 0 for non-blinking cursor + int m_blinkTimer; + int m_deleteAllTimer; + int m_blinkStatus; + int m_ascent; + int m_maxLength; + int lastCursorPos; + QList transactions; + QPoint m_tripleClick; + int m_tripleClickTimer; + + void emitCursorPositionChanged(); + + bool finishChange(int validateFromState = -1, bool update = false, bool edited = true); + + QPointer m_validator; + QPointer m_completer; +#ifndef QT_NO_COMPLETER + bool advanceToEnabledItem(int dir); +#endif + + struct MaskInputData { + enum Casemode { NoCaseMode, Upper, Lower }; + QChar maskChar; // either the separator char or the inputmask + bool separator; + Casemode caseMode; + }; + QString m_inputMask; + QChar blank; + MaskInputData *maskData; + + + // undo/redo handling + enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; + struct Command { + inline Command() {} + inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} + uint type : 4; + QChar uc; + int pos, selStart, selEnd; + }; + int modifiedState; + int undoState; + QVector history; + void addCommand(const Command& cmd); + + inline void separate() { separator = true; } + + // selection + int selstart, selend; + + // masking + void parseInputMask(const QString &maskFields); + bool isValidInput(QChar key, QChar mask) const; + bool hasAcceptableInput(const QString &text) const; + QString maskString(uint pos, const QString &str, bool clear = false) const; + QString clearString(uint pos, uint len) const; + QString stripString(const QString &str) const; + int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; + + + // complex text layout + QTextLayout textLayout; + + bool m_passwordEchoEditing; + QChar m_passwordCharacter; + +Q_SIGNALS: + void cursorPositionChanged(int, int); + void selectionChanged(); + + void displayTextChanged(const QString &); + void textChanged(const QString &); + void textEdited(const QString &); + + void resetInputContext(); + + void accepted(); + void editingFinished(); + void updateNeeded(const QRect &); +protected: + virtual void timerEvent ( QTimerEvent * event ); +private slots: + void _q_clipboardChanged(); + void _q_deleteSelected(); + +}; + +inline int QLineControl::nextMaskBlank(int pos) +{ + int c = findInMask(pos, true, false); + separator |= (c != pos); + return (c != -1 ? c : m_maxLength); +} + +inline int QLineControl::prevMaskBlank(int pos) +{ + int c = findInMask(pos, false, false); + separator |= (c != pos); + return (c != -1 ? c : 0); +} + +inline bool QLineControl::isUndoAvailable() const +{ + return !readOnly && undoState; +} + +inline bool QLineControl::isRedoAvailable() const +{ + return !readOnly && undoState < (int)history.size(); +} + +inline void QLineControl::clearUndo() +{ + history.clear(); + modifiedState = undoState = 0; +} + +inline bool QLineControl::isModified() const +{ + return modifiedState != undoState; +} + +inline void QLineControl::setModified(bool modified) +{ + modifiedState = modified ? -1 : undoState; +} + +inline bool QLineControl::allSelected() const +{ + return !m_text.isEmpty() && selstart == 0 && selend == (int)m_text.length(); +} + +inline bool QLineControl::hasSelectedText() const +{ + return !m_text.isEmpty() && selend > selstart; +} + +inline int QLineControl::width() const +{ + return qRound(textLayout.lineAt(0).width()) + 1; +} + +inline int QLineControl::height() const +{ + return qRound(textLayout.lineAt(0).height()) + 1; +} + +inline int QLineControl::ascent() const +{ + return m_ascent; +} + +inline QString QLineControl::selectedText() const +{ + if (hasSelectedText()) + return m_text.mid(selstart, selend - selstart); + return QString(); +} + +inline QString QLineControl::textBeforeSelection() const +{ + if (hasSelectedText()) + return m_text.left(selstart); + return QString(); +} + +inline QString QLineControl::textAfterSelection() const +{ + if (hasSelectedText()) + return m_text.mid(selend); + return QString(); +} + +inline int QLineControl::selectionStart() const +{ + return hasSelectedText() ? selstart : -1; +} + +inline int QLineControl::selectionEnd() const +{ + return hasSelectedText() ? selend : -1; +} + +inline int QLineControl::start() const +{ + return 0; +} + +inline int QLineControl::end() const +{ + return m_text.length(); +} + +inline void QLineControl::removeSelection() +{ + int priorState = undoState; + removeSelectedText(); + finishChange(priorState); +} + +inline bool QLineControl::inSelection(int x) const +{ + if (selstart >= selend) return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; +} + +inline int QLineControl::cursor() const +{ + return m_cursor; +} + +inline int QLineControl::preeditCursor() const +{ + return m_preeditCursor; +} + +inline int QLineControl::cursorWidth() const +{ + return m_cursorWidth; +} + +inline void QLineControl::setCursorWidth(int value) +{ + m_cursorWidth = value; +} + +inline void QLineControl::cursorForward(bool mark, int steps) +{ + int c = m_cursor; + if (steps > 0) { + while(steps--) + c = textLayout.nextCursorPosition(c); + } else if (steps < 0) { + while (steps++) + c = textLayout.previousCursorPosition(c); + } + moveCursor(c, mark); +} + +inline void QLineControl::cursorWordForward(bool mark) +{ + moveCursor(textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); +} + +inline void QLineControl::home(bool mark) +{ + moveCursor(0, mark); +} + +inline void QLineControl::end(bool mark) +{ + moveCursor(text().length(), mark); +} + +inline void QLineControl::cursorWordBackward(bool mark) +{ + moveCursor(textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); +} + +inline qreal QLineControl::cursorToX(int cursor) const +{ + return textLayout.lineAt(0).cursorToX(cursor); +} + +inline qreal QLineControl::cursorToX() const +{ + return cursorToX(m_cursor); +} + +inline bool QLineControl::isReadOnly() const +{ + return readOnly; +} + +inline void QLineControl::setReadOnly(bool enable) +{ + readOnly = enable; +} + +inline QString QLineControl::text() const +{ + QString res = maskData ? stripString(m_text) : m_text; + return (res.isNull() ? QString::fromLatin1("") : res); +} + +inline void QLineControl::setText(const QString &txt) +{ + p_setText(txt, -1, false); +} + +inline QString QLineControl::displayText() const +{ + return textLayout.text(); +} + +inline void QLineControl::deselect() +{ + p_deselect(); finishChange(); +} + +inline void QLineControl::selectAll() +{ + selstart = selend = m_cursor = 0; moveCursor(m_text.length(), true); +} + +inline void QLineControl::undo() +{ + p_undo(), finishChange(-1, true); +} + +inline void QLineControl::redo() +{ + p_redo(), finishChange(); +} + +inline uint QLineControl::echoMode() const +{ + return m_echoMode; +} + +inline void QLineControl::setEchoMode(uint mode) +{ + m_echoMode = mode; + m_passwordEchoEditing = false; + updateDisplayText(); +} + +inline void QLineControl::setMaxLength(int maxLength) +{ + if (maskData) + return; + m_maxLength = maxLength; + setText(m_text); +} + +inline int QLineControl::maxLength() const +{ + return m_maxLength; +} + +inline const QValidator *QLineControl::validator() const +{ + return m_validator; +} + +inline void QLineControl::setValidator(const QValidator *v) +{ + m_validator = const_cast(v); +} + +#ifndef QT_NO_COMPLETER +inline QCompleter *QLineControl::completer() const +{ + return m_completer; +} + +/* Note that you must set the widget for the completer seperately */ +inline void QLineControl::setCompleter(const QCompleter* c) +{ + m_completer = const_cast(c); +} +#endif + +inline void QLineControl::setCursorPosition(int pos) +{ + if (pos < 0) pos = 0; + if (pos < m_text.length()) + moveCursor(pos); +} + +inline int QLineControl::cursorPosition() const +{ + return m_cursor; +} + +inline bool QLineControl::hasAcceptableInput() const +{ + return hasAcceptableInput(m_text); +} + +inline QString QLineControl::inputMask() const +{ + return maskData ? m_inputMask + QLatin1Char(';') + blank : QString(); +} + +inline void QLineControl::setInputMask(const QString &mask) +{ + parseInputMask(mask); + if (maskData) + moveCursor(nextMaskBlank(0)); +} + +// input methods +#ifndef QT_NO_IM +inline bool QLineControl::composeMode() const +{ + return !textLayout.preeditAreaText().isEmpty(); +} + +inline void QLineControl::setPreeditArea(int cursor, const QString &text) +{ + textLayout.setPreeditArea(cursor, text); +} +#endif + +inline QString QLineControl::preeditAreaText() const +{ + return textLayout.preeditAreaText(); +} + +inline bool QLineControl::passwordEchoEditing() const +{ + return m_passwordEchoEditing; +} + +inline QChar QLineControl::passwordCharacter() const +{ + return m_passwordCharacter; +} + +inline void QLineControl::setPasswordCharacter(const QChar &character) +{ + m_passwordCharacter = character; + updateDisplayText(); +} + +inline Qt::LayoutDirection QLineControl::layoutDirection() const +{ + return m_layoutDirection; +} + +inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction) +{ + if (direction != m_layoutDirection) { + m_layoutDirection = direction; + updateDisplayText(); + } +} + +inline void QLineControl::setFont(const QFont &font) +{ + textLayout.setFont(font); + updateDisplayText(); +} + +inline int QLineControl::cursorBlinkPeriod() const +{ + return m_blinkPeriod; +} + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // QT_NO_LINEEDIT + + +#endif // QLINECONTROL_P_H diff --git a/src/gui/widgets/qlinecontrol_p_p.h b/src/gui/widgets/qlinecontrol_p_p.h new file mode 100644 index 0000000..e76794b --- /dev/null +++ b/src/gui/widgets/qlinecontrol_p_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINECONTROL_P_P_H +#define QLINECONTROL_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qobject_p.h" +#include "QtGui/qtextlayout.h" + +QT_BEGIN_NAMESPACE + +class QMimeData; +class QAbstractScrollArea; +class QInputContext; + +class QLineControlPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QLineControl) +public: + QLineControlPrivate() + : cursor(0), preeditCursor(0), cursorWidth(1), cursorTimer(0), + maxLength(32767), modifiedState(0), undoState(0), + selStart(0), selEnd(0), textInteractionFlags(0), + cursorVisible(0), hideCursor(0), echoMode(0) + {} + + QPalette palette; + QVector history; + QTextLayout textLayout; // display text + QString text; + + int cursor; + int preeditCursor; + int lastCursorPos; + int cursorWidth; + int cursorTimer; + + int maxLength; + + int modifiedState; + int undoState; + + int selStart, selEnd; + + Qt::TextInteractionFlags textInteractionFlags; + + // keep together and at end + uint cursorVisible : 1; + uint hideCursor : 1; // used to hide the cursor inside preedit areas + uint echoMode : 2; +}; + +QT_END_NAMESPACE + +#endif // QLINECONTROL_P_H + diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index d1067a8..baaad32 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -86,21 +86,12 @@ #include -#define verticalMargin 1 -#define horizontalMargin 2 - QT_BEGIN_NAMESPACE #ifdef Q_WS_MAC extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp #endif -static inline bool shouldEnableInputMethod(QLineEdit *lineedit) -{ - const QLineEdit::EchoMode mode = lineedit->echoMode(); - return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit); -} - /*! Initialize \a option with the values from this QLineEdit. This method is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want @@ -122,7 +113,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const : 0; option->midLineWidth = 0; option->state |= QStyle::State_Sunken; - if (d->readOnly) + if (d->control->isReadOnly()) option->state |= QStyle::State_ReadOnly; #ifdef QT_KEYPAD_NAVIGATION if (hasEditFocus()) @@ -350,14 +341,14 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* { Q_D(QLineEdit); setObjectName(QString::fromAscii(name)); - d->parseInputMask(inputMask); - if (d->maskData) { - QString ms = d->maskString(0, contents); - d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length())); - d->cursor = d->nextMaskBlank(ms.length()); - } else { + //d->control->parseInputMask(inputMask); + //if (d->control->maskData) { + // QString ms = d->control->maskString(0, contents); + // d->init(ms + d->control->clearString(ms.length(), d->control->maxLength() - ms.length())); + // d->control->moveCursor(d->control->nextMaskBlank(ms.length())); + // } else { d->init(contents); - } + // } } #endif @@ -388,19 +379,13 @@ QLineEdit::~QLineEdit() QString QLineEdit::text() const { Q_D(const QLineEdit); - QString res = d->text; - if (d->maskData) - res = d->stripString(d->text); - return (res.isNull() ? QString::fromLatin1("") : res); + return d->control->text(); } void QLineEdit::setText(const QString& text) { Q_D(QLineEdit); - d->setText(text, -1, false); -#ifdef QT_KEYPAD_NAVIGATION - d->origText = d->text; -#endif + d->control->setText(text); } @@ -421,17 +406,7 @@ void QLineEdit::setText(const QString& text) QString QLineEdit::displayText() const { Q_D(const QLineEdit); - if (d->echoMode == NoEcho) - return QString::fromLatin1(""); - QString res = d->text; - - if (d->echoMode == Password || (d->echoMode == PasswordEchoOnEdit - && !d->passwordEchoEditing)) { - QStyleOptionFrameV2 opt; - initStyleOption(&opt); - res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)); - } - return (res.isNull() ? QString::fromLatin1("") : res); + return d->control->displayText(); } @@ -456,20 +431,15 @@ QString QLineEdit::displayText() const int QLineEdit::maxLength() const { Q_D(const QLineEdit); - return d->maxLength; + return d->control->maxLength(); } void QLineEdit::setMaxLength(int maxLength) { Q_D(QLineEdit); - if (d->maskData) - return; - d->maxLength = maxLength; - setText(d->text); + d->control->setMaxLength(maxLength); } - - /*! \property QLineEdit::frame \brief whether the line edit draws itself with a frame @@ -536,22 +506,20 @@ void QLineEdit::setFrame(bool enable) QLineEdit::EchoMode QLineEdit::echoMode() const { Q_D(const QLineEdit); - return (EchoMode) d->echoMode; + return (EchoMode) d->control->echoMode(); } void QLineEdit::setEchoMode(EchoMode mode) { Q_D(QLineEdit); - if (mode == (EchoMode)d->echoMode) + if (mode == (EchoMode)d->control->echoMode()) return; - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); - d->echoMode = mode; - d->passwordEchoEditing = false; - d->updateTextLayout(); + setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod()); + d->control->setEchoMode(mode); update(); #ifdef Q_WS_MAC if (hasFocus()) - qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho); + qt_mac_secure_keyboard(mode == Password || mode == NoEcho); #endif } @@ -567,7 +535,7 @@ void QLineEdit::setEchoMode(EchoMode mode) const QValidator * QLineEdit::validator() const { Q_D(const QLineEdit); - return d->validator; + return d->control->validator(); } /*! @@ -585,7 +553,7 @@ const QValidator * QLineEdit::validator() const void QLineEdit::setValidator(const QValidator *v) { Q_D(QLineEdit); - d->validator = const_cast(v); + d->control->setValidator(v); } #endif // QT_NO_VALIDATOR @@ -609,23 +577,23 @@ void QLineEdit::setValidator(const QValidator *v) void QLineEdit::setCompleter(QCompleter *c) { Q_D(QLineEdit); - if (c == d->completer) + if (c == d->control->completer()) return; - if (d->completer) { - disconnect(d->completer, 0, this, 0); - d->completer->setWidget(0); - if (d->completer->parent() == this) - delete d->completer; + if (d->control->completer()) { + disconnect(d->control->completer(), 0, this, 0); + d->control->completer()->setWidget(0); + if (d->control->completer()->parent() == this) + delete d->control->completer(); } - d->completer = c; + d->control->setCompleter(c); if (!c) return; if (c->widget() == 0) c->setWidget(this); if (hasFocus()) { - QObject::connect(d->completer, SIGNAL(activated(QString)), + QObject::connect(d->control->completer(), SIGNAL(activated(QString)), this, SLOT(setText(QString))); - QObject::connect(d->completer, SIGNAL(highlighted(QString)), + QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), this, SLOT(_q_completionHighlighted(QString))); } } @@ -638,83 +606,9 @@ void QLineEdit::setCompleter(QCompleter *c) QCompleter *QLineEdit::completer() const { Q_D(const QLineEdit); - return d->completer; -} - -// looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the -// current row based. dir=0 indicates a new completion prefix was set. -bool QLineEditPrivate::advanceToEnabledItem(int dir) -{ - int start = completer->currentRow(); - if (start == -1) - return false; - int i = start + dir; - if (dir == 0) dir = 1; - do { - if (!completer->setCurrentRow(i)) { - if (!completer->wrapAround()) - break; - i = i > 0 ? 0 : completer->completionCount() - 1; - } else { - QModelIndex currentIndex = completer->currentIndex(); - if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled) - return true; - i += dir; - } - } while (i != start); - - completer->setCurrentRow(start); // restore - return false; -} - -void QLineEditPrivate::complete(int key) -{ - if (!completer || readOnly || echoMode != QLineEdit::Normal) - return; - - if (completer->completionMode() == QCompleter::InlineCompletion) { - if (key == Qt::Key_Backspace) - return; - int n = 0; - if (key == Qt::Key_Up || key == Qt::Key_Down) { - if (selend != 0 && selend != text.length()) - return; - QString prefix = hasSelectedText() ? text.left(selstart) : text; - if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0 - || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) { - completer->setCompletionPrefix(prefix); - } else { - n = (key == Qt::Key_Up) ? -1 : +1; - } - } else { - completer->setCompletionPrefix(text); - } - if (!advanceToEnabledItem(n)) - return; - } else { -#ifndef QT_KEYPAD_NAVIGATION - if (text.isEmpty()) { - completer->popup()->hide(); - return; - } -#endif - completer->setCompletionPrefix(text); - } - - completer->complete(); + return d->control->completer(); } -void QLineEditPrivate::_q_completionHighlighted(QString newText) -{ - Q_Q(QLineEdit); - if (completer->completionMode() != QCompleter::InlineCompletion) - q->setText(newText); - else { - int c = cursor; - q->setText(text.left(c) + newText.mid(c)); - q->setSelection(text.length(), c - newText.length()); - } -} #endif // QT_NO_COMPLETER /*! @@ -729,10 +623,10 @@ QSize QLineEdit::sizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm(font()); - int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin + int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin + d->topTextMargin + d->bottomTextMargin + d->topmargin + d->bottommargin; - int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin + int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin + d->leftTextMargin + d->rightTextMargin + d->leftmargin + d->rightmargin; // "some" QStyleOptionFrameV2 opt; @@ -753,7 +647,7 @@ QSize QLineEdit::minimumSizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm = fontMetrics(); - int h = fm.height() + qMax(2*verticalMargin, fm.leading()) + int h = fm.height() + qMax(2*d->verticalMargin, fm.leading()) + d->topmargin + d->bottommargin; int w = fm.maxWidth() + d->leftmargin + d->rightmargin; QStyleOptionFrameV2 opt; @@ -775,17 +669,13 @@ QSize QLineEdit::minimumSizeHint() const int QLineEdit::cursorPosition() const { Q_D(const QLineEdit); - return d->cursor; + return d->control->cursorPosition(); } void QLineEdit::setCursorPosition(int pos) { Q_D(QLineEdit); - if (pos < 0) - pos = 0; - - if (pos <= d->text.length()) - d->moveCursor(pos); + d->control->setCursorPosition(pos); } /*! @@ -807,22 +697,12 @@ int QLineEdit::cursorPositionAt(const QPoint &pos) bool QLineEdit::validateAndSet(const QString &newText, int newPos, int newMarkAnchor, int newMarkDrag) { - Q_D(QLineEdit); - int priorState = d->undoState; - d->selstart = 0; - d->selend = d->text.length(); - d->removeSelectedText(); - d->insert(newText); - d->finishChange(priorState); - if (d->undoState > priorState) { - d->cursor = newPos; - d->selstart = qMin(newMarkAnchor, newMarkDrag); - d->selend = qMax(newMarkAnchor, newMarkDrag); - update(); - d->emitCursorPositionChanged(); - return true; - } - return false; + // Note, this doesn't validate', but then neither + // does the suggested functions above in the docs. + setText(newText); + setCursorPosition(newPos); + setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); + return true; } #endif //QT3_SUPPORT @@ -863,15 +743,7 @@ void QLineEdit::setAlignment(Qt::Alignment alignment) void QLineEdit::cursorForward(bool mark, int steps) { Q_D(QLineEdit); - int cursor = d->cursor; - if (steps > 0) { - while(steps--) - cursor = d->textLayout.nextCursorPosition(cursor); - } else if (steps < 0) { - while (steps++) - cursor = d->textLayout.previousCursorPosition(cursor); - } - d->moveCursor(cursor, mark); + d->control->cursorForward(mark, steps); } @@ -896,7 +768,7 @@ void QLineEdit::cursorBackward(bool mark, int steps) void QLineEdit::cursorWordForward(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark); + d->control->cursorWordForward(mark); } /*! @@ -909,7 +781,7 @@ void QLineEdit::cursorWordForward(bool mark) void QLineEdit::cursorWordBackward(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark); + d->control->cursorWordBackward(mark); } @@ -924,26 +796,7 @@ void QLineEdit::cursorWordBackward(bool mark) void QLineEdit::backspace() { Q_D(QLineEdit); - int priorState = d->undoState; - if (d->hasSelectedText()) { - d->removeSelectedText(); - } else if (d->cursor) { - --d->cursor; - if (d->maskData) - d->cursor = d->prevMaskBlank(d->cursor); - QChar uc = d->text.at(d->cursor); - if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { - // second half of a surrogate, check if we have the first half as well, - // if yes delete both at once - uc = d->text.at(d->cursor - 1); - if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { - d->del(true); - --d->cursor; - } - } - d->del(true); - } - d->finishChange(priorState); + d->control->backspace(); } /*! @@ -957,15 +810,7 @@ void QLineEdit::backspace() void QLineEdit::del() { Q_D(QLineEdit); - int priorState = d->undoState; - if (d->hasSelectedText()) { - d->removeSelectedText(); - } else { - int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor; - while (n--) - d->del(); - } - d->finishChange(priorState); + d->control->del(); } /*! @@ -980,7 +825,7 @@ void QLineEdit::del() void QLineEdit::home(bool mark) { Q_D(QLineEdit); - d->moveCursor(0, mark); + d->control->home(mark); } /*! @@ -995,7 +840,7 @@ void QLineEdit::home(bool mark) void QLineEdit::end(bool mark) { Q_D(QLineEdit); - d->moveCursor(d->text.length(), mark); + d->control->end(mark); } @@ -1020,16 +865,13 @@ void QLineEdit::end(bool mark) bool QLineEdit::isModified() const { Q_D(const QLineEdit); - return d->modifiedState != d->undoState; + return d->control->isModified(); } void QLineEdit::setModified(bool modified) { Q_D(QLineEdit); - if (modified) - d->modifiedState = -1; - else - d->modifiedState = d->undoState; + d->control->setModified(modified); } @@ -1057,7 +899,7 @@ Use setModified(false) instead. bool QLineEdit::hasSelectedText() const { Q_D(const QLineEdit); - return d->hasSelectedText(); + return d->control->hasSelectedText(); } /*! @@ -1075,9 +917,7 @@ bool QLineEdit::hasSelectedText() const QString QLineEdit::selectedText() const { Q_D(const QLineEdit); - if (d->hasSelectedText()) - return d->text.mid(d->selstart, d->selend - d->selstart); - return QString(); + return d->control->selectedText(); } /*! @@ -1090,7 +930,7 @@ QString QLineEdit::selectedText() const int QLineEdit::selectionStart() const { Q_D(const QLineEdit); - return d->hasSelectedText() ? d->selstart : -1; + return d->control->selectionStart(); } @@ -1120,9 +960,10 @@ void QLineEdit::setEdited(bool on) { setModified(on); } int QLineEdit::characterAt(int xpos, QChar *chr) const { Q_D(const QLineEdit); - int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin); - if (chr && pos < (int) d->text.length()) - *chr = d->text.at(pos); + int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + d->horizontalMargin); + QString txt = d->control->text(); + if (chr && pos < (int) txt.length()) + *chr = txt.at(pos); return pos; } @@ -1133,9 +974,9 @@ int QLineEdit::characterAt(int xpos, QChar *chr) const bool QLineEdit::getSelection(int *start, int *end) { Q_D(QLineEdit); - if (d->hasSelectedText() && start && end) { - *start = d->selstart; - *end = d->selend; + if (d->control->hasSelectedText() && start && end) { + *start = selectionStart(); + *end = *start + selectedText().length(); return true; } return false; @@ -1153,30 +994,19 @@ bool QLineEdit::getSelection(int *start, int *end) void QLineEdit::setSelection(int start, int length) { Q_D(QLineEdit); - if (start < 0 || start > (int)d->text.length()) { + if (start < 0 || start > (int)d->control->text().length()) { qWarning("QLineEdit::setSelection: Invalid start position (%d)", start); return; - } else { - if (length > 0) { - d->selstart = start; - d->selend = qMin(start + length, (int)d->text.length()); - d->cursor = d->selend; - } else { - d->selstart = qMax(start + length, 0); - d->selend = start; - d->cursor = d->selstart; - } } - if (d->hasSelectedText()){ + d->control->setSelection(start, length); + + if (d->control->hasSelectedText()){ QStyleOptionFrameV2 opt; initStyleOption(&opt); if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) d->setCursorVisible(false); } - - update(); - d->emitCursorPositionChanged(); } @@ -1192,7 +1022,7 @@ void QLineEdit::setSelection(int start, int length) bool QLineEdit::isUndoAvailable() const { Q_D(const QLineEdit); - return d->isUndoAvailable(); + return d->control->isUndoAvailable(); } /*! @@ -1208,7 +1038,7 @@ bool QLineEdit::isUndoAvailable() const bool QLineEdit::isRedoAvailable() const { Q_D(const QLineEdit); - return d->isRedoAvailable(); + return d->control->isRedoAvailable(); } /*! @@ -1244,7 +1074,7 @@ void QLineEdit::setDragEnabled(bool b) bool QLineEdit::hasAcceptableInput() const { Q_D(const QLineEdit); - return d->hasAcceptableInput(d->text); + return d->control->hasAcceptableInput(); } /*! @@ -1350,15 +1180,13 @@ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) con QString QLineEdit::inputMask() const { Q_D(const QLineEdit); - return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString()); + return d->control->inputMask(); } void QLineEdit::setInputMask(const QString &inputMask) { Q_D(QLineEdit); - d->parseInputMask(inputMask); - if (d->maskData) - d->moveCursor(d->nextMaskBlank(0)); + d->control->setInputMask(inputMask); } /*! @@ -1373,8 +1201,7 @@ void QLineEdit::setInputMask(const QString &inputMask) void QLineEdit::selectAll() { Q_D(QLineEdit); - d->selstart = d->selend = d->cursor = 0; - d->moveCursor(d->text.length(), true); + d->control->selectAll(); } /*! @@ -1386,8 +1213,7 @@ void QLineEdit::selectAll() void QLineEdit::deselect() { Q_D(QLineEdit); - d->deselect(); - d->finishChange(); + d->control->deselect(); } @@ -1402,10 +1228,7 @@ void QLineEdit::insert(const QString &newText) { // q->resetInputContext(); //#### FIX ME IN QT Q_D(QLineEdit); - int priorState = d->undoState; - d->removeSelectedText(); - d->insert(newText); - d->finishChange(priorState); + d->control->insert(newText); } /*! @@ -1416,13 +1239,8 @@ void QLineEdit::insert(const QString &newText) void QLineEdit::clear() { Q_D(QLineEdit); - int priorState = d->undoState; resetInputContext(); - d->selstart = 0; - d->selend = d->text.length(); - d->removeSelectedText(); - d->separate(); - d->finishChange(priorState, /*update*/false, /*edited*/false); + d->control->clear(); } /*! @@ -1435,8 +1253,7 @@ void QLineEdit::undo() { Q_D(QLineEdit); resetInputContext(); - d->undo(); - d->finishChange(-1, true); + d->control->undo(); } /*! @@ -1447,8 +1264,7 @@ void QLineEdit::redo() { Q_D(QLineEdit); resetInputContext(); - d->redo(); - d->finishChange(); + d->control->redo(); } @@ -1470,16 +1286,16 @@ void QLineEdit::redo() bool QLineEdit::isReadOnly() const { Q_D(const QLineEdit); - return d->readOnly; + return d->control->isReadOnly(); } void QLineEdit::setReadOnly(bool enable) { Q_D(QLineEdit); - if (d->readOnly != enable) { - d->readOnly = enable; - setAttribute(Qt::WA_MacShowFocusRect, !d->readOnly); - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); + if (d->control->isReadOnly() != enable) { + d->control->setReadOnly(enable); + setAttribute(Qt::WA_MacShowFocusRect, !enable); + setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod()); #ifndef QT_NO_CURSOR setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor); #endif @@ -1518,7 +1334,7 @@ void QLineEdit::cut() void QLineEdit::copy() const { Q_D(const QLineEdit); - d->copy(); + d->control->copy(); } /*! @@ -1535,23 +1351,7 @@ void QLineEdit::copy() const void QLineEdit::paste() { Q_D(QLineEdit); - if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) { - // Clear the edit and reset to normal echo mode when pasting; the echo - // mode switches back when the edit loses focus. ### changes a public - // property, resets current content - d->updatePasswordEchoEditing(true); - clear(); - } - insert(QApplication::clipboard()->text(QClipboard::Clipboard)); -} - -void QLineEditPrivate::copy(bool clipboard) const -{ - Q_Q(const QLineEdit); - QString t = q->selectedText(); - if (!t.isEmpty() && echoMode == QLineEdit::Normal) { - QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection); - } + d->control->paste(); } #endif // !QT_NO_CLIPBOARD @@ -1561,57 +1361,10 @@ void QLineEditPrivate::copy(bool clipboard) const bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); -#ifndef QT_NO_SHORTCUT - if (e->type() == QEvent::ShortcutOverride && !d->readOnly) { - QKeyEvent* ke = (QKeyEvent*) e; - if (ke == QKeySequence::Copy - || ke == QKeySequence::Paste - || ke == QKeySequence::Cut - || ke == QKeySequence::Redo - || ke == QKeySequence::Undo - || ke == QKeySequence::MoveToNextWord - || ke == QKeySequence::MoveToPreviousWord - || ke == QKeySequence::MoveToStartOfDocument - || ke == QKeySequence::MoveToEndOfDocument - || ke == QKeySequence::SelectNextWord - || ke == QKeySequence::SelectPreviousWord - || ke == QKeySequence::SelectStartOfLine - || ke == QKeySequence::SelectEndOfLine - || ke == QKeySequence::SelectStartOfBlock - || ke == QKeySequence::SelectEndOfBlock - || ke == QKeySequence::SelectStartOfDocument - || ke == QKeySequence::SelectAll - || ke == QKeySequence::SelectEndOfDocument) { - ke->accept(); - } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - ke->accept(); - } else { - switch (ke->key()) { - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - ke->accept(); - default: - break; - } - } - } - } else -#endif if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); - if (timerId == d->cursorTimer) { - QStyleOptionFrameV2 opt; - initStyleOption(&opt); - if(!hasSelectedText() - || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) - d->setCursorVisible(!d->cursorVisible); + if (false) { #ifndef QT_NO_DRAGANDDROP } else if (timerId == d->dndTimer.timerId()) { d->drag(); @@ -1619,62 +1372,20 @@ bool QLineEdit::event(QEvent * e) } else if (timerId == d->tripleClickTimer.timerId()) d->tripleClickTimer.stop(); -#ifdef QT_KEYPAD_NAVIGATION - else if (timerId == d->deleteAllTimer.timerId()) { - d->deleteAllTimer.stop(); - clear(); - } -#endif } else if (e->type() == QEvent::ContextMenu) { #ifndef QT_NO_IM - if (d->composeMode()) + if (d->control->composeMode()) return true; #endif - d->separate(); + //d->separate(); } else if (e->type() == QEvent::WindowActivate) { QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate())); + }else if(e->type() == QEvent::ShortcutOverride){ + d->control->processEvent(e); + }else if(e->type() == QEvent::LayoutDirectionChange){ + d->control->setLayoutDirection((layoutDirection())); } -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)e; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((e->type() == QEvent::KeyRelease) - && !isReadOnly() - && d->deleteAllTimer.isActive()) { - d->deleteAllTimer.stop(); - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - if (!d->cursorTimer) { - int cft = QApplication::cursorFlashTime(); - d->cursorTimer = cft ? startTimer(cft/2) : -1; - } - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false); - if (d->cursorTimer > 0) - killTimer(d->cursorTimer); - d->cursorTimer = 0; - - if (!d->emitingEditingFinished) { - if (hasAcceptableInput() || d->fixup()) { - d->emitingEditingFinished = true; - emit editingFinished(); - d->emitingEditingFinished = false; - } - } - } - } -#endif + return QWidget::event(e); } @@ -1684,37 +1395,35 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->button() == Qt::RightButton) return; #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { setEditFocus(true); // Get the completion list to pop up. - if (d->completer) - d->completer->complete(); + if (d->control->completer()) + d->control->completer()->complete(); } #endif if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() < QApplication::startDragDistance()) { selectAll(); - return; + return; } bool mark = e->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(e->pos().x()); #ifndef QT_NO_DRAGANDDROP - if (!mark && d->dragEnabled && d->echoMode == Normal && - e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) { - d->cursor = cursor; - update(); + if (!mark && d->dragEnabled && d->control->echoMode() == Normal && + e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) { + d->control->moveCursor(cursor); d->dndPos = e->pos(); if (!d->dndTimer.isActive()) d->dndTimer.start(QApplication::startDragTime(), this); - d->emitCursorPositionChanged(); } else #endif { - d->moveCursor(cursor, mark); + d->control->moveCursor(cursor, mark); } } @@ -1724,7 +1433,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP @@ -1734,7 +1443,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) } else #endif { - d->moveCursor(d->xToPos(e->pos().x()), true); + d->control->moveCursor(d->xToPos(e->pos().x()), true); } } } @@ -1745,26 +1454,19 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; + + if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP - if (e->button() == Qt::LeftButton) { if (d->dndTimer.isActive()) { - d->dndTimer.stop(); - deselect(); - return; - } - } + if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) + d->drag(); + } else #endif -#ifndef QT_NO_CLIPBOARD - if (QApplication::clipboard()->supportsSelection()) { - if (e->button() == Qt::LeftButton) { - d->copy(false); - } else if (!d->readOnly && e->button() == Qt::MidButton) { - d->deselect(); - insert(QApplication::clipboard()->text(QClipboard::Selection)); + { + d->control->moveCursor(d->xToPos(e->pos().x()), true); } } -#endif } /*! \reimp @@ -1773,16 +1475,9 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; if (e->button() == Qt::LeftButton) { - deselect(); - d->cursor = d->xToPos(e->pos().x()); - d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords); - // ## text layout should support end of words. - int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords); - while (end > d->cursor && d->text[end-1].isSpace()) - --end; - d->moveCursor(end, true); + d->control->selectWordAtPos(d->xToPos(e->pos().x())); d->tripleClickTimer.start(QApplication::doubleClickInterval(), this); d->tripleClick = e->pos(); } @@ -1822,65 +1517,15 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) void QLineEdit::keyPressEvent(QKeyEvent *event) { Q_D(QLineEdit); - - bool inlineCompletionAccepted = false; - -#ifndef QT_NO_COMPLETER - if (d->completer) { - QCompleter::CompletionMode completionMode = d->completer->completionMode(); - if ((completionMode == QCompleter::PopupCompletion - || completionMode == QCompleter::UnfilteredPopupCompletion) - &&d->completer->popup() - && d->completer->popup()->isVisible()) { - // The following keys are forwarded by the completer to the widget - // Ignoring the events lets the completer provide suitable default behavior - switch (event->key()) { - case Qt::Key_Escape: - event->ignore(); - return; - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_F4: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - d->completer->popup()->hide(); // just hide. will end up propagating to parent - default: - break; // normal key processing - } - } else if (completionMode == QCompleter::InlineCompletion) { - switch (event->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_F4: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - if (!d->completer->currentCompletion().isEmpty() && d->selend > d->selstart - && d->selend == d->text.length()) { - setText(d->completer->currentCompletion()); - inlineCompletionAccepted = true; - } - default: - break; // normal key processing - } - } - } -#endif // QT_NO_COMPLETER - -#ifdef QT_KEYPAD_NAVIGATION + #ifdef QT_KEYPAD_NAVIGATION bool select = false; switch (event->key()) { case Qt::Key_Select: if (QApplication::keypadNavigationEnabled()) { if (hasEditFocus()) { setEditFocus(false); - if (d->completer && d->completer->popup()->isVisible()) - d->completer->popup()->hide(); + if (d->control->completer() && d->control->completer()->popup()->isVisible()) + d->control->completer()->popup()->hide(); select = true; } } @@ -1916,274 +1561,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) return; // Just start. No action. } #endif - - if (echoMode() == PasswordEchoOnEdit - && !d->passwordEchoEditing - && !isReadOnly() - && !event->text().isEmpty() -#ifdef QT_KEYPAD_NAVIGATION - && event->key() != Qt::Key_Select - && event->key() != Qt::Key_Up - && event->key() != Qt::Key_Down - && event->key() != Qt::Key_Back -#endif - && !(event->modifiers() & Qt::ControlModifier)) { - // Clear the edit and reset to normal echo mode while editing; the - // echo mode switches back when the edit loses focus. ### changes a - // public property, resets current content. dubious code; you can - // navigate with keys up, down, back, and select(?), but if you press - // "left" or "right" it clears? - d->updatePasswordEchoEditing(true); - clear(); - } - - d->setCursorVisible(true); - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - if (hasAcceptableInput() || d->fixup()) { - emit returnPressed(); - d->emitingEditingFinished = true; - emit editingFinished(); - d->emitingEditingFinished = false; - } - if (inlineCompletionAccepted) - event->accept(); - else - event->ignore(); - return; - } - bool unknown = false; - - if (false) { - } -#ifndef QT_NO_SHORTCUT - else if (event == QKeySequence::Undo) { - if (!d->readOnly) - undo(); - } - else if (event == QKeySequence::Redo) { - if (!d->readOnly) - redo(); - } - else if (event == QKeySequence::SelectAll) { - selectAll(); - } -#ifndef QT_NO_CLIPBOARD - else if (event == QKeySequence::Copy) { - copy(); - } - else if (event == QKeySequence::Paste) { - if (!d->readOnly) - paste(); - } - else if (event == QKeySequence::Cut) { - if (!d->readOnly) { - cut(); - } - } - else if (event == QKeySequence::DeleteEndOfLine) { - if (!d->readOnly) { - setSelection(d->cursor, d->text.size()); - copy(); - del(); - } - } -#endif //QT_NO_CLIPBOARD - else if (event == QKeySequence::MoveToStartOfLine) { - home(0); - } - else if (event == QKeySequence::MoveToEndOfLine) { - end(0); - } - else if (event == QKeySequence::SelectStartOfLine) { - home(1); - } - else if (event == QKeySequence::SelectEndOfLine) { - end(1); - } - else if (event == QKeySequence::MoveToNextChar) { -#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) - if (d->hasSelectedText()) { -#else - if (d->hasSelectedText() && d->completer - && d->completer->completionMode() == QCompleter::InlineCompletion) { -#endif - d->moveCursor(d->selend, false); - } else { - cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - } - else if (event == QKeySequence::SelectNextChar) { - cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - else if (event == QKeySequence::MoveToPreviousChar) { -#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) - if (d->hasSelectedText()) { -#else - if (d->hasSelectedText() && d->completer - && d->completer->completionMode() == QCompleter::InlineCompletion) { -#endif - d->moveCursor(d->selstart, false); - } else { - cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - } - else if (event == QKeySequence::SelectPreviousChar) { - cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1); - } - else if (event == QKeySequence::MoveToNextWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); - else - layoutDirection() == Qt::LeftToRight ? end(0) : home(0); - } - else if (event == QKeySequence::MoveToPreviousWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); - else if (!d->readOnly) { - layoutDirection() == Qt::LeftToRight ? home(0) : end(0); - } - } - else if (event == QKeySequence::SelectNextWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); - else - layoutDirection() == Qt::LeftToRight ? end(1) : home(1); - } - else if (event == QKeySequence::SelectPreviousWord) { - if (echoMode() == Normal) - layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); - else - layoutDirection() == Qt::LeftToRight ? home(1) : end(1); - } - else if (event == QKeySequence::Delete) { - if (!d->readOnly) - del(); - } - else if (event == QKeySequence::DeleteEndOfWord) { - if (!d->readOnly) { - cursorWordForward(true); - del(); - } - } - else if (event == QKeySequence::DeleteStartOfWord) { - if (!d->readOnly) { - cursorWordBackward(true); - del(); - } - } -#endif // QT_NO_SHORTCUT - else { -#ifdef Q_WS_MAC - if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { - Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); - if (myModifiers & Qt::ShiftModifier) { - if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) - || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) - || myModifiers == Qt::ShiftModifier) { - - event->key() == Qt::Key_Up ? home(1) : end(1); - } - } else { - if ((myModifiers == Qt::ControlModifier - || myModifiers == Qt::AltModifier - || myModifiers == Qt::NoModifier)) { - event->key() == Qt::Key_Up ? home(0) : end(0); - } - } - } -#endif - if (event->modifiers() & Qt::ControlModifier) { - switch (event->key()) { - case Qt::Key_Backspace: - if (!d->readOnly) { - cursorWordBackward(true); - del(); - } - break; -#ifndef QT_NO_COMPLETER - case Qt::Key_Up: - case Qt::Key_Down: - d->complete(event->key()); - break; -#endif -#if defined(Q_WS_X11) - case Qt::Key_E: - end(0); - break; - - case Qt::Key_U: - if (!d->readOnly) { - setSelection(0, d->text.size()); -#ifndef QT_NO_CLIPBOARD - copy(); -#endif - del(); - } - break; -#endif - default: - unknown = true; - } - } else { // ### check for *no* modifier - switch (event->key()) { - case Qt::Key_Backspace: - if (!d->readOnly) { - backspace(); -#ifndef QT_NO_COMPLETER - d->complete(Qt::Key_Backspace); -#endif - } - break; -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() - && !isReadOnly()) { - if (text().length() == 0) { - setText(d->origText); - - if (d->passwordEchoEditing) - d->updatePasswordEchoEditing(false); - - setEditFocus(false); - } else if (!d->deleteAllTimer.isActive()) { - d->deleteAllTimer.start(750, this); - } - } else { - unknown = true; - } - break; -#endif - - default: - unknown = true; - } - } - } - - if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { - setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); - d->updateTextLayout(); - update(); - unknown = false; - } - - if (unknown && !d->readOnly) { - QString t = event->text(); - if (!t.isEmpty() && t.at(0).isPrint() && - ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { - insert(t); -#ifndef QT_NO_COMPLETER - d->complete(event->key()); -#endif - event->accept(); - return; - } - } - - if (unknown) - event->ignore(); - else - event->accept(); + d->control->processKeyEvent(event); } /*! @@ -2197,50 +1575,17 @@ QRect QLineEdit::cursorRect() const return d->cursorRect(); } -/*! - This function is not intended as polymorphic usage. Just a shared code - fragment that calls QInputContext::mouseHandler for this - class. -*/ -bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e ) -{ -#if !defined QT_NO_IM - Q_Q(QLineEdit); - if ( composeMode() ) { - int tmp_cursor = xToPos(e->pos().x()); - int mousePos = tmp_cursor - cursor; - if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) { - mousePos = -1; - // don't send move events outside the preedit area - if ( e->type() == QEvent::MouseMove ) - return true; - } - - QInputContext *qic = q->inputContext(); - if ( qic ) - // may be causing reset() in some input methods - qic->mouseHandler(mousePos, e); - if (!textLayout.preeditAreaText().isEmpty()) - return true; - } -#else - Q_UNUSED(e); -#endif - - return false; -} - /*! \reimp */ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) { Q_D(QLineEdit); - if (d->readOnly) { + if (d->control->isReadOnly()) { e->ignore(); return; } - if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) { + if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) { // Clear the edit and reset to normal echo mode while entering input // method data; the echo mode switches back when the edit loses focus. // ### changes a public property, resets current content. @@ -2248,6 +1593,8 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) clear(); } + d->control->processInputMethodEvent(e); + #ifdef QT_KEYPAD_NAVIGATION // Focus in if currently in navigation focus on the widget // Only focus in on preedits, to allow input methods to @@ -2260,55 +1607,9 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) } #endif - int priorState = d->undoState; - d->removeSelectedText(); - - int c = d->cursor; // cursor position after insertion of commit string - if (e->replacementStart() <= 0) - c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength()); - - d->cursor += e->replacementStart(); - - // insert commit string - if (e->replacementLength()) { - d->selstart = d->cursor; - d->selend = d->selstart + e->replacementLength(); - d->removeSelectedText(); - } - if (!e->commitString().isEmpty()) - d->insert(e->commitString()); - - d->cursor = qMin(c, d->text.length()); - - d->textLayout.setPreeditArea(d->cursor, e->preeditString()); - d->preeditCursor = e->preeditString().length(); - d->hideCursor = false; - QList formats; - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Cursor) { - d->preeditCursor = a.start; - d->hideCursor = !a.length; - } else if (a.type == QInputMethodEvent::TextFormat) { - QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); - if (f.isValid()) { - QTextLayout::FormatRange o; - o.start = a.start + d->cursor; - o.length = a.length; - o.format = f; - formats.append(o); - } - } - } - d->textLayout.setAdditionalFormats(formats); - d->updateTextLayout(); - update(); - if (!e->commitString().isEmpty()) - d->emitCursorPositionChanged(); - d->finishChange(priorState); #ifndef QT_NO_COMPLETER if (!e->commitString().isEmpty()) - d->complete(Qt::Key_unknown); + d->control->complete(Qt::Key_unknown); #endif } @@ -2323,9 +1624,9 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const case Qt::ImFont: return font(); case Qt::ImCursorPosition: - return QVariant((d->selend - d->selstart == 0) ? d->cursor : d->selend); + return QVariant(d->control->hasSelectedText() ? d->control->selectionEnd() : d->control->cursor()); case Qt::ImSurroundingText: - return QVariant(d->text); + return QVariant(text()); case Qt::ImCurrentSelection: return QVariant(selectedText()); default: @@ -2342,36 +1643,34 @@ void QLineEdit::focusInEvent(QFocusEvent *e) if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason || e->reason() == Qt::ShortcutFocusReason) { - if (d->maskData) - d->moveCursor(d->nextMaskBlank(0)); - else if (!d->hasSelectedText()) + if (!d->control->inputMask().isEmpty()) + d->control->moveCursor(d->control->nextMaskBlank(0)); + else if (!d->control->hasSelectedText()) selectAll(); } #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)) #endif - if (!d->cursorTimer) { - int cft = QApplication::cursorFlashTime(); - d->cursorTimer = cft ? startTimer(cft/2) : -1; - } + int cft = QApplication::cursorFlashTime(); + d->control->setCursorBlinkPeriod(cft/2); QStyleOptionFrameV2 opt; initStyleOption(&opt); - if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty()) + if((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) d->setCursorVisible(true); #ifdef Q_WS_MAC - if (d->echoMode == Password || d->echoMode == NoEcho) + if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) qt_mac_secure_keyboard(true); #endif #ifdef QT_KEYPAD_NAVIGATION d->origText = d->text; #endif #ifndef QT_NO_COMPLETER - if (d->completer) { - d->completer->setWidget(this); - QObject::connect(d->completer, SIGNAL(activated(QString)), + if (d->control->completer()) { + d->control->completer()->setWidget(this); + QObject::connect(d->control->completer(), SIGNAL(activated(QString)), this, SLOT(setText(QString))); - QObject::connect(d->completer, SIGNAL(highlighted(QString)), + QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)), this, SLOT(_q_completionHighlighted(QString))); } #endif @@ -2384,7 +1683,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) void QLineEdit::focusOutEvent(QFocusEvent *e) { Q_D(QLineEdit); - if (d->passwordEchoEditing) { + if (d->control->passwordEchoEditing()) { // Reset the echomode back to PasswordEchoOnEdit when the widget loses // focus. d->updatePasswordEchoEditing(false); @@ -2396,21 +1695,18 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) deselect(); d->setCursorVisible(false); - if (d->cursorTimer > 0) - killTimer(d->cursorTimer); - d->cursorTimer = 0; - + d->control->setCursorBlinkPeriod(0); #ifdef QT_KEYPAD_NAVIGATION // editingFinished() is already emitted on LeaveEditFocus if (!QApplication::keypadNavigationEnabled()) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->emitingEditingFinished) { - if (hasAcceptableInput() || d->fixup()) { - d->emitingEditingFinished = true; + if (!d->control->emitingEditingFinished) { + if (hasAcceptableInput() || d->control->fixup()) { + d->control->emitingEditingFinished = true; emit editingFinished(); - d->emitingEditingFinished = false; + d->control->emitingEditingFinished = false; } } #ifdef QT3_SUPPORT @@ -2418,15 +1714,15 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif } #ifdef Q_WS_MAC - if (d->echoMode == Password || d->echoMode == NoEcho) + if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) qt_mac_secure_keyboard(false); #endif #ifdef QT_KEYPAD_NAVIGATION d->origText = QString(); #endif #ifndef QT_NO_COMPLETER - if (d->completer) { - QObject::disconnect(d->completer, 0, this, 0); + if (d->control->completer()) { + QObject::disconnect(d->control->completer(), 0, this, 0); } #endif update(); @@ -2456,24 +1752,19 @@ void QLineEdit::paintEvent(QPaintEvent *) Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment)); switch (va & Qt::AlignVertical_Mask) { case Qt::AlignBottom: - d->vscroll = r.y() + r.height() - fm.height() - verticalMargin; + d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin; break; case Qt::AlignTop: - d->vscroll = r.y() + verticalMargin; + d->vscroll = r.y() + d->verticalMargin; break; default: //center d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2; break; } - QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height()); - QTextLine line = d->textLayout.lineAt(0); + QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); - int cursor = d->cursor; - if (d->preeditCursor != -1) - cursor += d->preeditCursor; - // locate cursor position - int cix = qRound(line.cursorToX(cursor)); + int cix = qRound(d->control->cursorToX()); // horizontal scrolling. d->hscroll is the left indent from the beginning // of the text line to the left edge of lineRect. we update this value @@ -2483,7 +1774,7 @@ void QLineEdit::paintEvent(QPaintEvent *) // (cix). int minLB = qMax(0, -fm.minLeftBearing()); int minRB = qMax(0, -fm.minRightBearing()); - int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; + int widthUsed = d->control->width() + minRB; if ((minLB + widthUsed) <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { @@ -2511,7 +1802,7 @@ void QLineEdit::paintEvent(QPaintEvent *) d->hscroll = widthUsed - lineRect.width() + 1; } // the y offset is there to keep the baseline constant in case we have script changes in the text. - QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent()); + QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); // draw text, selections and cursors #ifndef QT_NO_STYLE_STYLESHEET @@ -2521,33 +1812,23 @@ void QLineEdit::paintEvent(QPaintEvent *) #endif p.setPen(pal.text().color()); - QVector selections; + int flags = QLineControl::DrawText; + #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || hasEditFocus()) #endif - if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) { - QTextLayout::FormatRange o; - if (d->selstart < d->selend) { - o.start = d->selstart; - o.length = d->selend - d->selstart; - o.format.setBackground(pal.brush(QPalette::Highlight)); - o.format.setForeground(pal.brush(QPalette::HighlightedText)); - } else { - // mask selection - o.start = d->cursor; - o.length = 1; - o.format.setBackground(pal.brush(QPalette::Text)); - o.format.setForeground(pal.brush(QPalette::Window)); - } - selections.append(o); - } + if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly())) + flags |= QLineControl::DrawSelections; // Asian users see an IM selection text as cursor on candidate // selection phase of input method, so the ordinary cursor should be // invisible if we have a preedit string. - d->textLayout.draw(&p, topLeft, selections, r); - if (d->cursorVisible && !d->readOnly && !d->hideCursor) - d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth)); + if (d->cursorVisible && !d->control->isReadOnly()) + flags |= QLineControl::DrawCursor; + + d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth)); + d->control->draw(&p, topLeft, r, flags); + } @@ -2557,12 +1838,11 @@ void QLineEdit::paintEvent(QPaintEvent *) void QLineEdit::dragMoveEvent(QDragMoveEvent *e) { Q_D(QLineEdit); - if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) { + if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) { e->acceptProposedAction(); - d->cursor = d->xToPos(e->pos().x()); + d->control->moveCursor(d->xToPos(e->pos().x()), false); d->cursorVisible = true; update(); - d->emitCursorPositionChanged(); } } @@ -2588,13 +1868,14 @@ void QLineEdit::dropEvent(QDropEvent* e) Q_D(QLineEdit); QString str = e->mimeData()->text(); - if (!str.isNull() && !d->readOnly) { + if (!str.isNull() && !d->control->isReadOnly()) { if (e->source() == this && e->dropAction() == Qt::CopyAction) deselect(); - d->cursor =d->xToPos(e->pos().x()); - int selStart = d->cursor; - int oldSelStart = d->selstart; - int oldSelEnd = d->selend; + int cursorPos = d->xToPos(e->pos().x()); + int selStart = cursorPos; + int oldSelStart = d->control->selectionStart(); + int oldSelEnd = d->control->selectionEnd(); + d->control->moveCursor(cursorPos, false); d->cursorVisible = false; e->acceptProposedAction(); insert(str); @@ -2616,22 +1897,6 @@ void QLineEdit::dropEvent(QDropEvent* e) } } -void QLineEditPrivate::drag() -{ - Q_Q(QLineEdit); - dndTimer.stop(); - QMimeData *data = new QMimeData; - data->setText(q->selectedText()); - QDrag *drag = new QDrag(q); - drag->setMimeData(data); - Qt::DropAction action = drag->start(); - if (action == Qt::MoveAction && !readOnly && drag->target() != q) { - int priorState = undoState; - removeSelectedText(); - finishChange(priorState); - } -} - #endif // QT_NO_DRAGANDDROP #ifndef QT_NO_CONTEXTMENU @@ -2676,37 +1941,37 @@ QMenu *QLineEdit::createStandardContextMenu() popup->setObjectName(QLatin1String("qt_edit_menu")); QAction *action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo)); - action->setEnabled(d->isUndoAvailable()); + action->setEnabled(d->control->isUndoAvailable()); connect(action, SIGNAL(triggered()), SLOT(undo())); action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo)); - action->setEnabled(d->isRedoAvailable()); + action->setEnabled(d->control->isRedoAvailable()); connect(action, SIGNAL(triggered()), SLOT(redo())); popup->addSeparator(); #ifndef QT_NO_CLIPBOARD action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); - action->setEnabled(!d->readOnly && d->hasSelectedText() && d->echoMode == QLineEdit::Normal); + action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(cut())); action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy)); - action->setEnabled(d->hasSelectedText() && d->echoMode == QLineEdit::Normal); + action->setEnabled(d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(copy())); action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); - action->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty()); + action->setEnabled(!d->control->isReadOnly() && !QApplication::clipboard()->text().isEmpty()); connect(action, SIGNAL(triggered()), SLOT(paste())); #endif action = popup->addAction(QLineEdit::tr("Delete")); - action->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText()); + action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText()); connect(action, SIGNAL(triggered()), SLOT(_q_deleteSelected())); popup->addSeparator(); action = popup->addAction(QLineEdit::tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll)); - action->setEnabled(!d->text.isEmpty() && !d->allSelected()); + action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected()); d->selectAllAction = action; connect(action, SIGNAL(triggered()), SLOT(selectAll())); @@ -2720,9 +1985,9 @@ QMenu *QLineEdit::createStandardContextMenu() #endif #if defined(Q_WS_WIN) - if (!d->readOnly && qt_use_rtl_extensions) { + if (!d->control->isReadOnly() && qt_use_rtl_extensions) { #else - if (!d->readOnly) { + if (!d->control->isReadOnly()) { #endif popup->addSeparator(); QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup); @@ -2736,806 +2001,26 @@ QMenu *QLineEdit::createStandardContextMenu() void QLineEdit::changeEvent(QEvent *ev) { Q_D(QLineEdit); - if(ev->type() == QEvent::ActivationChange) { + switch(ev->type()) + { + case QEvent::ActivationChange: if (!palette().isEqual(QPalette::Active, QPalette::Inactive)) update(); - } else if (ev->type() == QEvent::FontChange - || ev->type() == QEvent::StyleChange - || ev->type() == QEvent::LayoutDirectionChange) { - d->updateTextLayout(); - } - QWidget::changeEvent(ev); -} - -void QLineEditPrivate::_q_handleWindowActivate() -{ - Q_Q(QLineEdit); - if (!q->hasFocus() && q->hasSelectedText()) - q->deselect(); -} - -void QLineEditPrivate::_q_deleteSelected() -{ - Q_Q(QLineEdit); - if (!hasSelectedText()) - return; - - int priorState = undoState; - q->resetInputContext(); - removeSelectedText(); - separate(); - finishChange(priorState); -} - -void QLineEditPrivate::init(const QString& txt) -{ - Q_Q(QLineEdit); -#ifndef QT_NO_CURSOR - q->setCursor(Qt::IBeamCursor); -#endif - q->setFocusPolicy(Qt::StrongFocus); - q->setAttribute(Qt::WA_InputMethodEnabled); - // Specifies that this widget can use more, but is able to survive on - // less, horizontal space; and is fixed vertically. - q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit)); - q->setBackgroundRole(QPalette::Base); - q->setAttribute(Qt::WA_KeyCompression); - q->setMouseTracking(true); - q->setAcceptDrops(true); - text = txt; - updateTextLayout(); - cursor = text.length(); - - q->setAttribute(Qt::WA_MacShowFocusRect); -} - -void QLineEditPrivate::updatePasswordEchoEditing(bool editing) -{ - Q_Q(QLineEdit); - passwordEchoEditing = editing; - q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q)); - updateTextLayout(); - q->update(); -} - -void QLineEditPrivate::updateTextLayout() -{ - // replace certain non-printable characters with spaces (to avoid - // drawing boxes when using fonts that don't have glyphs for such - // characters) - Q_Q(QLineEdit); - QString str = q->displayText(); - QChar* uc = str.data(); - for (int i = 0; i < (int)str.length(); ++i) { - if ((uc[i] < 0x20 && uc[i] != 0x09) - || uc[i] == QChar::LineSeparator - || uc[i] == QChar::ParagraphSeparator - || uc[i] == QChar::ObjectReplacementCharacter) - uc[i] = QChar(0x0020); - } - textLayout.setFont(q->font()); - textLayout.setText(str); - QTextOption option; - option.setTextDirection(q->layoutDirection()); - option.setFlags(QTextOption::IncludeTrailingSpaces); - textLayout.setTextOption(option); - - textLayout.beginLayout(); - QTextLine l = textLayout.createLine(); - textLayout.endLayout(); - ascent = qRound(l.ascent()); -} - -int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const -{ - QRect cr = adjustedContentsRect(); - x-= cr.x() - hscroll + horizontalMargin; - QTextLine l = textLayout.lineAt(0); - return l.xToCursor(x, betweenOrOn); -} - -QRect QLineEditPrivate::cursorRect() const -{ - Q_Q(const QLineEdit); - QRect cr = adjustedContentsRect(); - int cix = cr.x() - hscroll + horizontalMargin; - QTextLine l = textLayout.lineAt(0); - int c = cursor; - if (preeditCursor != -1) - c += preeditCursor; - cix += qRound(l.cursorToX(c)); - int ch = qMin(cr.height(), q->fontMetrics().height() + 1); - int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth); - return QRect(cix-5, vscroll, w + 9, ch); -} - -QRect QLineEditPrivate::adjustedContentsRect() const -{ - Q_Q(const QLineEdit); - QStyleOptionFrameV2 opt; - q->initStyleOption(&opt); - QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); - r.setX(r.x() + leftTextMargin); - r.setY(r.y() + topTextMargin); - r.setRight(r.right() - rightTextMargin); - r.setBottom(r.bottom() - bottomTextMargin); - return r; -} - -bool QLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable -{ -#ifndef QT_NO_VALIDATOR - if (validator) { - QString textCopy = text; - int cursorCopy = cursor; - validator->fixup(textCopy); - if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { - if (textCopy != text || cursorCopy != cursor) - setText(textCopy, cursorCopy); - return true; - } - } -#endif - return false; -} - -void QLineEditPrivate::moveCursor(int pos, bool mark) -{ - Q_Q(QLineEdit); - if (pos != cursor) { - separate(); - if (maskData) - pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); - } - bool fullUpdate = mark || hasSelectedText(); - if (mark) { - int anchor; - if (selend > selstart && cursor == selstart) - anchor = selend; - else if (selend > selstart && cursor == selend) - anchor = selstart; - else - anchor = cursor; - selstart = qMin(anchor, pos); - selend = qMax(anchor, pos); - updateTextLayout(); - } else { - deselect(); - } - if (fullUpdate) { - cursor = pos; - q->update(); - } else { - setCursorVisible(false); - cursor = pos; - setCursorVisible(true); - if (!adjustedContentsRect().contains(cursorRect())) - q->update(); - } - QStyleOptionFrameV2 opt; - q->initStyleOption(&opt); - if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q)) - setCursorVisible(false); - if (mark || selDirty) { - selDirty = false; - emit q->selectionChanged(); - } - emitCursorPositionChanged(); -} - -void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited) -{ - Q_Q(QLineEdit); - bool lineDirty = selDirty; - if (textDirty) { - // do validation - bool wasValidInput = validInput; - validInput = true; -#ifndef QT_NO_VALIDATOR - if (validator) { - validInput = false; - QString textCopy = text; - int cursorCopy = cursor; - validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid); - if (validInput) { - if (text != textCopy) { - setText(textCopy, cursorCopy); - return; - } - cursor = cursorCopy; - } - } -#endif - if (validateFromState >= 0 && wasValidInput && !validInput) { - undo(validateFromState); - history.resize(undoState); - if (modifiedState > undoState) - modifiedState = -1; - validInput = true; - textDirty = false; - } - updateTextLayout(); - lineDirty |= textDirty; - if (textDirty) { - textDirty = false; - QString actualText = maskData ? stripString(text) : text; - if (edited) - emit q->textEdited(actualText); - q->updateMicroFocus(); -#ifndef QT_NO_COMPLETER - if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion) - complete(-1); // update the popup on cut/paste/del -#endif - emit q->textChanged(actualText); - } -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged); -#endif - } - if (selDirty) { - selDirty = false; - emit q->selectionChanged(); - } - if (lineDirty || update) - q->update(); - emitCursorPositionChanged(); -} - -void QLineEditPrivate::emitCursorPositionChanged() -{ - Q_Q(QLineEdit); - if (cursor != lastCursorPos) { - const int oldLast = lastCursorPos; - lastCursorPos = cursor; - emit q->cursorPositionChanged(oldLast, cursor); - } -} - -void QLineEditPrivate::setText(const QString& txt, int pos, bool edited) -{ - Q_Q(QLineEdit); - q->resetInputContext(); - deselect(); - QString oldText = text; - if (maskData) { - text = maskString(0, txt, true); - text += clearString(text.length(), maxLength - text.length()); - } else { - text = txt.isEmpty() ? txt : txt.left(maxLength); - } - history.clear(); - modifiedState = undoState = 0; - cursor = (pos < 0 || pos > text.length()) ? text.length() : pos; - textDirty = (oldText != text); - finishChange(-1, true, edited); -} - - -void QLineEditPrivate::setCursorVisible(bool visible) -{ - Q_Q(QLineEdit); - if ((bool)cursorVisible == visible) - return; - if (cursorTimer) - cursorVisible = visible; - QRect r = cursorRect(); - if (maskData) - q->update(); - else - q->update(r); -} - -void QLineEditPrivate::addCommand(const Command& cmd) -{ - if (separator && undoState && history[undoState-1].type != Separator) { - history.resize(undoState + 2); - history[undoState++] = Command(Separator, cursor, 0, selstart, selend); - } else { - history.resize(undoState + 1); - } - separator = false; - history[undoState++] = cmd; -} - -void QLineEditPrivate::insert(const QString& s) -{ - if (hasSelectedText()) - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - if (maskData) { - QString ms = maskString(cursor, s); - for (int i = 0; i < (int) ms.length(); ++i) { - addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1)); - addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1)); - } - text.replace(cursor, ms.length(), ms); - cursor += ms.length(); - cursor = nextMaskBlank(cursor); - textDirty = true; - } else { - int remaining = maxLength - text.length(); - if (remaining != 0) { - text.insert(cursor, s.left(remaining)); - for (int i = 0; i < (int) s.left(remaining).length(); ++i) - addCommand(Command(Insert, cursor++, s.at(i), -1, -1)); - textDirty = true; - } - } -} - -void QLineEditPrivate::del(bool wasBackspace) -{ - if (cursor < (int) text.length()) { - if (hasSelectedText()) - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor), -1, -1)); - if (maskData) { - text.replace(cursor, 1, clearString(cursor, 1)); - addCommand(Command(Insert, cursor, text.at(cursor), -1, -1)); - } else { - text.remove(cursor, 1); - } - textDirty = true; - } -} - -void QLineEditPrivate::removeSelectedText() -{ - if (selstart < selend && selend <= (int) text.length()) { - separate(); - int i ; - addCommand(Command(SetSelection, cursor, 0, selstart, selend)); - if (selstart <= cursor && cursor < selend) { - // cursor is within the selection. Split up the commands - // to be able to restore the correct cursor position - for (i = cursor; i >= selstart; --i) - addCommand (Command(DeleteSelection, i, text.at(i), -1, 1)); - for (i = selend - 1; i > cursor; --i) - addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i), -1, -1)); - } else { - for (i = selend-1; i >= selstart; --i) - addCommand (Command(RemoveSelection, i, text.at(i), -1, -1)); - } - if (maskData) { - text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); - for (int i = 0; i < selend - selstart; ++i) - addCommand(Command(Insert, selstart + i, text.at(selstart + i), -1, -1)); - } else { - text.remove(selstart, selend - selstart); - } - if (cursor > selstart) - cursor -= qMin(cursor, selend) - selstart; - deselect(); - textDirty = true; - - // adjust hscroll to avoid gap - const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing()); - updateTextLayout(); - const QTextLine line = textLayout.lineAt(0); - const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; - hscroll = qMin(hscroll, widthUsed); - } -} - -void QLineEditPrivate::parseInputMask(const QString &maskFields) -{ - int delimiter = maskFields.indexOf(QLatin1Char(';')); - if (maskFields.isEmpty() || delimiter == 0) { - if (maskData) { - delete [] maskData; - maskData = 0; - maxLength = 32767; - setText(QString()); - } - return; - } - - if (delimiter == -1) { - blank = QLatin1Char(' '); - inputMask = maskFields; - } else { - inputMask = maskFields.left(delimiter); - blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); - } - - // calculate maxLength / maskData length - maxLength = 0; - QChar c = 0; - for (int i=0; i 0 && inputMask.at(i-1) == QLatin1Char('\\')) { - maxLength++; - continue; - } - if (c != QLatin1Char('\\') && c != QLatin1Char('!') && - c != QLatin1Char('<') && c != QLatin1Char('>') && - c != QLatin1Char('{') && c != QLatin1Char('}') && - c != QLatin1Char('[') && c != QLatin1Char(']')) - maxLength++; - } - - delete [] maskData; - maskData = new MaskInputData[maxLength]; - - MaskInputData::Casemode m = MaskInputData::NoCaseMode; - c = 0; - bool s; - bool escape = false; - int index = 0; - for (int i = 0; i < inputMask.length(); i++) { - c = inputMask.at(i); - if (escape) { - s = true; - maskData[index].maskChar = c; - maskData[index].separator = s; - maskData[index].caseMode = m; - index++; - escape = false; - } else if (c == QLatin1Char('<')) { - m = MaskInputData::Lower; - } else if (c == QLatin1Char('>')) { - m = MaskInputData::Upper; - } else if (c == QLatin1Char('!')) { - m = MaskInputData::NoCaseMode; - } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { - switch (c.unicode()) { - case 'A': - case 'a': - case 'N': - case 'n': - case 'X': - case 'x': - case '9': - case '0': - case 'D': - case 'd': - case '#': - case 'H': - case 'h': - case 'B': - case 'b': - s = false; - break; - case '\\': - escape = true; - default: - s = true; - break; - } - - if (!escape) { - maskData[index].maskChar = c; - maskData[index].separator = s; - maskData[index].caseMode = m; - index++; - } - } - } - setText(text); -} - - -/* checks if the key is valid compared to the inputMask */ -bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const -{ - switch (mask.unicode()) { - case 'A': - if (key.isLetter()) - return true; - break; - case 'a': - if (key.isLetter() || key == blank) - return true; - break; - case 'N': - if (key.isLetterOrNumber()) - return true; - break; - case 'n': - if (key.isLetterOrNumber() || key == blank) - return true; - break; - case 'X': - if (key.isPrint()) - return true; - break; - case 'x': - if (key.isPrint() || key == blank) - return true; - break; - case '9': - if (key.isNumber()) - return true; - break; - case '0': - if (key.isNumber() || key == blank) - return true; - break; - case 'D': - if (key.isNumber() && key.digitValue() > 0) - return true; - break; - case 'd': - if ((key.isNumber() && key.digitValue() > 0) || key == blank) - return true; - break; - case '#': - if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) - return true; break; - case 'B': - if (key == QLatin1Char('0') || key == QLatin1Char('1')) - return true; + case QEvent::FontChange: + d->control->setFont(font()); break; - case 'b': - if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) - return true; + case QEvent::StyleChange: + d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter)); + update(); break; - case 'H': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) - return true; - break; - case 'h': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) - return true; + case QEvent::LayoutDirectionChange: + d->control->setLayoutDirection(layoutDirection()); break; default: break; } - return false; -} - -bool QLineEditPrivate::hasAcceptableInput(const QString &str) const -{ -#ifndef QT_NO_VALIDATOR - QString textCopy = str; - int cursorCopy = cursor; - if (validator && validator->validate(textCopy, cursorCopy) - != QValidator::Acceptable) - return false; -#endif - - if (!maskData) - return true; - - if (str.length() != maxLength) - return false; - - for (int i=0; i < maxLength; ++i) { - if (maskData[i].separator) { - if (str.at(i) != maskData[i].maskChar) - return false; - } else { - if (!isValidInput(str.at(i), maskData[i].maskChar)) - return false; - } - } - return true; -} - -/* - Applies the inputMask on \a str starting from position \a pos in the mask. \a clear - specifies from where characters should be gotten when a separator is met in \a str - true means - that blanks will be used, false that previous input is used. - Calling this when no inputMask is set is undefined. -*/ -QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const -{ - if (pos >= (uint)maxLength) - return QString::fromLatin1(""); - - QString fill; - fill = clear ? clearString(0, maxLength) : text; - - int strIndex = 0; - QString s = QString::fromLatin1(""); - int i = pos; - while (i < maxLength) { - if (strIndex < str.length()) { - if (maskData[i].separator) { - s += maskData[i].maskChar; - if (str[(int)strIndex] == maskData[i].maskChar) - strIndex++; - ++i; - } else { - if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { - switch (maskData[i].caseMode) { - case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); - break; - case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); - break; - default: - s += str[(int)strIndex]; - } - ++i; - } else { - // search for separator first - int n = findInMask(i, true, true, str[(int)strIndex]); - if (n != -1) { - if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { - s += fill.mid(i, n-i+1); - i = n + 1; // update i to find + 1 - } - } else { - // search for valid blank if not - n = findInMask(i, true, false, str[(int)strIndex]); - if (n != -1) { - s += fill.mid(i, n-i); - switch (maskData[n].caseMode) { - case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); - break; - case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); - break; - default: - s += str[(int)strIndex]; - } - i = n + 1; // updates i to find + 1 - } - } - } - strIndex++; - } - } else - break; - } - - return s; -} - - - -/* - Returns a "cleared" string with only separators and blank chars. - Calling this when no inputMask is set is undefined. -*/ -QString QLineEditPrivate::clearString(uint pos, uint len) const -{ - if (pos >= (uint)maxLength) - return QString(); - - QString s; - int end = qMin((uint)maxLength, pos + len); - for (int i=pos; i= maxLength || pos < 0) - return -1; - - int end = forward ? maxLength : -1; - int step = forward ? 1 : -1; - int i = pos; - - while (i != end) { - if (findSeparator) { - if (maskData[i].separator && maskData[i].maskChar == searchChar) - return i; - } else { - if (!maskData[i].separator) { - if (searchChar.isNull()) - return i; - else if (isValidInput(searchChar, maskData[i].maskChar)) - return i; - } - } - i += step; - } - return -1; -} - -void QLineEditPrivate::undo(int until) -{ - if (!isUndoAvailable()) - return; - deselect(); - while (undoState && undoState > until) { - Command& cmd = history[--undoState]; - switch (cmd.type) { - case Insert: - text.remove(cmd.pos, 1); - cursor = cmd.pos; - break; - case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Remove: - case RemoveSelection: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos + 1; - break; - case Delete: - case DeleteSelection: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos; - break; - case Separator: - continue; - } - if (until < 0 && undoState) { - Command& next = history[undoState-1]; - if (next.type != cmd.type && next.type < RemoveSelection - && (cmd.type < RemoveSelection || next.type == Separator)) - break; - } - } - textDirty = true; - emitCursorPositionChanged(); -} - -void QLineEditPrivate::redo() { - if (!isRedoAvailable()) - return; - deselect(); - while (undoState < (int)history.size()) { - Command& cmd = history[undoState++]; - switch (cmd.type) { - case Insert: - text.insert(cmd.pos, cmd.uc); - cursor = cmd.pos + 1; - break; - case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Remove: - case Delete: - case RemoveSelection: - case DeleteSelection: - text.remove(cmd.pos, 1); - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - case Separator: - selstart = cmd.selStart; - selend = cmd.selEnd; - cursor = cmd.pos; - break; - } - if (undoState < (int)history.size()) { - Command& next = history[undoState]; - if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator - && (next.type < RemoveSelection || cmd.type == Separator)) - break; - } - } - textDirty = true; - emitCursorPositionChanged(); + QWidget::changeEvent(ev); } /*! diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h index a97dc9a..daac6a7 100644 --- a/src/gui/widgets/qlineedit.h +++ b/src/gui/widgets/qlineedit.h @@ -268,6 +268,8 @@ private: Q_DECLARE_PRIVATE(QLineEdit) Q_PRIVATE_SLOT(d_func(), void _q_handleWindowActivate()) Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected()) + Q_PRIVATE_SLOT(d_func(), void _q_textEdited(const QString &)) + Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged(int, int)) #ifndef QT_NO_COMPLETER Q_PRIVATE_SLOT(d_func(), void _q_completionHighlighted(QString)) #endif diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp new file mode 100644 index 0000000..0e39304 --- /dev/null +++ b/src/gui/widgets/qlineedit_p.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlineedit.h" +#include "qlineedit_p.h" + +#ifndef QT_NO_LINEEDIT + +#include "qabstractitemview.h" +#include "qclipboard.h" +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qlist.h" +#endif + +QT_BEGIN_NAMESPACE + +const int QLineEditPrivate::verticalMargin(1); +const int QLineEditPrivate::horizontalMargin(2); + +int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + QRect cr = adjustedContentsRect(); + x-= cr.x() - hscroll + horizontalMargin; + return control->xToPos(x, betweenOrOn); +} + +QRect QLineEditPrivate::cursorRect() const +{ + QRect cr = adjustedContentsRect(); + int cix = cr.x() - hscroll + horizontalMargin; + QRect crect = control->cursorRect(); + crect.moveTo(crect.topLeft() + QPoint(cix, vscroll)); + return crect; +} + +#ifndef QT_NO_COMPLETER + +void QLineEditPrivate::_q_completionHighlighted(QString newText) +{ + Q_Q(QLineEdit); + if (control->completer()->completionMode() != QCompleter::InlineCompletion) { + q->setText(newText); + } else { + int c = control->cursor(); + QString text = control->text(); + q->setText(text.left(c) + newText.mid(c)); + control->moveCursor(control->end(), false); + control->moveCursor(c, true); + } +} + +#endif // QT_NO_COMPLETER + +void QLineEditPrivate::_q_clipboardChanged() +{ +} + +void QLineEditPrivate::_q_handleWindowActivate() +{ + Q_Q(QLineEdit); + if (!q->hasFocus() && control->hasSelectedText()) + control->deselect(); +} + +void QLineEditPrivate::_q_deleteSelected() +{ +} + +void QLineEditPrivate::_q_textEdited(const QString &text) +{ + Q_Q(QLineEdit); +#ifndef QT_NO_COMPLETER + if (control->completer() && + control->completer()->completionMode() != QCompleter::InlineCompletion) + control->complete(-1); // update the popup on cut/paste/del +#endif + emit q->textEdited(text); +} + +void QLineEditPrivate::_q_cursorPositionChanged(int from, int to) +{ + Q_Q(QLineEdit); + q->update(); + emit q->cursorPositionChanged(from, to); +} + +void QLineEditPrivate::init(const QString& txt) +{ + Q_Q(QLineEdit); + control = new QLineControl(txt); + QObject::connect(control, SIGNAL(textChanged(const QString &)), + q, SIGNAL(textChanged(const QString &))); + QObject::connect(control, SIGNAL(textEdited(const QString &)), + q, SLOT(_q_textEdited(const QString &))); + QObject::connect(control, SIGNAL(cursorPositionChanged(int, int)), + q, SLOT(_q_cursorPositionChanged(int, int))); + QObject::connect(control, SIGNAL(selectionChanged()), + q, SIGNAL(selectionChanged())); + QObject::connect(control, SIGNAL(accepted()), + q, SIGNAL(returnPressed())); + QObject::connect(control, SIGNAL(editingFinished()), + q, SIGNAL(editingFinished())); + + // for now, going completely overboard with updates. + QObject::connect(control, SIGNAL(selectionChanged()), + q, SLOT(update())); + + QObject::connect(control, SIGNAL(displayTextChanged(const QString &)), + q, SLOT(update())); + control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter)); +#ifndef QT_NO_CURSOR + q->setCursor(Qt::IBeamCursor); +#endif + q->setFocusPolicy(Qt::StrongFocus); + q->setAttribute(Qt::WA_InputMethodEnabled); + // Specifies that this widget can use more, but is able to survive on + // less, horizontal space; and is fixed vertically. + q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit)); + q->setBackgroundRole(QPalette::Base); + q->setAttribute(Qt::WA_KeyCompression); + q->setMouseTracking(true); + q->setAcceptDrops(true); + + q->setAttribute(Qt::WA_MacShowFocusRect); +} + +QRect QLineEditPrivate::adjustedContentsRect() const +{ + Q_Q(const QLineEdit); + QStyleOptionFrameV2 opt; + q->initStyleOption(&opt); + QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q); + r.setX(r.x() + leftTextMargin); + r.setY(r.y() + topTextMargin); + r.setRight(r.right() - rightTextMargin); + r.setBottom(r.bottom() - bottomTextMargin); + return r; +} + +void QLineEditPrivate::setCursorVisible(bool visible) +{ + Q_Q(QLineEdit); + if ((bool)cursorVisible == visible) + return; + cursorVisible = visible; + QRect r = cursorRect(); + if (control->inputMask().isEmpty()) + q->update(r); + else + q->update(); +} + +void QLineEditPrivate::updatePasswordEchoEditing(bool editing) +{ + Q_Q(QLineEdit); + control->updatePasswordEchoEditing(editing); + q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod()); +} + +/*! + This function is not intended as polymorphic usage. Just a shared code + fragment that calls QInputContext::mouseHandler for this + class. +*/ +bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e ) +{ +#if !defined QT_NO_IM + Q_Q(QLineEdit); + if ( control->composeMode() ) { + int tmp_cursor = xToPos(e->pos().x()); + int mousePos = tmp_cursor - control->cursor(); + if ( mousePos < 0 || mousePos > control->preeditAreaText().length() ) { + mousePos = -1; + // don't send move events outside the preedit area + if ( e->type() == QEvent::MouseMove ) + return true; + } + + QInputContext *qic = q->inputContext(); + if ( qic ) + // may be causing reset() in some input methods + qic->mouseHandler(mousePos, e); + if (!control->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); +#endif + + return false; +} + +#ifndef QT_NO_DRAGANDDROP +void QLineEditPrivate::drag() +{ + Q_Q(QLineEdit); + dndTimer.stop(); + QMimeData *data = new QMimeData; + data->setText(control->selectedText()); + QDrag *drag = new QDrag(q); + drag->setMimeData(data); + Qt::DropAction action = drag->start(); + if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q) + control->removeSelection(); +} + +#endif // QT_NO_DRAGANDDROP + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 7a4ff26..c6d7496 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -65,6 +65,8 @@ #include "QtCore/qpointer.h" #include "QtGui/qlineedit.h" +#include "private/qlinecontrol_p.h" + QT_BEGIN_NAMESPACE class QLineEditPrivate : public QWidgetPrivate @@ -73,168 +75,66 @@ class QLineEditPrivate : public QWidgetPrivate public: QLineEditPrivate() - : cursor(0), preeditCursor(0), cursorTimer(0), frame(1), - cursorVisible(0), hideCursor(false), separator(0), readOnly(0), - dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0), - selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0), - maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0), - modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false), - emitingEditingFinished(false), passwordEchoEditing(false) -#ifndef QT_NO_COMPLETER - , completer(0) -#endif - , leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0) - { - } + : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0), + dragEnabled(0), hscroll(0), vscroll(0), + alignment(Qt::AlignLeading | Qt::AlignVCenter), + leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0) + { + } ~QLineEditPrivate() { - delete [] maskData; } + + QLineControl *control; + +#ifndef QT_NO_CONTEXTMENU + QPointer selectAllAction; +#endif void init(const QString&); - QString text; - int cursor; - int preeditCursor; - int cursorTimer; // -1 for non blinking cursor. + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect cursorRect() const; + void setCursorVisible(bool visible); + + void updatePasswordEchoEditing(bool); + + inline bool shouldEnableInputMethod() const + { + return !control->isReadOnly() && (control->echoMode() == QLineEdit::Normal || control->echoMode() == QLineEdit::PasswordEchoOnEdit); + } + QPoint tripleClick; QBasicTimer tripleClickTimer; uint frame : 1; + uint contextMenuEnabled : 1; uint cursorVisible : 1; - uint hideCursor : 1; // used to hide the cursor inside preedit areas - uint separator : 1; - uint readOnly : 1; uint dragEnabled : 1; - uint contextMenuEnabled : 1; - uint echoMode : 2; - uint textDirty : 1; - uint selDirty : 1; - uint validInput : 1; - uint alignment; - int ascent; - int maxLength; int hscroll; int vscroll; - int lastCursorPos; - -#ifndef QT_NO_CONTEXTMENU - QPointer selectAllAction; -#endif + uint alignment; + static const int verticalMargin; + static const int horizontalMargin; - inline void emitCursorPositionChanged(); bool sendMouseEventToInputContext(QMouseEvent *e); - void finishChange(int validateFromState = -1, bool update = false, bool edited = true); - - QPointer validator; - struct MaskInputData { - enum Casemode { NoCaseMode, Upper, Lower }; - QChar maskChar; // either the separator char or the inputmask - bool separator; - Casemode caseMode; - }; - QString inputMask; - QChar blank; - MaskInputData *maskData; - inline int nextMaskBlank(int pos) { - int c = findInMask(pos, true, false); - separator |= (c != pos); - return (c != -1 ? c : maxLength); - } - inline int prevMaskBlank(int pos) { - int c = findInMask(pos, false, false); - separator |= (c != pos); - return (c != -1 ? c : 0); - } - - void setCursorVisible(bool visible); + QRect adjustedContentsRect() const; + void _q_clipboardChanged(); + void _q_handleWindowActivate(); + void _q_deleteSelected(); + void _q_textEdited(const QString &); + void _q_cursorPositionChanged(int, int); - // undo/redo handling - enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; - struct Command { - inline Command() {} - inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} - uint type : 4; - QChar uc; - int pos, selStart, selEnd; - }; - int modifiedState; - int undoState; - QVector history; - void addCommand(const Command& cmd); - void insert(const QString& s); - void del(bool wasBackspace = false); - void remove(int pos); - - inline void separate() { separator = true; } - void undo(int until = -1); - void redo(); - inline bool isUndoAvailable() const { return !readOnly && undoState; } - inline bool isRedoAvailable() const { return !readOnly && undoState < (int)history.size(); } - - // selection - int selstart, selend; - inline bool allSelected() const { return !text.isEmpty() && selstart == 0 && selend == (int)text.length(); } - inline bool hasSelectedText() const { return !text.isEmpty() && selend > selstart; } - inline void deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } - void removeSelectedText(); -#ifndef QT_NO_CLIPBOARD - void copy(bool clipboard = true) const; +#ifndef QT_NO_COMPLETER + void _q_completionHighlighted(QString); #endif - inline bool inSelection(int x) const - { if (selstart >= selend) return false; - int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; } - - // masking - void parseInputMask(const QString &maskFields); - bool isValidInput(QChar key, QChar mask) const; - bool hasAcceptableInput(const QString &text) const; - QString maskString(uint pos, const QString &str, bool clear = false) const; - QString clearString(uint pos, uint len) const; - QString stripString(const QString &str) const; - int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; - - // input methods - bool composeMode() const { return !textLayout.preeditAreaText().isEmpty(); } - - // complex text layout - QTextLayout textLayout; - void updateTextLayout(); - void moveCursor(int pos, bool mark = false); - void setText(const QString& txt, int pos = -1, bool edited = true); - int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; - QRect cursorRect() const; - bool fixup(); - - QRect adjustedContentsRect() const; - #ifndef QT_NO_DRAGANDDROP - // drag and drop QPoint dndPos; QBasicTimer dndTimer; void drag(); #endif - void _q_handleWindowActivate(); - void _q_deleteSelected(); - bool userInput; - bool emitingEditingFinished; - -#ifdef QT_KEYPAD_NAVIGATION - QBasicTimer deleteAllTimer; // keypad navigation - QString origText; -#endif - - bool passwordEchoEditing; - void updatePasswordEchoEditing(bool editing); - -#ifndef QT_NO_COMPLETER - QPointer completer; - void complete(int key = -1); - void _q_completionHighlighted(QString); - bool advanceToEnabledItem(int n); -#endif int leftTextMargin; int topTextMargin; diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h index ce78959..5ddc44e 100644 --- a/src/gui/widgets/qvalidator.h +++ b/src/gui/widgets/qvalidator.h @@ -61,7 +61,7 @@ class Q_GUI_EXPORT QValidator : public QObject { Q_OBJECT public: - explicit QValidator(QObject * parent); + explicit QValidator(QObject * parent=0); ~QValidator(); enum State { @@ -100,7 +100,7 @@ class Q_GUI_EXPORT QIntValidator : public QValidator Q_PROPERTY(int top READ top WRITE setTop) public: - explicit QIntValidator(QObject * parent); + explicit QIntValidator(QObject * parent=0); QIntValidator(int bottom, int top, QObject * parent); ~QIntValidator(); @@ -120,7 +120,7 @@ public: #endif private: - Q_DISABLE_COPY(QIntValidator) + /*Q_DISABLE_COPY(QIntValidator)*/ int b; int t; diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 2d809a1..8f24fac 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -30,6 +30,7 @@ HEADERS += \ widgets/qlcdnumber.h \ widgets/qlineedit.h \ widgets/qlineedit_p.h \ + widgets/qlinecontrol_p.h \ widgets/qmainwindow.h \ widgets/qmainwindowlayout_p.h \ widgets/qmdiarea.h \ @@ -101,7 +102,9 @@ SOURCES += \ widgets/qgroupbox.cpp \ widgets/qlabel.cpp \ widgets/qlcdnumber.cpp \ + widgets/qlineedit_p.cpp \ widgets/qlineedit.cpp \ + widgets/qlinecontrol.cpp \ widgets/qmainwindow.cpp \ widgets/qmainwindowlayout.cpp \ widgets/qmdiarea.cpp \ -- cgit v0.12 From 043a9b2eb3dd346126cf13817b67ed0790a72f7a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 17:45:56 +1000 Subject: Manually integrate 099a32d121 to QLineControl This change to QLineEdit didn't merge, as it needs to be applied to QLineControl in this case. --- src/gui/widgets/qlinecontrol.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index b762a00..08574b5 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1685,7 +1685,8 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (unknown && !isReadOnly()) { QString t = event->text(); - if (!t.isEmpty() && t.at(0).isPrint()) { + if (!t.isEmpty() && t.at(0).isPrint() && + ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { insert(t); #ifndef QT_NO_COMPLETER complete(event->key()); -- cgit v0.12 From 96d3be9039baaebc64f5de5d6917dd56d7ed192b Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 18:13:18 +1000 Subject: Finish remaining TODOs for QLineControl Didn't notice there were still some TODO markers left. They have now all been done. --- src/gui/widgets/qlinecontrol.cpp | 16 +++++++--------- src/gui/widgets/qlinecontrol_p.h | 14 ++++++++++++++ src/gui/widgets/qlineedit.cpp | 4 ++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 08574b5..fc0a173 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1232,7 +1232,6 @@ bool QLineControl::processEvent(QEvent* ev) return true; } } - //TODO: Needs a call to processKeyEvent? } else if (e->type() == QEvent::EnterEditFocus) { end(false); int cft = QApplication::cursorFlashTime(); @@ -1450,11 +1449,10 @@ void QLineControl::processKeyEvent(QKeyEvent* event) // ### resets current content. dubious code; you can // navigate with keys up, down, back, and select(?), but if you press // "left" or "right" it clears? - updatePasswordEchoEditing(true);//TODO: used to set a WA too + updatePasswordEchoEditing(true); clear(); } - //setCursorVisible(true);TODO: Who handles this? if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); @@ -1652,19 +1650,19 @@ void QLineControl::processKeyEvent(QKeyEvent* event) #endif } break; -#ifdef QT_KEYPAD_NAVIGATION//TODO: This section +#ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() && !isReadOnly()) { if (text().length() == 0) { - setText(d->origText); + setText(m_cancelText); - if (d->passwordEchoEditing) - d->updatePasswordEchoEditing(false); + if (passwordEchoEditing) + updatePasswordEchoEditing(false); setEditFocus(false); - } else if (!d->deleteAllTimer.isActive()) { - d->deleteAllTimer.start(750, this); + } else if (!deleteAllTimer) { + deleteAllTimer = startTimer(750); } } else { unknown = true; diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bb27778..600206d 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -217,6 +217,9 @@ public: int cursorBlinkPeriod() const; void setCursorBlinkPeriod(int msec); + QString cancelText() const; + void setCancelText(QString); + enum DrawFlags { DrawText = 0x01, DrawSelections = 0x02, @@ -265,6 +268,7 @@ private: QList transactions; QPoint m_tripleClick; int m_tripleClickTimer; + QString m_cancelText; void emitCursorPositionChanged(); @@ -706,6 +710,16 @@ inline int QLineControl::cursorBlinkPeriod() const return m_blinkPeriod; } +QString QLineControl::cancelText() const +{ + return m_cancelText; +} + +void QLineControl::setCancelText(QString s) +{ + m_cancelText = s; +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index baaad32..7fdda6c 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1663,7 +1663,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) qt_mac_secure_keyboard(true); #endif #ifdef QT_KEYPAD_NAVIGATION - d->origText = d->text; + d->control->setCancelText(d->text); #endif #ifndef QT_NO_COMPLETER if (d->control->completer()) { @@ -1718,7 +1718,7 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) qt_mac_secure_keyboard(false); #endif #ifdef QT_KEYPAD_NAVIGATION - d->origText = QString(); + d->control->setCancelText(QString()); #endif #ifndef QT_NO_COMPLETER if (d->control->completer()) { -- cgit v0.12 From fe6ca9332cf4516c84d9a1b8ca9ea2846458f98f Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 7 Jul 2009 18:28:54 +1000 Subject: Forgot to bring in the change to QAbstractSpinBox QAbstractSpinBox had some code using QLineEdit internals, this had to be move to use QLineControl as well. This commit also includes fixing some typos in my last commit. --- src/gui/widgets/qabstractspinbox.cpp | 2 +- src/gui/widgets/qlinecontrol_p.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 25acd6e..1d62ab4 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -970,7 +970,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) #endif case Qt::Key_Enter: case Qt::Key_Return: - d->edit->d_func()->modifiedState = d->edit->d_func()->undoState = 0; + d->edit->d_func()->control->clearUndo(); d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged); selectAll(); event->ignore(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 600206d..4ecedcd 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -710,12 +710,12 @@ inline int QLineControl::cursorBlinkPeriod() const return m_blinkPeriod; } -QString QLineControl::cancelText() const +inline QString QLineControl::cancelText() const { return m_cancelText; } -void QLineControl::setCancelText(QString s) +inline void QLineControl::setCancelText(QString s) { m_cancelText = s; } -- cgit v0.12 From 3528101647e7320d07623e659138005d7d603980 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 8 Jul 2009 15:54:33 +1000 Subject: Fixed one of the QT3_SUPPORT constructors. It was accidentally left commented out instead of working with QLineControl. --- src/gui/widgets/qlineedit.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 7fdda6c..8e7fdec 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -341,14 +341,9 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget* { Q_D(QLineEdit); setObjectName(QString::fromAscii(name)); - //d->control->parseInputMask(inputMask); - //if (d->control->maskData) { - // QString ms = d->control->maskString(0, contents); - // d->init(ms + d->control->clearString(ms.length(), d->control->maxLength() - ms.length())); - // d->control->moveCursor(d->control->nextMaskBlank(ms.length())); - // } else { - d->init(contents); - // } + d->init(contents); + d->control->setInputMask(inputMask); + d->control->moveCursor(d->control->nextMaskBlank(contents.length())); } #endif -- cgit v0.12 From b9fc86cd9f51c80a1103e5e896940b49bf552b07 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 9 Jul 2009 09:47:18 +1000 Subject: Accidental Behavioural changes have been identified and rectified. createStandardContextMenu should still only cut/copy in normal echo mode and the Qt3Support function validateAndSet will again only set if it is validated. --- src/gui/widgets/qlineedit.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 8e7fdec..2d6ef03 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -692,9 +692,14 @@ int QLineEdit::cursorPositionAt(const QPoint &pos) bool QLineEdit::validateAndSet(const QString &newText, int newPos, int newMarkAnchor, int newMarkDrag) { - // Note, this doesn't validate', but then neither - // does the suggested functions above in the docs. + // The suggested functions above in the docs don't seem to validate, + // below code tries to mimic previous behaviour. + QString oldText = text(); setText(newText); + if(!hasAcceptableInput()){ + setText(oldText); + return false; + } setCursorPosition(newPos); setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag)); return true; @@ -1947,11 +1952,13 @@ QMenu *QLineEdit::createStandardContextMenu() #ifndef QT_NO_CLIPBOARD action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut)); - action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()); + action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText() + && d->control->echoMode() == QLineEdit::Normal); connect(action, SIGNAL(triggered()), SLOT(cut())); action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy)); - action->setEnabled(d->control->hasSelectedText()); + action->setEnabled(d->control->hasSelectedText() + && d->control->echoMode() == QLineEdit::Normal); connect(action, SIGNAL(triggered()), SLOT(copy())); action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste)); -- cgit v0.12 From 61084f0e8dcbd9b7ecaa250c74cd53ba042210e1 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 10 Jul 2009 10:33:20 +1000 Subject: Fix some minor mistakes --- src/gui/widgets/qlineedit.cpp | 6 +++--- src/gui/widgets/qvalidator.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2d6ef03..977d00c 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1409,7 +1409,7 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() < QApplication::startDragDistance()) { selectAll(); - return; + return; } bool mark = e->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(e->pos().x()); @@ -1593,8 +1593,6 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) clear(); } - d->control->processInputMethodEvent(e); - #ifdef QT_KEYPAD_NAVIGATION // Focus in if currently in navigation focus on the widget // Only focus in on preedits, to allow input methods to @@ -1607,6 +1605,8 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) } #endif + d->control->processInputMethodEvent(e); + #ifndef QT_NO_COMPLETER if (!e->commitString().isEmpty()) d->control->complete(Qt::Key_unknown); diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h index 5ddc44e..5c27d1d 100644 --- a/src/gui/widgets/qvalidator.h +++ b/src/gui/widgets/qvalidator.h @@ -120,7 +120,7 @@ public: #endif private: - /*Q_DISABLE_COPY(QIntValidator)*/ + Q_DISABLE_COPY(QIntValidator) int b; int t; -- cgit v0.12 From 2718577ecf7a4a5c9fc619a46ee79a468044b4d7 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 10:44:05 +1000 Subject: Move some keypad navigation code back out of QLineControl --- src/gui/widgets/qlinecontrol.cpp | 46 ----------------------------------- src/gui/widgets/qlineedit.cpp | 52 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index fc0a173..dd3c057 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1212,44 +1212,6 @@ void QLineControl::timerEvent ( QTimerEvent * event ) bool QLineControl::processEvent(QEvent* ev) { -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)ev; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((ev->type() == QEvent::KeyRelease) - && !isReadOnly() - && deleteAllTimer) { - killTimer(m_deleteAllTimer); - m_deleteAllTimer = 0; - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - int cft = QApplication::cursorFlashTime(); - control->setCursorBlinkPeriod(cft/2); - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false);//!!! - control->setCursorBlinkPeriod(0); - if (!m_emitingEditingFinished) { - if (hasAcceptableInput() || fixup()) { - m_emitingEditingFinished = true; - emit editingFinished(); - m_emitingEditingFinished = false; - } - } - } - return; - } -#endif switch(ev->type()){ #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseMove: @@ -1332,14 +1294,6 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) } if (ev->button() == Qt::RightButton) return; -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { - setEditFocus(true); - // Get the completion list to pop up. - if (m_completer) - m_completer->complete(); - } -#endif bool mark = ev->modifiers() & Qt::ShiftModifier; int cursor = xToPos(ev->pos().x()); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 977d00c..b0c48b0 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1361,7 +1361,45 @@ void QLineEdit::paste() bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); - if (e->type() == QEvent::Timer) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + } else if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false);//!!! + control->setCursorBlinkPeriod(0); + if (!m_emitingEditingFinished) { + if (hasAcceptableInput() || fixup()) { + m_emitingEditingFinished = true; + emit editingFinished(); + m_emitingEditingFinished = false; + } + } + } + return; + } +#endif + if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); if (false) { @@ -1442,9 +1480,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) d->drag(); } else #endif - { d->control->moveCursor(d->xToPos(e->pos().x()), true); - } } } @@ -1463,10 +1499,18 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) d->drag(); } else #endif - { d->control->moveCursor(d->xToPos(e->pos().x()), true); + } +#ifndef QT_NO_CLIPBOARD + if (QApplication::clipboard()->supportsSelection()) { + if (e->button() == Qt::LeftButton) { + d->control->copy(QClipboard::Selection); + } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) { + deselect(); + insert(QApplication::clipboard()->text(QClipboard::Selection)); } } +#endif } /*! \reimp -- cgit v0.12 From 960332de7ae1206390169fb5ef03aa94dffb8f14 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 11:31:57 +1000 Subject: Actually, some of that can't be moved back into QLineEdit Also it should be executed a little later to avoid accidental behaviour changes. --- src/gui/widgets/qlinecontrol.cpp | 23 ++++++++++++++++ src/gui/widgets/qlineedit.cpp | 58 ++++++++++++++-------------------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index dd3c057..e6f397a 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1212,6 +1212,29 @@ void QLineControl::timerEvent ( QTimerEvent * event ) bool QLineControl::processEvent(QEvent* ev) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + } + } +#endif switch(ev->type()){ #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseMove: diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index b0c48b0..92dcfc4 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1361,44 +1361,6 @@ void QLineEdit::paste() bool QLineEdit::event(QEvent * e) { Q_D(QLineEdit); -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { - QKeyEvent *ke = (QKeyEvent *)ev; - if (ke->key() == Qt::Key_Back) { - if (ke->isAutoRepeat()) { - // Swallow it. We don't want back keys running amok. - ke->accept(); - return true; - } - if ((ev->type() == QEvent::KeyRelease) - && !isReadOnly() - && deleteAllTimer) { - killTimer(m_deleteAllTimer); - m_deleteAllTimer = 0; - backspace(); - ke->accept(); - return true; - } - } - } else if (e->type() == QEvent::EnterEditFocus) { - end(false); - int cft = QApplication::cursorFlashTime(); - control->setCursorBlinkPeriod(cft/2); - } else if (e->type() == QEvent::LeaveEditFocus) { - d->setCursorVisible(false);//!!! - control->setCursorBlinkPeriod(0); - if (!m_emitingEditingFinished) { - if (hasAcceptableInput() || fixup()) { - m_emitingEditingFinished = true; - emit editingFinished(); - m_emitingEditingFinished = false; - } - } - } - return; - } -#endif if (e->type() == QEvent::Timer) { // should be timerEvent, is here for binary compatibility int timerId = ((QTimerEvent*)e)->timerId(); @@ -1424,6 +1386,26 @@ bool QLineEdit::event(QEvent * e) d->control->setLayoutDirection((layoutDirection())); } +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::keypadNavigationEnabled()) { + if (e->type() == QEvent::EnterEditFocus) { + end(false); + int cft = QApplication::cursorFlashTime(); + d->control->setCursorBlinkPeriod(cft/2); + } else if (e->type() == QEvent::LeaveEditFocus) { + d->setCursorVisible(false); + d->control->setCursorBlinkPeriod(0); + if (!d->control->emitingEditingFinished) { + if (d->control->hasAcceptableInput() || d->control->fixup()) { + d->control->emitingEditingFinished = true; + emit editingFinished(); + d->control->emitingEditingFinished = false; + } + } + } + return; + } +#endif return QWidget::event(e); } -- cgit v0.12 From da3b21f6cf51ef10f230f2cf86e43fe0e6314193 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 13:34:40 +1000 Subject: Replace Q_ASSERT with qWarning This is probably more correct, but is also the way it used to behave. --- src/gui/widgets/qlinecontrol.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index e6f397a..557892f 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -222,8 +222,10 @@ void QLineControl::clear() */ void QLineControl::setSelection(int start, int length) { - Q_ASSERT_X(start >= 0 && start <= (int)m_text.length(), - "QLineControl::setSelection", "Invalid start position"); + if(start < 0 || start > (int)m_text.length()){ + qWarning("QLineControl::setSelection: Invalid start position"); + return; + } if (length > 0) { selstart = start; -- cgit v0.12 From f6e0f0d549de292f0bbab98a67b035a8327175bf Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 13:47:37 +1000 Subject: qlinecontrol_p_p.h isn't actually used at all, remove file. --- src/gui/widgets/qlinecontrol_p_p.h | 105 ------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 src/gui/widgets/qlinecontrol_p_p.h diff --git a/src/gui/widgets/qlinecontrol_p_p.h b/src/gui/widgets/qlinecontrol_p_p.h deleted file mode 100644 index e76794b..0000000 --- a/src/gui/widgets/qlinecontrol_p_p.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLINECONTROL_P_P_H -#define QLINECONTROL_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qobject_p.h" -#include "QtGui/qtextlayout.h" - -QT_BEGIN_NAMESPACE - -class QMimeData; -class QAbstractScrollArea; -class QInputContext; - -class QLineControlPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QLineControl) -public: - QLineControlPrivate() - : cursor(0), preeditCursor(0), cursorWidth(1), cursorTimer(0), - maxLength(32767), modifiedState(0), undoState(0), - selStart(0), selEnd(0), textInteractionFlags(0), - cursorVisible(0), hideCursor(0), echoMode(0) - {} - - QPalette palette; - QVector history; - QTextLayout textLayout; // display text - QString text; - - int cursor; - int preeditCursor; - int lastCursorPos; - int cursorWidth; - int cursorTimer; - - int maxLength; - - int modifiedState; - int undoState; - - int selStart, selEnd; - - Qt::TextInteractionFlags textInteractionFlags; - - // keep together and at end - uint cursorVisible : 1; - uint hideCursor : 1; // used to hide the cursor inside preedit areas - uint echoMode : 2; -}; - -QT_END_NAMESPACE - -#endif // QLINECONTROL_P_H - -- cgit v0.12 From 291703873d208fec1eba1a039a79a61543745b35 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 14 Jul 2009 14:17:28 +1000 Subject: Cleanup some incorrect changes to QLineEdit --- src/gui/widgets/qlineedit.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 92dcfc4..9252888 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1382,8 +1382,6 @@ bool QLineEdit::event(QEvent * e) QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate())); }else if(e->type() == QEvent::ShortcutOverride){ d->control->processEvent(e); - }else if(e->type() == QEvent::LayoutDirectionChange){ - d->control->setLayoutDirection((layoutDirection())); } #ifdef QT_KEYPAD_NAVIGATION @@ -1462,7 +1460,9 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) d->drag(); } else #endif + { d->control->moveCursor(d->xToPos(e->pos().x()), true); + } } } @@ -1473,16 +1473,15 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) return; - - if (e->buttons() & Qt::LeftButton) { #ifndef QT_NO_DRAGANDDROP + if (e->button() == Qt::LeftButton) { if (d->dndTimer.isActive()) { - if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) - d->drag(); - } else -#endif - d->control->moveCursor(d->xToPos(e->pos().x()), true); + d->dndTimer.stop(); + deselect(); + return; + } } +#endif #ifndef QT_NO_CLIPBOARD if (QApplication::clipboard()->supportsSelection()) { if (e->button() == Qt::LeftButton) { -- cgit v0.12 From 1bd89d1c8a9bc41f8ea76f55a2ebd17447fc2d70 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 15:05:42 +0200 Subject: Add '\internal' to the QLineControl documentation. --- src/gui/widgets/qlinecontrol.cpp | 142 ++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 40 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 557892f..9b2a47a 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -59,7 +59,9 @@ QT_BEGIN_NAMESPACE -/* +/*! + \internal + Updates the display text based of the current edit text If the text has changed will emit displayTextChanged() */ @@ -105,7 +107,9 @@ void QLineControl::updateDisplayText() } #ifndef QT_NO_CLIPBOARD -/* +/*! + \internal + Copies the currently selected text into the clipboard using the given \a mode. @@ -124,7 +128,9 @@ void QLineControl::copy(QClipboard::Mode mode) const } } -/* +/*! + \internal + Inserts the text stored in the application clipboard into the line control. @@ -137,7 +143,9 @@ void QLineControl::paste() #endif // !QT_NO_CLIPBOARD -/* +/*! + \internal + Handles the behavior for the backspace key or function. Removes the current selection if there is a selection, otherwise removes the character prior to the cursor position. @@ -168,7 +176,9 @@ void QLineControl::backspace() finishChange(priorState); } -/* +/*! + \internal + Handles the behavior for the delete key or function. Removes the current selection if there is a selection, otherwise removes the character after the cursor position. @@ -188,7 +198,9 @@ void QLineControl::del() finishChange(priorState); } -/* +/*! + \internal + Inserts the given \a newText at the current cursor position. If there is any selected text it is removed prior to insertion of the new text. @@ -201,7 +213,9 @@ void QLineControl::insert(const QString &newText) finishChange(priorState); } -/* +/*! + \internal + Clears the line control text. */ void QLineControl::clear() @@ -214,7 +228,9 @@ void QLineControl::clear() finishChange(priorState, /*update*/false, /*edited*/false); } -/* +/*! + \internal + Sets \a length characters from the given \a start position as selected. The given \a start position must be within the current text for the line control. If \a length characters cannot be selected, then @@ -254,7 +270,9 @@ void QLineControl::_q_deleteSelected() finishChange(priorState); } -/* +/*! + \internal + Initializes the line control with a starting text value of \a txt. */ void QLineControl::init(const QString& txt) @@ -264,7 +282,9 @@ void QLineControl::init(const QString& txt) m_cursor = m_text.length(); } -/* +/*! + \internal + Sets the password echo editing to \a editing. If password echo editing is true, then the text of the password is displayed even if the echo mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing @@ -276,7 +296,9 @@ void QLineControl::updatePasswordEchoEditing(bool editing) updateDisplayText(); } -/* +/*! + \internal + Returns the cursor position of the given \a x pixel value in relation to the displayed text. The given \a betweenOrOn specified what kind of cursor position is requested. @@ -286,7 +308,9 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const return textLayout.lineAt(0).xToCursor(x, betweenOrOn); } -/* +/*! + \internal + Returns the bounds of the current cursor, as defined as a between characters cursor. */ @@ -303,7 +327,9 @@ QRect QLineControl::cursorRect() const return QRect(cix-5, 0, w+9, ch); } -/* +/*! + \internal + Fixes the current text so that it is valid given any set validators. Returns true if the text was changed. Otherwise returns false. @@ -325,7 +351,9 @@ bool QLineControl::fixup() // this function assumes that validate currently retu return false; } -/* +/*! + \internal + Moves the cursor to the given position \a pos. If \a mark is true will adjust the currently selected text. */ @@ -358,7 +386,9 @@ void QLineControl::moveCursor(int pos, bool mark) emitCursorPositionChanged(); } -/* +/*! + \internal + Applies the given input method event \a event to the text of the line control */ @@ -411,7 +441,9 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) finishChange(priorState); } -/* +/*! + \internal + Draws the display text for the line control using the given \a painter, \a clip, and \a offset. Which aspects of the display text are drawn is specified by the given \a flags. @@ -453,7 +485,9 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl } } -/* +/*! + \internal + Sets the selection to cover the word at the given cursor position. The word boundries is defined by the behavior of QTextLayout::SkipWords cursor mode. @@ -469,7 +503,9 @@ void QLineControl::selectWordAtPos(int cursor) moveCursor(end, true); } -/* +/*! + \internal + Completes a change to the line control text. If the change is not valid will undo the line control state back to the given \a validateFromState. @@ -479,7 +515,6 @@ void QLineControl::selectWordAtPos(int cursor) The \a update value is currently unused. */ - bool QLineControl::finishChange(int validateFromState, bool update, bool edited) { Q_UNUSED(update) @@ -531,7 +566,9 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) return true; } -/* +/*! + \internal + An internal function for setting the text of the line control. */ void QLineControl::p_setText(const QString& txt, int pos, bool edited) @@ -553,7 +590,9 @@ void QLineControl::p_setText(const QString& txt, int pos, bool edited) } -/* +/*! + \internal + Adds the given \a command to the undo history of the line control. Does not apply the command. */ @@ -569,7 +608,9 @@ void QLineControl::addCommand(const Command& cmd) history[undoState++] = cmd; } -/* +/*! + \internal + Inserts the given string \a s into the line control. @@ -602,8 +643,9 @@ void QLineControl::p_insert(const QString& s) } } -/* +/*! \internal + deletes a single character from the current text. If \a wasBackspace, the character prior to the cursor is removed. Otherwise the character after the cursor is removed. @@ -628,8 +670,9 @@ void QLineControl::p_del(bool wasBackspace) } } -/* +/*! \internal + removes the currently selected text from the line control. Also adds the appropriate commands into the undo history. @@ -667,7 +710,9 @@ void QLineControl::removeSelectedText() } } -/* +/*! + \internal + Parses the input mask specified by \a maskFields to generate the mask data used to handle input masks. */ @@ -769,7 +814,11 @@ void QLineControl::parseInputMask(const QString &maskFields) } -/* checks if the key is valid compared to the inputMask */ +/*! + \internal + + checks if the key is valid compared to the inputMask +*/ bool QLineControl::isValidInput(QChar key, QChar mask) const { switch (mask.unicode()) { @@ -839,7 +888,9 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return false; } -/* +/*! + \internal + Returns true if the given text \a str is valid for any validator or input mask set for the line control. @@ -873,11 +924,13 @@ bool QLineControl::hasAcceptableInput(const QString &str) const return true; } -/* - Applies the inputMask on \a str starting from position \a pos in the mask. \a clear - specifies from where characters should be gotten when a separator is met in \a str - true means - that blanks will be used, false that previous input is used. - Calling this when no inputMask is set is undefined. +/*! + \internal + + Applies the inputMask on \a str starting from position \a pos in the mask. \a clear + specifies from where characters should be gotten when a separator is met in \a str - true means + that blanks will be used, false that previous input is used. + Calling this when no inputMask is set is undefined. */ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const { @@ -948,9 +1001,11 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const -/* - Returns a "cleared" string with only separators and blank chars. - Calling this when no inputMask is set is undefined. +/*! + \internal + + Returns a "cleared" string with only separators and blank chars. + Calling this when no inputMask is set is undefined. */ QString QLineControl::clearString(uint pos, uint len) const { @@ -968,9 +1023,11 @@ QString QLineControl::clearString(uint pos, uint len) const return s; } -/* - Strips blank parts of the input in a QLineControl when an inputMask is set, - separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". +/*! + \internal + + Strips blank parts of the input in a QLineControl when an inputMask is set, + separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". */ QString QLineControl::stripString(const QString &str) const { @@ -989,7 +1046,10 @@ QString QLineControl::stripString(const QString &str) const return s; } -/* searches forward/backward in maskData for either a separator or a blank */ +/*! + \internal + searches forward/backward in maskData for either a separator or a blank +*/ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const { if (pos >= m_maxLength || pos < 0) @@ -1099,7 +1159,9 @@ void QLineControl::p_redo() { emitCursorPositionChanged(); } -/* +/*! + \internal + If the current cursor position differs from the last emited cursor position, emits cursorPositionChanged(). */ -- cgit v0.12 From 363221747e68b7a5930afdeef87a5454f40c5ffb Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 15:19:35 +0200 Subject: Some minor style and whitespace fixes. --- src/gui/widgets/qlinecontrol.cpp | 59 ++++++++++++++++++++-------------------- src/gui/widgets/qlinecontrol_p.h | 23 ++++++++++------ 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 9b2a47a..6d8fe06 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -275,7 +275,7 @@ void QLineControl::_q_deleteSelected() Initializes the line control with a starting text value of \a txt. */ -void QLineControl::init(const QString& txt) +void QLineControl::init(const QString &txt) { m_text = txt; updateDisplayText(); @@ -571,7 +571,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) An internal function for setting the text of the line control. */ -void QLineControl::p_setText(const QString& txt, int pos, bool edited) +void QLineControl::p_setText(const QString &txt, int pos, bool edited) { p_deselect(); emit resetInputContext(); @@ -596,7 +596,7 @@ void QLineControl::p_setText(const QString& txt, int pos, bool edited) Adds the given \a command to the undo history of the line control. Does not apply the command. */ -void QLineControl::addCommand(const Command& cmd) +void QLineControl::addCommand(const Command &cmd) { if (separator && undoState && history[undoState-1].type != Separator) { history.resize(undoState + 2); @@ -618,15 +618,15 @@ void QLineControl::addCommand(const Command& cmd) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_insert(const QString& s) +void QLineControl::p_insert(const QString &s) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); if (maskData) { QString ms = maskString(m_cursor, s); for (int i = 0; i < (int) ms.length(); ++i) { - addCommand (Command(DeleteSelection, m_cursor+i, m_text.at(m_cursor+i), -1, -1)); - addCommand(Command(Insert, m_cursor+i, ms.at(i), -1, -1)); + addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); + addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1)); } m_text.replace(m_cursor, ms.length(), ms); m_cursor += ms.length(); @@ -659,7 +659,8 @@ void QLineControl::p_del(bool wasBackspace) if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); + addCommand(Command((CommandType)((maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), + m_cursor, m_text.at(m_cursor), -1, -1)); if (maskData) { m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); @@ -990,7 +991,7 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const } } } - strIndex++; + ++strIndex; } } else break; @@ -1014,7 +1015,7 @@ QString QLineControl::clearString(uint pos, uint len) const QString s; int end = qMin((uint)m_maxLength, pos + len); - for (int i=pos; itimerId() == m_blinkTimer) { + if (event->timerId() == m_blinkTimer) { m_blinkStatus = !m_blinkStatus; - emit updateNeeded(inputMask().isEmpty()?cursorRect():QRect()); - }else if(event->timerId() == m_deleteAllTimer){ + emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); + } else if (event->timerId() == m_deleteAllTimer) { killTimer(m_deleteAllTimer); m_deleteAllTimer = 0; clear(); - }else if(event->timerId() == m_tripleClickTimer){ + } else if (event->timerId() == m_tripleClickTimer) { killTimer(m_tripleClickTimer); m_tripleClickTimer = 0; } @@ -1371,11 +1372,12 @@ bool QLineControl::processEvent(QEvent* ev) void QLineControl::processMouseEvent(QMouseEvent* ev) { - switch (ev->type()){ + switch (ev->type()) { case QEvent::GraphicsSceneMousePress: case QEvent::MouseButtonPress:{ - if (m_tripleClickTimer && (ev->pos() - m_tripleClick).manhattanLength() < - QApplication::startDragDistance()) { + if (m_tripleClickTimer + && (ev->pos() - m_tripleClick).manhattanLength() + < QApplication::startDragDistance()) { selectAll(); return; } @@ -1390,7 +1392,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) case QEvent::MouseButtonDblClick: if (ev->button() == Qt::LeftButton) { selectWordAtPos(xToPos(ev->pos().x())); - if(m_tripleClickTimer) + if (m_tripleClickTimer) killTimer(m_tripleClickTimer); m_tripleClickTimer = startTimer(QApplication::doubleClickInterval()); m_tripleClick = ev->pos(); @@ -1412,7 +1414,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) case QEvent::GraphicsSceneMouseMove: case QEvent::MouseMove: if (ev->buttons() & Qt::LeftButton) { - moveCursor(xToPos(ev->pos().x()), true); + moveCursor(xToPos(ev->pos().x()), true); } break; default: @@ -1422,7 +1424,6 @@ void QLineControl::processMouseEvent(QMouseEvent* ev) void QLineControl::processKeyEvent(QKeyEvent* event) { - bool inlineCompletionAccepted = false; #ifndef QT_NO_COMPLETER @@ -1472,8 +1473,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event) } #endif // QT_NO_COMPLETER - - if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing() && !isReadOnly() diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 4ecedcd..2d93e90 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -462,8 +462,10 @@ inline void QLineControl::removeSelection() inline bool QLineControl::inSelection(int x) const { - if (selstart >= selend) return false; - int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; + if (selstart >= selend) + return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); + return pos >= selstart && pos < selend; } inline int QLineControl::cursor() const @@ -557,22 +559,26 @@ inline QString QLineControl::displayText() const inline void QLineControl::deselect() { - p_deselect(); finishChange(); + p_deselect(); + finishChange(); } inline void QLineControl::selectAll() { - selstart = selend = m_cursor = 0; moveCursor(m_text.length(), true); + selstart = selend = m_cursor = 0; + moveCursor(m_text.length(), true); } inline void QLineControl::undo() { - p_undo(), finishChange(-1, true); + p_undo(); + finishChange(-1, true); } inline void QLineControl::redo() { - p_redo(), finishChange(); + p_redo(); + finishChange(); } inline uint QLineControl::echoMode() const @@ -625,7 +631,8 @@ inline void QLineControl::setCompleter(const QCompleter* c) inline void QLineControl::setCursorPosition(int pos) { - if (pos < 0) pos = 0; + if (pos < 0) + pos = 0; if (pos < m_text.length()) moveCursor(pos); } @@ -723,7 +730,7 @@ inline void QLineControl::setCancelText(QString s) QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_LINEEDIT +#endif // QT_NO_LINEEDIT #endif // QLINECONTROL_P_H -- cgit v0.12 From aec21d2255e9927689e640b36150b7c9a4e9f522 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 16:16:47 +0200 Subject: Make the member variable names in QLineControl consistent. --- src/gui/widgets/qlinecontrol.cpp | 330 +++++++++++++++++++-------------------- src/gui/widgets/qlinecontrol_p.h | 161 ++++++++++--------- src/gui/widgets/qlineedit.cpp | 6 +- src/gui/widgets/qlineedit_p.h | 1 - 4 files changed, 253 insertions(+), 245 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 6d8fe06..50ce6e6 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE */ void QLineControl::updateDisplayText() { - QString orig = textLayout.text(); + QString orig = m_textLayout.text(); QString str; if (m_echoMode == QLineEdit::NoEcho) str = QString::fromLatin1(""); @@ -90,16 +90,16 @@ void QLineControl::updateDisplayText() uc[i] = QChar(0x0020); } - textLayout.setText(str); + m_textLayout.setText(str); QTextOption option; option.setTextDirection(m_layoutDirection); option.setFlags(QTextOption::IncludeTrailingSpaces); - textLayout.setTextOption(option); + m_textLayout.setTextOption(option); - textLayout.beginLayout(); - QTextLine l = textLayout.createLine(); - textLayout.endLayout(); + m_textLayout.beginLayout(); + QTextLine l = m_textLayout.createLine(); + m_textLayout.endLayout(); m_ascent = qRound(l.ascent()); if (str != orig) @@ -154,12 +154,12 @@ void QLineControl::paste() */ void QLineControl::backspace() { - int priorState = undoState; + int priorState = m_undoState; if (hasSelectedText()) { removeSelectedText(); } else if (m_cursor) { --m_cursor; - if (maskData) + if (m_maskData) m_cursor = prevMaskBlank(m_cursor); QChar uc = m_text.at(m_cursor); if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { @@ -187,11 +187,11 @@ void QLineControl::backspace() */ void QLineControl::del() { - int priorState = undoState; + int priorState = m_undoState; if (hasSelectedText()) { removeSelectedText(); } else { - int n = textLayout.nextCursorPosition(m_cursor) - m_cursor; + int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; while (n--) p_del(); } @@ -207,7 +207,7 @@ void QLineControl::del() */ void QLineControl::insert(const QString &newText) { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); p_insert(newText); finishChange(priorState); @@ -220,9 +220,9 @@ void QLineControl::insert(const QString &newText) */ void QLineControl::clear() { - int priorState = undoState; - selstart = 0; - selend = m_text.length(); + int priorState = m_undoState; + m_selstart = 0; + m_selend = m_text.length(); removeSelectedText(); separate(); finishChange(priorState, /*update*/false, /*edited*/false); @@ -244,13 +244,13 @@ void QLineControl::setSelection(int start, int length) } if (length > 0) { - selstart = start; - selend = qMin(start + length, (int)m_text.length()); - m_cursor = selend; + m_selstart = start; + m_selend = qMin(start + length, (int)m_text.length()); + m_cursor = m_selend; } else { - selstart = qMax(start + length, 0); - selend = start; - m_cursor = selstart; + m_selstart = qMax(start + length, 0); + m_selend = start; + m_cursor = m_selstart; } } @@ -263,7 +263,7 @@ void QLineControl::_q_deleteSelected() if (!hasSelectedText()) return; - int priorState = undoState; + int priorState = m_undoState; emit resetInputContext(); removeSelectedText(); separate(); @@ -305,7 +305,7 @@ void QLineControl::updatePasswordEchoEditing(bool editing) */ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const { - return textLayout.lineAt(0).xToCursor(x, betweenOrOn); + return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn); } /*! @@ -316,7 +316,7 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const */ QRect QLineControl::cursorRect() const { - QTextLine l = textLayout.lineAt(0); + QTextLine l = m_textLayout.lineAt(0); int c = m_cursor; if (m_preeditCursor != -1) c += m_preeditCursor; @@ -361,26 +361,26 @@ void QLineControl::moveCursor(int pos, bool mark) { if (pos != m_cursor) { separate(); - if (maskData) + if (m_maskData) pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); } if (mark) { int anchor; - if (selend > selstart && m_cursor == selstart) - anchor = selend; - else if (selend > selstart && m_cursor == selend) - anchor = selstart; + if (m_selend > m_selstart && m_cursor == m_selstart) + anchor = m_selend; + else if (m_selend > m_selstart && m_cursor == m_selend) + anchor = m_selstart; else anchor = m_cursor; - selstart = qMin(anchor, pos); - selend = qMax(anchor, pos); + m_selstart = qMin(anchor, pos); + m_selend = qMax(anchor, pos); updateDisplayText(); } else { p_deselect(); } m_cursor = pos; - if (mark || selDirty) { - selDirty = false; + if (mark || m_selDirty) { + m_selDirty = false; emit selectionChanged(); } emitCursorPositionChanged(); @@ -394,7 +394,7 @@ void QLineControl::moveCursor(int pos, bool mark) */ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); int c = m_cursor; // cursor position after insertion of commit string @@ -405,8 +405,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) // insert commit string if (event->replacementLength()) { - selstart = m_cursor; - selend = selstart + event->replacementLength(); + m_selstart = m_cursor; + m_selend = m_selstart + event->replacementLength(); removeSelectedText(); } if (!event->commitString().isEmpty()) @@ -416,13 +416,13 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) setPreeditArea(m_cursor, event->preeditString()); m_preeditCursor = event->preeditString().length(); - hideCursor = false; + m_hideCursor = false; QList formats; for (int i = 0; i < event->attributes().size(); ++i) { const QInputMethodEvent::Attribute &a = event->attributes().at(i); if (a.type == QInputMethodEvent::Cursor) { m_preeditCursor = a.start; - hideCursor = !a.length; + m_hideCursor = !a.length; } else if (a.type == QInputMethodEvent::TextFormat) { QTextCharFormat f = qvariant_cast(a.value).toCharFormat(); if (f.isValid()) { @@ -434,7 +434,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) } } } - textLayout.setAdditionalFormats(formats); + m_textLayout.setAdditionalFormats(formats); updateDisplayText(); if (!event->commitString().isEmpty()) emitCursorPositionChanged(); @@ -461,9 +461,9 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl QVector selections; if (flags & DrawSelections) { QTextLayout::FormatRange o; - if (selstart < selend) { - o.start = selstart; - o.length = selend - selstart; + if (m_selstart < m_selend) { + o.start = m_selstart; + o.length = m_selend - m_selstart; o.format.setBackground(m_palette.brush(QPalette::Highlight)); o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); } else { @@ -477,11 +477,11 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl } if (flags & DrawText) - textLayout.draw(painter, offset, selections, clip); + m_textLayout.draw(painter, offset, selections, clip); if (flags & DrawCursor){ if(!m_blinkPeriod || m_blinkStatus) - textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); } } @@ -494,10 +494,10 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. - int end = textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); while (end > cursor && m_text[end-1].isSpace()) --end; moveCursor(end, true); @@ -518,18 +518,18 @@ void QLineControl::selectWordAtPos(int cursor) bool QLineControl::finishChange(int validateFromState, bool update, bool edited) { Q_UNUSED(update) - bool lineDirty = selDirty; - if (textDirty) { + bool lineDirty = m_selDirty; + if (m_textDirty) { // do validation - bool wasValidInput = validInput; - validInput = true; + bool wasValidInput = m_validInput; + m_validInput = true; #ifndef QT_NO_VALIDATOR if (m_validator) { - validInput = false; + m_validInput = false; QString textCopy = m_text; int cursorCopy = m_cursor; - validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); - if (validInput) { + m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (m_validInput) { if (m_text != textCopy) { p_setText(textCopy, cursorCopy); return true; @@ -538,28 +538,28 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) } } #endif - if (validateFromState >= 0 && wasValidInput && !validInput) { - if (transactions.count()) + if (validateFromState >= 0 && wasValidInput && !m_validInput) { + if (m_transactions.count()) return false; p_undo(validateFromState); - history.resize(undoState); - if (modifiedState > undoState) - modifiedState = -1; - validInput = true; - textDirty = false; + m_history.resize(m_undoState); + if (m_modifiedState > m_undoState) + m_modifiedState = -1; + m_validInput = true; + m_textDirty = false; } updateDisplayText(); - lineDirty |= textDirty; - if (textDirty) { - textDirty = false; + lineDirty |= m_textDirty; + if (m_textDirty) { + m_textDirty = false; QString actualText = text(); if (edited) emit textEdited(actualText); emit textChanged(actualText); } } - if (selDirty) { - selDirty = false; + if (m_selDirty) { + m_selDirty = false; emit selectionChanged(); } emitCursorPositionChanged(); @@ -576,16 +576,16 @@ void QLineControl::p_setText(const QString &txt, int pos, bool edited) p_deselect(); emit resetInputContext(); QString oldText = m_text; - if (maskData) { + if (m_maskData) { m_text = maskString(0, txt, true); m_text += clearString(m_text.length(), m_maxLength - m_text.length()); } else { m_text = txt.isEmpty() ? txt : txt.left(m_maxLength); } - history.clear(); - modifiedState = undoState = 0; + m_history.clear(); + m_modifiedState = m_undoState = 0; m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; - textDirty = (oldText != m_text); + m_textDirty = (oldText != m_text); finishChange(-1, true, edited); } @@ -598,14 +598,14 @@ void QLineControl::p_setText(const QString &txt, int pos, bool edited) */ void QLineControl::addCommand(const Command &cmd) { - if (separator && undoState && history[undoState-1].type != Separator) { - history.resize(undoState + 2); - history[undoState++] = Command(Separator, m_cursor, 0, selstart, selend); + if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) { + m_history.resize(m_undoState + 2); + m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend); } else { - history.resize(undoState + 1); + m_history.resize(m_undoState + 1); } - separator = false; - history[undoState++] = cmd; + m_separator = false; + m_history[m_undoState++] = cmd; } /*! @@ -621,8 +621,8 @@ void QLineControl::addCommand(const Command &cmd) void QLineControl::p_insert(const QString &s) { if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - if (maskData) { + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_maskData) { QString ms = maskString(m_cursor, s); for (int i = 0; i < (int) ms.length(); ++i) { addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); @@ -631,14 +631,14 @@ void QLineControl::p_insert(const QString &s) m_text.replace(m_cursor, ms.length(), ms); m_cursor += ms.length(); m_cursor = nextMaskBlank(m_cursor); - textDirty = true; + m_textDirty = true; } else { int remaining = m_maxLength - m_text.length(); if (remaining != 0) { m_text.insert(m_cursor, s.left(remaining)); for (int i = 0; i < (int) s.left(remaining).length(); ++i) addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); - textDirty = true; + m_textDirty = true; } } } @@ -658,16 +658,16 @@ void QLineControl::p_del(bool wasBackspace) { if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - addCommand(Command((CommandType)((maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), m_cursor, m_text.at(m_cursor), -1, -1)); - if (maskData) { + if (m_maskData) { m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); } else { m_text.remove(m_cursor, 1); } - textDirty = true; + m_textDirty = true; } } @@ -682,32 +682,32 @@ void QLineControl::p_del(bool wasBackspace) */ void QLineControl::removeSelectedText() { - if (selstart < selend && selend <= (int) m_text.length()) { + if (m_selstart < m_selend && m_selend <= (int) m_text.length()) { separate(); int i ; - addCommand(Command(SetSelection, m_cursor, 0, selstart, selend)); - if (selstart <= m_cursor && m_cursor < selend) { + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_selstart <= m_cursor && m_cursor < m_selend) { // cursor is within the selection. Split up the commands // to be able to restore the correct cursor position - for (i = m_cursor; i >= selstart; --i) + for (i = m_cursor; i >= m_selstart; --i) addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1)); - for (i = selend - 1; i > m_cursor; --i) - addCommand (Command(DeleteSelection, i - m_cursor + selstart - 1, m_text.at(i), -1, -1)); + for (i = m_selend - 1; i > m_cursor; --i) + addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1)); } else { - for (i = selend-1; i >= selstart; --i) + for (i = m_selend-1; i >= m_selstart; --i) addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); } - if (maskData) { - m_text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart)); - for (int i = 0; i < selend - selstart; ++i) - addCommand(Command(Insert, selstart + i, m_text.at(selstart + i), -1, -1)); + if (m_maskData) { + m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart)); + for (int i = 0; i < m_selend - m_selstart; ++i) + addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1)); } else { - m_text.remove(selstart, selend - selstart); + m_text.remove(m_selstart, m_selend - m_selstart); } - if (m_cursor > selstart) - m_cursor -= qMin(m_cursor, selend) - selstart; + if (m_cursor > m_selstart) + m_cursor -= qMin(m_cursor, m_selend) - m_selstart; p_deselect(); - textDirty = true; + m_textDirty = true; } } @@ -721,9 +721,9 @@ void QLineControl::parseInputMask(const QString &maskFields) { int delimiter = maskFields.indexOf(QLatin1Char(';')); if (maskFields.isEmpty() || delimiter == 0) { - if (maskData) { - delete [] maskData; - maskData = 0; + if (m_maskData) { + delete [] m_maskData; + m_maskData = 0; m_maxLength = 32767; p_setText(QString()); } @@ -731,14 +731,14 @@ void QLineControl::parseInputMask(const QString &maskFields) } if (delimiter == -1) { - blank = QLatin1Char(' '); + m_blank = QLatin1Char(' '); m_inputMask = maskFields; } else { m_inputMask = maskFields.left(delimiter); - blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); } - // calculate m_maxLength / maskData length + // calculate m_maxLength / m_maskData length m_maxLength = 0; QChar c = 0; for (int i=0; i 0) || key == blank) + if ((key.isNumber() && key.digitValue() > 0) || key == m_blank) return true; break; case '#': - if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank) + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank) return true; break; case 'B': @@ -872,7 +872,7 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return true; break; case 'b': - if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank) + if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank) return true; break; case 'H': @@ -880,7 +880,7 @@ bool QLineControl::isValidInput(QChar key, QChar mask) const return true; break; case 'h': - if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank) + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank) return true; break; default: @@ -907,18 +907,18 @@ bool QLineControl::hasAcceptableInput(const QString &str) const return false; #endif - if (!maskData) + if (!m_maskData) return true; if (str.length() != m_maxLength) return false; for (int i=0; i < m_maxLength; ++i) { - if (maskData[i].separator) { - if (str.at(i) != maskData[i].maskChar) + if (m_maskData[i].separator) { + if (str.at(i) != m_maskData[i].maskChar) return false; } else { - if (!isValidInput(str.at(i), maskData[i].maskChar)) + if (!isValidInput(str.at(i), m_maskData[i].maskChar)) return false; } } @@ -946,14 +946,14 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const int i = pos; while (i < m_maxLength) { if (strIndex < str.length()) { - if (maskData[i].separator) { - s += maskData[i].maskChar; - if (str[(int)strIndex] == maskData[i].maskChar) + if (m_maskData[i].separator) { + s += m_maskData[i].maskChar; + if (str[(int)strIndex] == m_maskData[i].maskChar) strIndex++; ++i; } else { - if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) { - switch (maskData[i].caseMode) { + if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) { + switch (m_maskData[i].caseMode) { case MaskInputData::Upper: s += str[(int)strIndex].toUpper(); break; @@ -968,16 +968,16 @@ QString QLineControl::maskString(uint pos, const QString &str, bool clear) const // search for separator first int n = findInMask(i, true, true, str[(int)strIndex]); if (n != -1) { - if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) { + if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) { s += fill.mid(i, n-i+1); i = n + 1; // update i to find + 1 } } else { - // search for valid blank if not + // search for valid m_blank if not n = findInMask(i, true, false, str[(int)strIndex]); if (n != -1) { s += fill.mid(i, n-i); - switch (maskData[n].caseMode) { + switch (m_maskData[n].caseMode) { case MaskInputData::Upper: s += str[(int)strIndex].toUpper(); break; @@ -1016,10 +1016,10 @@ QString QLineControl::clearString(uint pos, uint len) const QString s; int end = qMin((uint)m_maxLength, pos + len); for (int i = pos; i < end; ++i) - if (maskData[i].separator) - s += maskData[i].maskChar; + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; else - s += blank; + s += m_blank; return s; } @@ -1032,16 +1032,16 @@ QString QLineControl::clearString(uint pos, uint len) const */ QString QLineControl::stripString(const QString &str) const { - if (!maskData) + if (!m_maskData) return str; QString s; int end = qMin(m_maxLength, (int)str.length()); for (int i = 0; i < end; ++i) - if (maskData[i].separator) - s += maskData[i].maskChar; + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; else - if (str[i] != blank) + if (str[i] != m_blank) s += str[i]; return s; @@ -1049,7 +1049,7 @@ QString QLineControl::stripString(const QString &str) const /*! \internal - searches forward/backward in maskData for either a separator or a blank + searches forward/backward in m_maskData for either a separator or a m_blank */ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const { @@ -1062,13 +1062,13 @@ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar se while (i != end) { if (findSeparator) { - if (maskData[i].separator && maskData[i].maskChar == searchChar) + if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar) return i; } else { - if (!maskData[i].separator) { + if (!m_maskData[i].separator) { if (searchChar.isNull()) return i; - else if (isValidInput(searchChar, maskData[i].maskChar)) + else if (isValidInput(searchChar, m_maskData[i].maskChar)) return i; } } @@ -1082,16 +1082,16 @@ void QLineControl::p_undo(int until) if (!isUndoAvailable()) return; p_deselect(); - while (undoState && undoState > until) { - Command& cmd = history[--undoState]; + while (m_undoState && m_undoState > until) { + Command& cmd = m_history[--m_undoState]; switch (cmd.type) { case Insert: m_text.remove(cmd.pos, 1); m_cursor = cmd.pos; break; case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Remove: @@ -1107,14 +1107,14 @@ void QLineControl::p_undo(int until) case Separator: continue; } - if (until < 0 && undoState) { - Command& next = history[undoState-1]; + if (until < 0 && m_undoState) { + Command& next = m_history[m_undoState-1]; if (next.type != cmd.type && next.type < RemoveSelection && (cmd.type < RemoveSelection || next.type == Separator)) break; } } - textDirty = true; + m_textDirty = true; emitCursorPositionChanged(); } @@ -1122,16 +1122,16 @@ void QLineControl::p_redo() { if (!isRedoAvailable()) return; p_deselect(); - while (undoState < (int)history.size()) { - Command& cmd = history[undoState++]; + while (m_undoState < (int)m_history.size()) { + Command& cmd = m_history[m_undoState++]; switch (cmd.type) { case Insert: m_text.insert(cmd.pos, cmd.uc); m_cursor = cmd.pos + 1; break; case SetSelection: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Remove: @@ -1139,24 +1139,24 @@ void QLineControl::p_redo() { case RemoveSelection: case DeleteSelection: m_text.remove(cmd.pos, 1); - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; case Separator: - selstart = cmd.selStart; - selend = cmd.selEnd; + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; m_cursor = cmd.pos; break; } - if (undoState < (int)history.size()) { - Command& next = history[undoState]; + if (m_undoState < (int)m_history.size()) { + Command& next = m_history[m_undoState]; if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator && (next.type < RemoveSelection || cmd.type == Separator)) break; } } - textDirty = true; + m_textDirty = true; emitCursorPositionChanged(); } @@ -1168,9 +1168,9 @@ void QLineControl::p_redo() { */ void QLineControl::emitCursorPositionChanged() { - if (m_cursor != lastCursorPos) { - const int oldLast = lastCursorPos; - lastCursorPos = m_cursor; + if (m_cursor != m_lastCursorPos) { + const int oldLast = m_lastCursorPos; + m_lastCursorPos = m_cursor; cursorPositionChanged(oldLast, m_cursor); } } @@ -1496,9 +1496,9 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); - emitingEditingFinished = true; + m_emitingEditingFinished = true; emit editingFinished(); - emitingEditingFinished = false; + m_emitingEditingFinished = false; } if (inlineCompletionAccepted) event->accept(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 2d93e90..6029989 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -75,24 +75,24 @@ QT_MODULE(Gui) class Q_GUI_EXPORT QLineControl : public QObject { Q_OBJECT -public: +public: QLineControl(const QString &txt = QString()) - : emitingEditingFinished(0), + : m_emitingEditingFinished(0), m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), - hideCursor(false), separator(0), readOnly(0), - dragEnabled(0), m_echoMode(0), textDirty(0), selDirty(0), - validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), - m_ascent(0), m_maxLength(32767), lastCursorPos(-1), - m_tripleClickTimer(0), maskData(0), modifiedState(0), undoState(0), - selstart(0), selend(0), m_passwordEchoEditing(false) + m_hideCursor(false), m_separator(0), m_readOnly(0), + m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), + m_validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1), + m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0), + m_selstart(0), m_selend(0), m_passwordEchoEditing(false) { init(txt); } ~QLineControl() { - delete [] maskData; + delete [] m_maskData; } int nextMaskBlank(int pos); @@ -154,7 +154,7 @@ public: void setReadOnly(bool enable); QString text() const; - void setText(const QString &); + void setText(const QString &txt); QString displayText() const; @@ -218,7 +218,7 @@ public: void setCursorBlinkPeriod(int msec); QString cancelText() const; - void setCancelText(QString); + void setCancelText(const QString &text); enum DrawFlags { DrawText = 0x01, @@ -228,19 +228,26 @@ public: }; void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll); - bool processEvent(QEvent* ev); + bool processEvent(QEvent *ev); + + bool m_emitingEditingFinished; //Needed in QLineEdit FocusOut event - bool emitingEditingFinished;//Needed in QLineEdit FocusOut event private: - void init(const QString&); + void init(const QString &txt); void removeSelectedText(); - void p_setText(const QString& txt, int pos = -1, bool edited = true); + void p_setText(const QString &txt, int pos = -1, bool edited = true); void updateDisplayText(); - void p_insert(const QString& s); + void p_insert(const QString &s); void p_del(bool wasBackspace = false); void p_remove(int pos); - inline void p_deselect() { selDirty |= (selend > selstart); selstart = selend = 0; } + + inline void p_deselect() + { + m_selDirty |= (m_selend > m_selstart); + m_selstart = m_selend = 0; + } + void p_undo(int until = -1); void p_redo(); @@ -250,22 +257,22 @@ private: int m_preeditCursor; int m_cursorWidth; Qt::LayoutDirection m_layoutDirection; - uint hideCursor : 1; // used to hide the m_cursor inside preedit areas - uint separator : 1; - uint readOnly : 1; - uint dragEnabled : 1; + uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas + uint m_separator : 1; + uint m_readOnly : 1; + uint m_dragEnabled : 1; uint m_echoMode : 2; - uint textDirty : 1; - uint selDirty : 1; - uint validInput : 1; + uint m_textDirty : 1; + uint m_selDirty : 1; + uint m_validInput : 1; int m_blinkPeriod; // 0 for non-blinking cursor int m_blinkTimer; int m_deleteAllTimer; int m_blinkStatus; int m_ascent; int m_maxLength; - int lastCursorPos; - QList transactions; + int m_lastCursorPos; + QList m_transactions; QPoint m_tripleClick; int m_tripleClickTimer; QString m_cancelText; @@ -287,8 +294,8 @@ private: Casemode caseMode; }; QString m_inputMask; - QChar blank; - MaskInputData *maskData; + QChar m_blank; + MaskInputData *m_maskData; // undo/redo handling @@ -300,15 +307,16 @@ private: QChar uc; int pos, selStart, selEnd; }; - int modifiedState; - int undoState; - QVector history; + int m_modifiedState; + int m_undoState; + QVector m_history; void addCommand(const Command& cmd); - inline void separate() { separator = true; } + inline void separate() { m_separator = true; } // selection - int selstart, selend; + int m_selstart; + int m_selend; // masking void parseInputMask(const QString &maskFields); @@ -319,9 +327,8 @@ private: QString stripString(const QString &str) const; int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; - // complex text layout - QTextLayout textLayout; + QTextLayout m_textLayout; bool m_passwordEchoEditing; QChar m_passwordCharacter; @@ -339,8 +346,10 @@ Q_SIGNALS: void accepted(); void editingFinished(); void updateNeeded(const QRect &); + protected: - virtual void timerEvent ( QTimerEvent * event ); + virtual void timerEvent(QTimerEvent *event); + private slots: void _q_clipboardChanged(); void _q_deleteSelected(); @@ -350,61 +359,61 @@ private slots: inline int QLineControl::nextMaskBlank(int pos) { int c = findInMask(pos, true, false); - separator |= (c != pos); + m_separator |= (c != pos); return (c != -1 ? c : m_maxLength); } inline int QLineControl::prevMaskBlank(int pos) { int c = findInMask(pos, false, false); - separator |= (c != pos); + m_separator |= (c != pos); return (c != -1 ? c : 0); } inline bool QLineControl::isUndoAvailable() const { - return !readOnly && undoState; + return !m_readOnly && m_undoState; } inline bool QLineControl::isRedoAvailable() const { - return !readOnly && undoState < (int)history.size(); + return !m_readOnly && m_undoState < (int)m_history.size(); } inline void QLineControl::clearUndo() { - history.clear(); - modifiedState = undoState = 0; + m_history.clear(); + m_modifiedState = m_undoState = 0; } inline bool QLineControl::isModified() const { - return modifiedState != undoState; + return m_modifiedState != m_undoState; } inline void QLineControl::setModified(bool modified) { - modifiedState = modified ? -1 : undoState; + m_modifiedState = modified ? -1 : m_undoState; } inline bool QLineControl::allSelected() const { - return !m_text.isEmpty() && selstart == 0 && selend == (int)m_text.length(); + return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); } inline bool QLineControl::hasSelectedText() const { - return !m_text.isEmpty() && selend > selstart; + return !m_text.isEmpty() && m_selend > m_selstart; } inline int QLineControl::width() const { - return qRound(textLayout.lineAt(0).width()) + 1; + return qRound(m_textLayout.lineAt(0).width()) + 1; } inline int QLineControl::height() const { - return qRound(textLayout.lineAt(0).height()) + 1; + return qRound(m_textLayout.lineAt(0).height()) + 1; } inline int QLineControl::ascent() const @@ -415,32 +424,32 @@ inline int QLineControl::ascent() const inline QString QLineControl::selectedText() const { if (hasSelectedText()) - return m_text.mid(selstart, selend - selstart); + return m_text.mid(m_selstart, m_selend - m_selstart); return QString(); } inline QString QLineControl::textBeforeSelection() const { if (hasSelectedText()) - return m_text.left(selstart); + return m_text.left(m_selstart); return QString(); } inline QString QLineControl::textAfterSelection() const { if (hasSelectedText()) - return m_text.mid(selend); + return m_text.mid(m_selend); return QString(); } inline int QLineControl::selectionStart() const { - return hasSelectedText() ? selstart : -1; + return hasSelectedText() ? m_selstart : -1; } inline int QLineControl::selectionEnd() const { - return hasSelectedText() ? selend : -1; + return hasSelectedText() ? m_selend : -1; } inline int QLineControl::start() const @@ -455,17 +464,17 @@ inline int QLineControl::end() const inline void QLineControl::removeSelection() { - int priorState = undoState; + int priorState = m_undoState; removeSelectedText(); finishChange(priorState); } inline bool QLineControl::inSelection(int x) const { - if (selstart >= selend) + if (m_selstart >= m_selend) return false; int pos = xToPos(x, QTextLine::CursorOnCharacter); - return pos >= selstart && pos < selend; + return pos >= m_selstart && pos < m_selend; } inline int QLineControl::cursor() const @@ -492,18 +501,18 @@ inline void QLineControl::cursorForward(bool mark, int steps) { int c = m_cursor; if (steps > 0) { - while(steps--) - c = textLayout.nextCursorPosition(c); + while (steps--) + c = m_textLayout.nextCursorPosition(c); } else if (steps < 0) { while (steps++) - c = textLayout.previousCursorPosition(c); + c = m_textLayout.previousCursorPosition(c); } moveCursor(c, mark); } inline void QLineControl::cursorWordForward(bool mark) { - moveCursor(textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); + moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } inline void QLineControl::home(bool mark) @@ -518,12 +527,12 @@ inline void QLineControl::end(bool mark) inline void QLineControl::cursorWordBackward(bool mark) { - moveCursor(textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); + moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } inline qreal QLineControl::cursorToX(int cursor) const { - return textLayout.lineAt(0).cursorToX(cursor); + return m_textLayout.lineAt(0).cursorToX(cursor); } inline qreal QLineControl::cursorToX() const @@ -533,17 +542,17 @@ inline qreal QLineControl::cursorToX() const inline bool QLineControl::isReadOnly() const { - return readOnly; + return m_readOnly; } inline void QLineControl::setReadOnly(bool enable) { - readOnly = enable; + m_readOnly = enable; } inline QString QLineControl::text() const { - QString res = maskData ? stripString(m_text) : m_text; + QString res = m_maskData ? stripString(m_text) : m_text; return (res.isNull() ? QString::fromLatin1("") : res); } @@ -554,7 +563,7 @@ inline void QLineControl::setText(const QString &txt) inline QString QLineControl::displayText() const { - return textLayout.text(); + return m_textLayout.text(); } inline void QLineControl::deselect() @@ -565,7 +574,7 @@ inline void QLineControl::deselect() inline void QLineControl::selectAll() { - selstart = selend = m_cursor = 0; + m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); } @@ -595,7 +604,7 @@ inline void QLineControl::setEchoMode(uint mode) inline void QLineControl::setMaxLength(int maxLength) { - if (maskData) + if (m_maskData) return; m_maxLength = maxLength; setText(m_text); @@ -649,13 +658,13 @@ inline bool QLineControl::hasAcceptableInput() const inline QString QLineControl::inputMask() const { - return maskData ? m_inputMask + QLatin1Char(';') + blank : QString(); + return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); } inline void QLineControl::setInputMask(const QString &mask) { parseInputMask(mask); - if (maskData) + if (m_maskData) moveCursor(nextMaskBlank(0)); } @@ -663,18 +672,18 @@ inline void QLineControl::setInputMask(const QString &mask) #ifndef QT_NO_IM inline bool QLineControl::composeMode() const { - return !textLayout.preeditAreaText().isEmpty(); + return !m_textLayout.preeditAreaText().isEmpty(); } inline void QLineControl::setPreeditArea(int cursor, const QString &text) { - textLayout.setPreeditArea(cursor, text); + m_textLayout.setPreeditArea(cursor, text); } #endif inline QString QLineControl::preeditAreaText() const { - return textLayout.preeditAreaText(); + return m_textLayout.preeditAreaText(); } inline bool QLineControl::passwordEchoEditing() const @@ -708,7 +717,7 @@ inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction) inline void QLineControl::setFont(const QFont &font) { - textLayout.setFont(font); + m_textLayout.setFont(font); updateDisplayText(); } @@ -722,9 +731,9 @@ inline QString QLineControl::cancelText() const return m_cancelText; } -inline void QLineControl::setCancelText(QString s) +inline void QLineControl::setCancelText(const QString &text) { - m_cancelText = s; + m_cancelText = text; } QT_END_NAMESPACE diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 9252888..6deb196 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1727,11 +1727,11 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->control->emitingEditingFinished) { + if (!d->control->m_emitingEditingFinished) { if (hasAcceptableInput() || d->control->fixup()) { - d->control->emitingEditingFinished = true; + d->control->m_emitingEditingFinished = true; emit editingFinished(); - d->control->emitingEditingFinished = false; + d->control->m_emitingEditingFinished = false; } } #ifdef QT3_SUPPORT diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index c6d7496..230023d 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -135,7 +135,6 @@ public: void drag(); #endif - int leftTextMargin; int topTextMargin; int rightTextMargin; -- cgit v0.12 From 4a2e73a06eb9cba373f9662700883bd3bd7f5047 Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 14 Jul 2009 16:34:13 +0200 Subject: Rename the p_foo() functions in QLineControl to internalFoo(). --- src/gui/widgets/qlinecontrol.cpp | 39 ++++++++++++++++++++------------------- src/gui/widgets/qlinecontrol_p.h | 23 +++++++++++------------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 50ce6e6..ba85182 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -167,11 +167,11 @@ void QLineControl::backspace() // if yes delete both at once uc = m_text.at(m_cursor - 1); if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { - p_del(true); + internalDelete(true); --m_cursor; } } - p_del(true); + internalDelete(true); } finishChange(priorState); } @@ -193,7 +193,7 @@ void QLineControl::del() } else { int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; while (n--) - p_del(); + internalDelete(); } finishChange(priorState); } @@ -209,7 +209,7 @@ void QLineControl::insert(const QString &newText) { int priorState = m_undoState; removeSelectedText(); - p_insert(newText); + internalInsert(newText); finishChange(priorState); } @@ -343,7 +343,7 @@ bool QLineControl::fixup() // this function assumes that validate currently retu m_validator->fixup(textCopy); if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { if (textCopy != m_text || cursorCopy != m_cursor) - p_setText(textCopy, cursorCopy); + internalSetText(textCopy, cursorCopy); return true; } } @@ -376,7 +376,7 @@ void QLineControl::moveCursor(int pos, bool mark) m_selend = qMax(anchor, pos); updateDisplayText(); } else { - p_deselect(); + internalDeselect(); } m_cursor = pos; if (mark || m_selDirty) { @@ -531,7 +531,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); if (m_validInput) { if (m_text != textCopy) { - p_setText(textCopy, cursorCopy); + internalSetText(textCopy, cursorCopy); return true; } m_cursor = cursorCopy; @@ -541,7 +541,7 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) if (validateFromState >= 0 && wasValidInput && !m_validInput) { if (m_transactions.count()) return false; - p_undo(validateFromState); + internalUndo(validateFromState); m_history.resize(m_undoState); if (m_modifiedState > m_undoState) m_modifiedState = -1; @@ -571,9 +571,9 @@ bool QLineControl::finishChange(int validateFromState, bool update, bool edited) An internal function for setting the text of the line control. */ -void QLineControl::p_setText(const QString &txt, int pos, bool edited) +void QLineControl::internalSetText(const QString &txt, int pos, bool edited) { - p_deselect(); + internalDeselect(); emit resetInputContext(); QString oldText = m_text; if (m_maskData) { @@ -618,7 +618,7 @@ void QLineControl::addCommand(const Command &cmd) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_insert(const QString &s) +void QLineControl::internalInsert(const QString &s) { if (hasSelectedText()) addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); @@ -654,7 +654,7 @@ void QLineControl::p_insert(const QString &s) This function does not call finishChange(), and may leave the text in an invalid state. */ -void QLineControl::p_del(bool wasBackspace) +void QLineControl::internalDelete(bool wasBackspace) { if (m_cursor < (int) m_text.length()) { if (hasSelectedText()) @@ -706,7 +706,7 @@ void QLineControl::removeSelectedText() } if (m_cursor > m_selstart) m_cursor -= qMin(m_cursor, m_selend) - m_selstart; - p_deselect(); + internalDeselect(); m_textDirty = true; } } @@ -725,7 +725,7 @@ void QLineControl::parseInputMask(const QString &maskFields) delete [] m_maskData; m_maskData = 0; m_maxLength = 32767; - p_setText(QString()); + internalSetText(QString()); } return; } @@ -811,7 +811,7 @@ void QLineControl::parseInputMask(const QString &maskFields) } } } - p_setText(m_text); + internalSetText(m_text); } @@ -1077,11 +1077,11 @@ int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar se return -1; } -void QLineControl::p_undo(int until) +void QLineControl::internalUndo(int until) { if (!isUndoAvailable()) return; - p_deselect(); + internalDeselect(); while (m_undoState && m_undoState > until) { Command& cmd = m_history[--m_undoState]; switch (cmd.type) { @@ -1118,10 +1118,11 @@ void QLineControl::p_undo(int until) emitCursorPositionChanged(); } -void QLineControl::p_redo() { +void QLineControl::internalRedo() +{ if (!isRedoAvailable()) return; - p_deselect(); + internalDeselect(); while (m_undoState < (int)m_history.size()) { Command& cmd = m_history[m_undoState++]; switch (cmd.type) { diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 6029989..68ff66b 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -235,21 +235,21 @@ public: private: void init(const QString &txt); void removeSelectedText(); - void p_setText(const QString &txt, int pos = -1, bool edited = true); + void internalSetText(const QString &txt, int pos = -1, bool edited = true); void updateDisplayText(); - void p_insert(const QString &s); - void p_del(bool wasBackspace = false); - void p_remove(int pos); + void internalInsert(const QString &s); + void internalDelete(bool wasBackspace = false); + void internalRemove(int pos); - inline void p_deselect() + inline void internalDeselect() { m_selDirty |= (m_selend > m_selstart); m_selstart = m_selend = 0; } - void p_undo(int until = -1); - void p_redo(); + void internalUndo(int until = -1); + void internalRedo(); QString m_text; QPalette m_palette; @@ -297,7 +297,6 @@ private: QChar m_blank; MaskInputData *m_maskData; - // undo/redo handling enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; struct Command { @@ -558,7 +557,7 @@ inline QString QLineControl::text() const inline void QLineControl::setText(const QString &txt) { - p_setText(txt, -1, false); + internalSetText(txt, -1, false); } inline QString QLineControl::displayText() const @@ -568,7 +567,7 @@ inline QString QLineControl::displayText() const inline void QLineControl::deselect() { - p_deselect(); + internalDeselect(); finishChange(); } @@ -580,13 +579,13 @@ inline void QLineControl::selectAll() inline void QLineControl::undo() { - p_undo(); + internalUndo(); finishChange(-1, true); } inline void QLineControl::redo() { - p_redo(); + internalRedo(); finishChange(); } -- cgit v0.12 From 6263185ab45f533efea6c8f397092afb625cd929 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 16 Jul 2009 10:07:10 +1000 Subject: Remove emitingEditingFinished from QLineControl Doesn't seem to hurt anything, and it was ugly API. --- src/gui/widgets/qlinecontrol.cpp | 2 -- src/gui/widgets/qlinecontrol_p.h | 5 +---- src/gui/widgets/qlineedit.cpp | 18 ++++-------------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index ba85182..97f4a45 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1497,9 +1497,7 @@ void QLineControl::processKeyEvent(QKeyEvent* event) if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput() || fixup()) { emit accepted(); - m_emitingEditingFinished = true; emit editingFinished(); - m_emitingEditingFinished = false; } if (inlineCompletionAccepted) event->accept(); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 68ff66b..1e5c144 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -78,8 +78,7 @@ class Q_GUI_EXPORT QLineControl : public QObject public: QLineControl(const QString &txt = QString()) - : m_emitingEditingFinished(0), - m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), + : m_cursor(0), m_preeditCursor(0), m_layoutDirection(Qt::LeftToRight), m_hideCursor(false), m_separator(0), m_readOnly(0), m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), m_validInput(1), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), @@ -230,8 +229,6 @@ public: bool processEvent(QEvent *ev); - bool m_emitingEditingFinished; //Needed in QLineEdit FocusOut event - private: void init(const QString &txt); void removeSelectedText(); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 6deb196..e0f5bc9 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1393,15 +1393,10 @@ bool QLineEdit::event(QEvent * e) } else if (e->type() == QEvent::LeaveEditFocus) { d->setCursorVisible(false); d->control->setCursorBlinkPeriod(0); - if (!d->control->emitingEditingFinished) { - if (d->control->hasAcceptableInput() || d->control->fixup()) { - d->control->emitingEditingFinished = true; - emit editingFinished(); - d->control->emitingEditingFinished = false; - } - } + if (d->control->hasAcceptableInput() || d->control->fixup()) + emit editingFinished(); } - return; + return true; } #endif return QWidget::event(e); @@ -1727,13 +1722,8 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (!d->control->m_emitingEditingFinished) { - if (hasAcceptableInput() || d->control->fixup()) { - d->control->m_emitingEditingFinished = true; + if (hasAcceptableInput() || d->control->fixup()) emit editingFinished(); - d->control->m_emitingEditingFinished = false; - } - } #ifdef QT3_SUPPORT emit lostFocus(); #endif -- cgit v0.12 From 6eb1e397491c2d73aa40f3273cb20b371efad35a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 16 Jul 2009 10:14:47 +1000 Subject: Initial commit of QFxLineEdit QLineControl is integrated here, so no more need for qfxlineedit branch --- src/declarative/fx/fx.pri | 3 + src/declarative/fx/qfxlineedit.cpp | 543 +++++++++++++++++++++++++++++++++++++ src/declarative/fx/qfxlineedit.h | 193 +++++++++++++ src/declarative/fx/qfxlineedit_p.h | 106 ++++++++ 4 files changed, 845 insertions(+) create mode 100644 src/declarative/fx/qfxlineedit.cpp create mode 100644 src/declarative/fx/qfxlineedit.h create mode 100644 src/declarative/fx/qfxlineedit_p.h diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri index 0c26356..50bdc98 100644 --- a/src/declarative/fx/fx.pri +++ b/src/declarative/fx/fx.pri @@ -35,6 +35,8 @@ HEADERS += \ fx/qfxrepeater_p.h \ fx/qfxscalegrid.h \ fx/qfxshadowfilter.h \ + fx/qfxlineedit.h \ + fx/qfxlineedit_p.h \ fx/qfxtextedit.h \ fx/qfxtextedit_p.h \ fx/qfxtext.h \ @@ -70,6 +72,7 @@ SOURCES += \ fx/qfxrepeater.cpp \ fx/qfxscalegrid.cpp \ fx/qfxshadowfilter.cpp \ + fx/qfxlineedit.cpp \ fx/qfxtext.cpp \ fx/qfxtextedit.cpp \ fx/qfxtransform.cpp \ diff --git a/src/declarative/fx/qfxlineedit.cpp b/src/declarative/fx/qfxlineedit.cpp new file mode 100644 index 0000000..d23c325 --- /dev/null +++ b/src/declarative/fx/qfxlineedit.cpp @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfxlineedit.h" +#include "qfxlineedit_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE +QML_DEFINE_TYPE(QFxLineEdit,LineEdit); +QML_DEFINE_TYPE(QIntValidator,QIntValidator); + +QFxLineEdit::QFxLineEdit(QFxItem* parent) + : QFxPaintedItem(*(new QFxLineEditPrivate), parent) +{ + Q_D(QFxLineEdit); + d->init(); +} + +/* + \internal +*/ +QFxLineEdit::QFxLineEdit(QFxLineEditPrivate &dd, QFxItem* parent) + : QFxPaintedItem(dd, parent) +{ + Q_D(QFxLineEdit); + d->init(); +} + +QFxLineEdit::~QFxLineEdit() +{ +} + +QString QFxLineEdit::text() const +{ + Q_D(const QFxLineEdit); + return d->control->text(); +} + +void QFxLineEdit::setText(const QString &s) +{ + Q_D(QFxLineEdit); + if(s == text()) + return; + d->control->setText(s); + //emit textChanged(); +} + +QmlFont *QFxLineEdit::font() +{ + Q_D(QFxLineEdit); + return d->font; +} + +QColor QFxLineEdit::color() const +{ + Q_D(const QFxLineEdit); + return d->color; +} + +void QFxLineEdit::setColor(const QColor &c) +{ + Q_D(QFxLineEdit); + d->color = c; +} + +/* +QFxText::TextStyle QFxLineEdit::style() const +{ + Q_D(const QFxLineEdit); + return d->style; +} + +void QFxLineEdit::setStyle(QFxText::TextStyle style) +{ + Q_D(QFxLineEdit); + d->style = style; +} + +QColor QFxLineEdit::styleColor() const +{ + Q_D(const QFxLineEdit); + return d->styleColor; +} + +void QFxLineEdit::setStyleColor(const QColor &c) +{ + Q_D(QFxLineEdit); + d->styleColor = c; +} +*/ + +QFxText::HAlignment QFxLineEdit::hAlign() const +{ + Q_D(const QFxLineEdit); + return d->hAlign; +} + +void QFxLineEdit::setHAlign(QFxText::HAlignment align) +{ + Q_D(QFxLineEdit); + d->hAlign = align; +} + +QFxText::VAlignment QFxLineEdit::vAlign() const +{ + Q_D(const QFxLineEdit); + return d->vAlign; +} + +void QFxLineEdit::setVAlign(QFxText::VAlignment align) +{ + Q_D(QFxLineEdit); + d->vAlign = align; +} + +//### Should this also toggle cursor visibility? +bool QFxLineEdit::isReadOnly() const +{ + Q_D(const QFxLineEdit); + return d->control->isReadOnly(); +} + +void QFxLineEdit::setReadOnly(bool ro) +{ + Q_D(QFxLineEdit); + d->control->setReadOnly(ro); +} + +int QFxLineEdit::maxLength() const +{ + Q_D(const QFxLineEdit); + return d->control->maxLength(); +} + +void QFxLineEdit::setMaxLength(int ml) +{ + Q_D(QFxLineEdit); + d->control->setMaxLength(ml); +} + +int QFxLineEdit::cursorPosition() const +{ + Q_D(const QFxLineEdit); + return d->control->cursor(); +} +void QFxLineEdit::setCursorPosition(int cp) +{ + Q_D(QFxLineEdit); + d->control->moveCursor(cp); +} + +int QFxLineEdit::selectionLength() const +{ + Q_D(const QFxLineEdit); + return d->control->selectionEnd() - d->control->selectionStart(); +} + +void QFxLineEdit::setSelectionLength(int len) +{ + Q_D(QFxLineEdit); + d->control->setSelection(d->control->cursor(), len); +} + +QString QFxLineEdit::selectedText() const +{ + Q_D(const QFxLineEdit); + return d->control->selectedText(); +} + +bool QFxLineEdit::isAwesome() const +{ + Q_D(const QFxLineEdit); + return d->awesome; +} + +#include //Can be removed along wit the property +void QFxLineEdit::setAwesome(bool a) +{ + Q_D(QFxLineEdit); + d->awesome = a; + if(a){ + setColor(QColor(0,0,255)); + rainbowRedraw(); + } +} + +QObject* QFxLineEdit::validator() const +{ + Q_D(const QFxLineEdit); + //###const cast isn't good, but needed for property system? + //###same should be said about using QObject* as the property type + return const_cast(d->control->validator()); +} + +void QFxLineEdit::setValidator(QObject* v) +{ + Q_D(QFxLineEdit); + QValidator* valid = qobject_cast(v); + if(!valid) + return; + d->control->setValidator(valid); + if(!d->control->hasAcceptableInput()){ + d->oldValidity = false; + emit acceptableInputChanged(); + } +} + +QString QFxLineEdit::inputMask() const +{ + Q_D(const QFxLineEdit); + return d->control->inputMask(); +} + +void QFxLineEdit::setInputMask(const QString &im) +{ + Q_D(QFxLineEdit); + d->control->setInputMask(im); +} + +bool QFxLineEdit::hasAcceptableInput() const +{ + Q_D(const QFxLineEdit); + return d->control->hasAcceptableInput(); +} + +uint QFxLineEdit::echoMode() const +{ + Q_D(const QFxLineEdit); + return d->control->echoMode(); +} + +void QFxLineEdit::setEchoMode(uint echo) +{ + Q_D(QFxLineEdit); + d->control->setEchoMode(echo); +} + +QmlComponent* QFxLineEdit::cursorDelegate() const +{ + Q_D(const QFxLineEdit); + return d->cursorComponent; +} + +void QFxLineEdit::setCursorDelegate(QmlComponent* c) +{ + Q_D(QFxLineEdit); + if(d->cursorComponent) + delete d->cursorComponent; + d->cursorComponent = c; + d->startCreatingCursor(); +} + +void QFxLineEditPrivate::startCreatingCursor() +{ + Q_Q(QFxLineEdit); + if(!cursorComponent){ + q->disconnect(control, SIGNAL(cursorPositionChanged(int, int)), + q, SLOT(moveCursor())); + return; + } + q->connect(control, SIGNAL(cursorPositionChanged(int, int)), + q, SLOT(moveCursor())); + if(cursorComponent->isReady()){ + q->createCursor(); + }else if(cursorComponent->isLoading()){ + q->connect(cursorComponent, SIGNAL(statusChanged(int)), + q, SLOT(createCursor())); + }else{//isError + qWarning() << "You could really use the error checking for QFxLineEdit. We'll implement it soon."; + } +} + +void QFxLineEdit::createCursor() +{ + Q_D(QFxLineEdit); + //Handle isError too + if(!d->cursorComponent->isReady()) + return; + + if(d->cursorItem) + delete d->cursorItem; + d->cursorItem = qobject_cast(d->cursorComponent->create()); + if(!d->cursorItem){ + qWarning() << "You could really use the error reporting for QFxLineEdit. We'll implement it soon."; + return; + } + + d->cursorItem->setItemParent(this); + d->cursorItem->setX(d->control->cursorToX()); + d->cursorItem->setHeight(d->control->height()); +} + +void QFxLineEdit::moveCursor() +{ + Q_D(QFxLineEdit); + if(!d->cursorItem) + return; + d->cursorItem->setX(d->control->cursorToX() - d->hscroll); +} + +/* +int QFxLineEdit::scrollDuration() const +{ + Q_D(const QFxLineEdit); + return d->scrollDur; +} + +void QFxLineEdit::setScrollDuration(int s) +{ + Q_D(QFxLineEdit); + d->scrollDur = s; + //Need to update cur anims as well +} +*/ +int QFxLineEdit::xToPos(int x) +{ + Q_D(const QFxLineEdit); + return d->control->xToPos(x - d->hscroll); +} + +void QFxLineEdit::focusChanged(bool hasFocus) +{ + Q_D(QFxLineEdit); + if(d->focused && !hasFocus){ + d->focused = false; + d->control->setCursorBlinkPeriod(0); + updateAll();//Only need the cursor rect + }else{ + d->focused = hasFocus; + updateAll();//Only need the cursor rect + } +} + +void QFxLineEdit::keyPressEvent(QKeyEvent* ev) +{ + Q_D(QFxLineEdit); + d->control->processKeyEvent(ev); +} + +void QFxLineEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QFxLineEdit); + setFocus(true); + d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + d->focused = true; + d->control->processEvent(event); + //event->accept(); +} + +bool QFxLineEdit::event(QEvent* ev) +{ + Q_D(QFxLineEdit); + //Anything we don't deal with ourselves, pass to the control + switch(ev->type()){ + case QEvent::GraphicsSceneMousePress: + break; + default: + return d->control->processEvent(ev); + } + return false; +} + +void QFxLineEdit::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + if (newGeometry.width() != oldGeometry.width()) + updateSize(); + QFxPaintedItem::geometryChanged(newGeometry, oldGeometry); +} + +void QFxLineEdit::drawContents(QPainter *p, const QRect &r) +{ + Q_D(QFxLineEdit); + p->setRenderHint(QPainter::TextAntialiasing, true); + p->save(); + p->setPen(QPen(d->color)); + int flags = QLineControl::DrawText; + if(!isReadOnly() && d->focused && !d->cursorItem) + flags |= QLineControl::DrawCursor; + if (d->control->hasSelectedText()) + flags |= QLineControl::DrawSelections; + + //TODO: Clean up this cut'n'pasted section from QLineEdit + QRect lineRect(r); + + int cix = qRound(d->control->cursorToX()); + + // horizontal scrolling. d->hscroll is the left indent from the beginning + // of the text line to the left edge of lineRect. we update this value + // depending on the delta from the last paint event; in effect this means + // the below code handles all scrolling based on the textline (widthUsed, + // minLB, minRB), the line edit rect (lineRect) and the cursor position + // (cix). + QFontMetrics fm = QApplication::fontMetrics(); + int minLB = qMax(0, -fm.minLeftBearing()); + int minRB = qMax(0, -fm.minRightBearing()); + int widthUsed = d->control->width() + minRB; + if ((minLB + widthUsed) <= lineRect.width()) { + // text fits in lineRect; use hscroll for alignment + d->hscroll = 0; + d->hscroll -= minLB; + } else if (cix - d->hscroll >= lineRect.width()) { + // text doesn't fit, cursor is to the right of lineRect (scroll right) + d->hscroll = cix - lineRect.width() + 1; + } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { + // text doesn't fit, cursor is to the left of lineRect (scroll left) + d->hscroll = cix; + } + // the y offset is there to keep the baseline constant in case we have script changes in the text. + QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); + + if(d->hscroll != d->oldScroll) + moveCursor(); + + d->control->draw(p, topLeft, r, flags); + + d->oldScroll = d->hscroll; + p->restore(); +} + +void QFxLineEditPrivate::init() +{ + Q_Q(QFxLineEdit); + control->setCursorWidth(1); + control->setPasswordCharacter('*'); + control->setLayoutDirection(Qt::LeftToRight); + control->setSelection(0,0); + q->setSmooth(true); + q->setAcceptedMouseButtons(Qt::LeftButton); + q->setOptions(QFxLineEdit::AcceptsInputMethods | QFxLineEdit::SimpleItem + | QFxLineEdit::HasContents | QFxLineEdit::MouseEvents); + q->connect(control, SIGNAL(cursorPositionChanged(int,int)), + q, SIGNAL(cursorPositionChanged())); + q->connect(control, SIGNAL(selectionChanged()), + q, SLOT(selectionChanged())); + q->connect(control, SIGNAL(textChanged(const QString &)), + q, SLOT(q_textChanged())); + q->connect(control, SIGNAL(accepted()), + q, SIGNAL(accepted())); + q->connect(control, SIGNAL(updateNeeded(const QRect &)), + // q, SLOT(dirtyCache(const QRect &))); + q, SLOT(updateAll())); + q->connect(control, SIGNAL(cursorPositionChanged(int,int)), + q, SLOT(updateAll())); + q->connect(control, SIGNAL(selectionChanged()), + q, SLOT(updateAll())); + if(!font) + font = new QmlFont(); + q->updateSize(); + oldValidity = control->hasAcceptableInput(); + oldSelectLength = q->selectionLength(); +} + +void QFxLineEdit::selectionChanged() +{ + Q_D(QFxLineEdit); + emit selectedTextChanged(); + if(selectionLength() != d->oldSelectLength){ + d->oldSelectLength = selectionLength(); + emit selectionLengthChanged(); + } +} + +void QFxLineEdit::q_textChanged() +{ + Q_D(QFxLineEdit); + updateAll(); + emit textChanged(); + if(hasAcceptableInput() != d->oldValidity){ + d->oldValidity = hasAcceptableInput(); + emit acceptableInputChanged(); + } +} + +//### Please replace this function with proper updating +void QFxLineEdit::updateAll() +{ + clearCache(); + updateSize(); + update(); +} + +void QFxLineEdit::updateSize() +{ + Q_D(QFxLineEdit); + setImplicitHeight(d->control->height()); + //d->control->width() is max width, not current width + QFontMetrics fm = QFontMetrics(d->font->font()); + setImplicitWidth(fm.boundingRect(d->control->text()).width()+1); + setContentsSize(QSize(width(), height())); +} + +void QFxLineEdit::rainbowRedraw() +{ + Q_D(QFxLineEdit); + if(!d->awesome) + return; + setColor(QColor::fromHsv((d->color.hue() + 5)%360, d->color.saturation(), d->color.value())); + updateAll(); + QTimer::singleShot(50, this, SLOT(rainbowRedraw())); +} +QT_END_NAMESPACE + diff --git a/src/declarative/fx/qfxlineedit.h b/src/declarative/fx/qfxlineedit.h new file mode 100644 index 0000000..04dbee3 --- /dev/null +++ b/src/declarative/fx/qfxlineedit.h @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXLINEEDIT_H +#define QFXLINEEDIT_H + +#include "qfxtext.h" +#include "qfxpainteditem.h" +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QFxLineEditPrivate; +class QValidator; +class Q_DECLARATIVE_EXPORT QFxLineEdit : public QFxPaintedItem +{ + Q_OBJECT + + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QmlFont *font READ font) + Q_PROPERTY(QColor color READ color WRITE setColor) + /* + Q_PROPERTY(QFxText::TextStyle style READ style WRITE setStyle) + Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor) + Q_PROPERTY(QFxText::HAlignment hAlign READ hAlign WRITE setHAlign) + Q_PROPERTY(QFxText::VAlignment vAlign READ vAlign WRITE setVAlign) + */ + + Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly); + Q_PROPERTY(int maxLength READ maxLength WRITE setMaxLength); + Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged); + Q_PROPERTY(int selectionLength READ selectionLength WRITE setSelectionLength NOTIFY selectionLengthChanged); + Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged); + + Q_PROPERTY(QObject* validator READ validator WRITE setValidator); + Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask); + Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged); + Q_PROPERTY(uint echoMode READ echoMode WRITE setEchoMode); + + Q_PROPERTY(QmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate); + /* + Q_PROPERTY(int scrollDuration READ scrollDuration SET setScrollDuration NOTIFY scrollDurationChanged); + */ + //### Requested by Aaron K.(Remove before release?) + Q_PROPERTY(bool awesome READ isAwesome WRITE setAwesome); +public: + QFxLineEdit(QFxItem* parent=0); + ~QFxLineEdit(); + + QString text() const; + void setText(const QString &); + + QmlFont *font(); + + QColor color() const; + void setColor(const QColor &c); + + //### Should we have this function or x variants of properties? + Q_INVOKABLE int xToPos(int x); + + /* + QFxText::TextStyle style() const; + void setStyle(QFxText::TextStyle style); + + QColor styleColor() const; + void setStyleColor(const QColor &c); + */ + + QFxText::HAlignment hAlign() const; + void setHAlign(QFxText::HAlignment align); + + QFxText::VAlignment vAlign() const; + void setVAlign(QFxText::VAlignment align); + + bool isReadOnly() const; + void setReadOnly(bool); + + int maxLength() const; + void setMaxLength(int ml); + + int cursorPosition() const; + void setCursorPosition(int cp); + + int selectionLength() const; + void setSelectionLength(int len); + + QString selectedText() const; + + QObject * validator() const; + void setValidator(QObject* v); + + QString inputMask() const; + void setInputMask(const QString &im); + + uint echoMode() const; + void setEchoMode(uint echo); + + QmlComponent* cursorDelegate() const; + void setCursorDelegate(QmlComponent*); + + /* + int scrollDuration() const; + void setScrollDuration(int); + */ + + bool hasAcceptableInput() const; + + bool isAwesome() const; + void setAwesome(bool a); + + void drawContents(QPainter *p,const QRect &r); +Q_SIGNALS: + void textChanged(); + void cursorPositionChanged(); + void selectionLengthChanged(); + void selectedTextChanged(); + void accepted(); + void acceptableInputChanged(); + +protected: + QFxLineEdit(QFxLineEditPrivate &dd, QFxItem *parent); + virtual void geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry); + + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void keyPressEvent(QKeyEvent* ev); + bool event(QEvent *e); + + void focusChanged(bool hasFocus); + +private slots: + void updateSize(); + void q_textChanged(); + void selectionChanged(); + void updateAll(); + void createCursor(); + void moveCursor(); + void rainbowRedraw(); + +private: + Q_DECLARE_PRIVATE(QFxLineEdit); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QFxLineEdit) +QML_DECLARE_TYPE(QIntValidator) + +QT_END_HEADER +#endif // QFXLINEEDIT_H diff --git a/src/declarative/fx/qfxlineedit_p.h b/src/declarative/fx/qfxlineedit_p.h new file mode 100644 index 0000000..8ee5cca --- /dev/null +++ b/src/declarative/fx/qfxlineedit_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXLINEEDIT_P_H +#define QFXLINEEDIT_P_H + +#include "qfxlineedit.h" +#include "qml.h" +#include "qfxpainteditem_p.h" +#include "private/qlinecontrol_p.h" +#include +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +QT_BEGIN_NAMESPACE + +class QFxLineEditPrivate : public QFxPaintedItemPrivate +{ + Q_DECLARE_PUBLIC(QFxLineEdit); +public: + QFxLineEditPrivate() : control(new QLineControl(QString())), + font(0), color((QRgb)0), style(QFxText::Normal), + hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), + styleColor((QRgb)0), oldScroll(0), hscroll(0), + focused(false), awesome(false) + { + } + + ~QFxLineEditPrivate() + { + } + + void init(); + void startCreatingCursor(); + + QLineControl* control; + + QmlFont *font; + QColor color; + QFxText::TextStyle style; + QColor styleColor; + QFxText::HAlignment hAlign; + QFxText::VAlignment vAlign; + QPointer cursorComponent; + QPointer cursorItem; + + int oldSelectLength; + int oldHeight; + int oldWidth; + bool oldValidity; + int hscroll; + int oldScroll; + bool focused; + bool awesome; + +}; + +QT_END_NAMESPACE + +#endif + -- cgit v0.12 From 87c97621a1b6ff958d773559f5c39db010c9b073 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 16 Jul 2009 11:08:06 +1000 Subject: Fixes bugs with particles Fixed: Particle count changes had a noticable delay Fixed: Changing from zero to non-zero didn't work --- src/declarative/extra/qfxparticles.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/declarative/extra/qfxparticles.cpp b/src/declarative/extra/qfxparticles.cpp index 3130f06..e1c5bbe 100644 --- a/src/declarative/extra/qfxparticles.cpp +++ b/src/declarative/extra/qfxparticles.cpp @@ -473,8 +473,9 @@ void QFxParticlesPrivate::tick(int time) } } } - while(particles.count() < count && particles.count() < percCount && streamWidth--) - createParticle(time); + while(particles.count() < count && + (!stream || (particles.count() < percCount && streamWidth--))) + createParticle(time); } lastAdvTime = time; @@ -704,11 +705,13 @@ void QFxParticles::setCount(int cnt) { Q_D(QFxParticles); if (cnt != d->count) { - if (!d->count && d->clock.state() != QAbstractAnimation::Running) - d->clock.start(); // infinity?? + int oldCount = d->count; d->count = cnt; d->addParticleTime = 0; d->addParticleCount = d->particles.count(); + if (!oldCount && d->clock.state() != QAbstractAnimation::Running){ + d->clock.start(); // infinity?? + } update(); } } -- cgit v0.12 From befae051c1f80d66f459f375279f36047017c194 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 16 Jul 2009 11:09:49 +1000 Subject: Update SameGame particles Remove count:1 hack, make particles the right color. --- demos/declarative/samegame/content/BoomBlock.qml | 23 ++++++++++++++++++--- .../declarative/samegame/content/pics/blueStar.png | Bin 0 -> 2684 bytes .../samegame/content/pics/greenStar.png | Bin 0 -> 2675 bytes .../declarative/samegame/content/pics/redStar.png | Bin 0 -> 2676 bytes 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 demos/declarative/samegame/content/pics/blueStar.png create mode 100644 demos/declarative/samegame/content/pics/greenStar.png create mode 100644 demos/declarative/samegame/content/pics/redStar.png diff --git a/demos/declarative/samegame/content/BoomBlock.qml b/demos/declarative/samegame/content/BoomBlock.qml index 68e0e1a..0d05772 100644 --- a/demos/declarative/samegame/content/BoomBlock.qml +++ b/demos/declarative/samegame/content/BoomBlock.qml @@ -9,19 +9,36 @@ Item { id:block y: Follow { source: targetY; spring: 1.2; damping: 0.1 } Image { id: img - source: {if(type==0){"pics/redStone.png";}else if(type==1){"pics/blueStone.png";}else{"pics/greenStone.png";}} + source: { + if(type == 0){ + "pics/redStone.png"; + } else if(type == 1) { + "pics/blueStone.png"; + } else { + "pics/greenStone.png"; + } + } opacity: 0 opacity: Behavior { NumberAnimation { properties:"opacity"; duration: 200 } } anchors.fill: parent } Particles { id: particles width:1; height:1; anchors.centeredIn: parent; opacity: 0 - lifeSpan: 100000; source: "pics/star.png"; count:1; streamIn: false + lifeSpan: 1000000000; count:0; streamIn: false angle: 0; angleDeviation: 360; velocity: 100; velocityDeviation:30 + source: { + if(type == 0){ + "pics/redStar.png"; + } else if (type == 1) { + "pics/blueStar.png"; + } else { + "pics/greenStar.png"; + } + } } states: [ - State{ name: "SpawnState"; when: spawning == true && dying == false + State{ name: "AliveState"; when: spawning == true && dying == false SetProperties { target: img; opacity: 1 } }, State{ name: "DeathState"; when: dying == true diff --git a/demos/declarative/samegame/content/pics/blueStar.png b/demos/declarative/samegame/content/pics/blueStar.png new file mode 100644 index 0000000..822dc53 Binary files /dev/null and b/demos/declarative/samegame/content/pics/blueStar.png differ diff --git a/demos/declarative/samegame/content/pics/greenStar.png b/demos/declarative/samegame/content/pics/greenStar.png new file mode 100644 index 0000000..1abbcf0 Binary files /dev/null and b/demos/declarative/samegame/content/pics/greenStar.png differ diff --git a/demos/declarative/samegame/content/pics/redStar.png b/demos/declarative/samegame/content/pics/redStar.png new file mode 100644 index 0000000..b18834f Binary files /dev/null and b/demos/declarative/samegame/content/pics/redStar.png differ -- cgit v0.12 From 8e31e21bb4fc5630706cd21a4a74251c41563adb Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 16 Jul 2009 11:13:27 +1000 Subject: Do not segfault when index == -1. --- src/declarative/extra/qmlfolderlistmodel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/extra/qmlfolderlistmodel.cpp b/src/declarative/extra/qmlfolderlistmodel.cpp index acee5e1..4a71109 100644 --- a/src/declarative/extra/qmlfolderlistmodel.cpp +++ b/src/declarative/extra/qmlfolderlistmodel.cpp @@ -161,7 +161,9 @@ void QmlFolderListModel::classComplete() bool QmlFolderListModel::isFolder(int index) const { Q_D(const QmlFolderListModel); - return d->model.isDir(d->model.index(index, 0, d->folderIndex)); + if (index != -1) + return d->model.isDir(d->model.index(index, 0, d->folderIndex)); + return false; } void QmlFolderListModel::refresh() -- cgit v0.12 From 17f3d0d2389619109a80c54240903a1534a86358 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 16 Jul 2009 11:15:24 +1000 Subject: Add QmlPalette::darker() and QmlPalette::lighter(). --- src/declarative/util/qmlpalette.cpp | 10 ++++++++++ src/declarative/util/qmlpalette.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/declarative/util/qmlpalette.cpp b/src/declarative/util/qmlpalette.cpp index eda0ded..40cfa71 100644 --- a/src/declarative/util/qmlpalette.cpp +++ b/src/declarative/util/qmlpalette.cpp @@ -151,6 +151,16 @@ QColor QmlPalette::highlightedText() const return d->palette.color(d->group, QPalette::HighlightedText); } +QColor QmlPalette::lighter(const QColor& color) const +{ + return color.lighter(); +} + +QColor QmlPalette::darker(const QColor& color) const +{ + return color.darker(); +} + void QmlPalette::setColorGroup(QPalette::ColorGroup colorGroup) { Q_D(QmlPalette); diff --git a/src/declarative/util/qmlpalette.h b/src/declarative/util/qmlpalette.h index 1401ad1..7f26f9a 100644 --- a/src/declarative/util/qmlpalette.h +++ b/src/declarative/util/qmlpalette.h @@ -101,6 +101,9 @@ public: bool virtual eventFilter(QObject *watched, QEvent *event); bool virtual event(QEvent *event); + Q_INVOKABLE QColor lighter(const QColor&) const; + Q_INVOKABLE QColor darker(const QColor&) const; + Q_SIGNALS: void paletteChanged(); }; -- cgit v0.12 From effc7e9c521b230f5a7dccfa195011ec0c791bd2 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 16 Jul 2009 11:17:29 +1000 Subject: Improve loader example Use system palette and icons. --- examples/declarative/loader/Browser.qml | 62 +++++++++++++++++------- examples/declarative/loader/images/fileopen.png | Bin 0 -> 953 bytes examples/declarative/loader/images/up.png | Bin 0 -> 662 bytes examples/declarative/loader/loader.qrc | 2 + examples/declarative/loader/main.cpp | 2 + 5 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 examples/declarative/loader/images/fileopen.png create mode 100644 examples/declarative/loader/images/up.png diff --git a/examples/declarative/loader/Browser.qml b/examples/declarative/loader/Browser.qml index 280273b..aec373b 100644 --- a/examples/declarative/loader/Browser.qml +++ b/examples/declarative/loader/Browser.qml @@ -2,6 +2,7 @@ Rect { id: Root width: parent.width height: parent.height + color: activePalette.base FolderListModel { id: folders nameFilters: [ "*.qml" ] @@ -13,12 +14,26 @@ Rect { Rect { id: Wrapper width: Root.width - height: NameText.height + height: 32 + color: activePalette.base + Rect { + id: Highlight; visible: false + anchors.fill: parent + gradient: Gradient { + GradientStop { id: t1; position: 0.0; color: activePalette.highlight } + GradientStop { id: t2; position: 1.0; color: activePalette.lighter(activePalette.highlight) } + } + } + Item { + width: 32; height: 32 + Image { source: "images/fileopen.png"; anchors.centeredIn: parent; visible: folders.isFolder(index)} + } Text { id: NameText - text: fileName - font.bold: true - font.size: 12 + anchors.fill: parent; vAlign: "AlignVCenter" + text: fileName; anchors.leftMargin: 32 + font.size: 10 + color: activePalette.windowText } MouseRegion { id: Mouse @@ -35,7 +50,8 @@ Rect { State { name: "pressed" when: Mouse.pressed - SetProperties { target: Wrapper; color: "#bbbbbb" } + SetProperties { target: Highlight; visible: true } + SetProperties { target: NameText; color: activePalette.highlightedText } } ] } @@ -48,19 +64,8 @@ Rect { } } - Rect { - id: UpButton - width: 30 - height: UpText.height - color: "grey" - MouseRegion { anchors.fill: parent; onClicked: folders.folder = up(folders.folder) } - Text { id: UpText; text: "Up" } - } - - Text { anchors.left: UpButton.right; text: folders.folder } - ListView { - anchors.top: UpButton.bottom + anchors.top: TitleBar.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom @@ -68,4 +73,27 @@ Rect { delegate: FolderDelegate clip: true } + + Rect { + id: TitleBar + width: parent.width + height: 32 + color: activePalette.button; pen.color: activePalette.mid + + Rect { + id: UpButton + width: 30 + height: TitleBar.height + pen.color: activePalette.mid; color: "transparent" + MouseRegion { anchors.fill: parent; onClicked: folders.folder = up(folders.folder) } + Image { anchors.centeredIn: parent; source: "images/up.png" } + } + + Text { + anchors.left: UpButton.right; anchors.right: parent.right; height: parent.height + anchors.leftMargin: 4; anchors.rightMargin: 4 + text: folders.folder; color: activePalette.buttonText + elide: "ElideLeft"; hAlign: "AlignRight"; vAlign: "AlignVCenter" + } + } } diff --git a/examples/declarative/loader/images/fileopen.png b/examples/declarative/loader/images/fileopen.png new file mode 100644 index 0000000..4aaf149 Binary files /dev/null and b/examples/declarative/loader/images/fileopen.png differ diff --git a/examples/declarative/loader/images/up.png b/examples/declarative/loader/images/up.png new file mode 100644 index 0000000..b05f802 Binary files /dev/null and b/examples/declarative/loader/images/up.png differ diff --git a/examples/declarative/loader/loader.qrc b/examples/declarative/loader/loader.qrc index 1f0925f..bdbcd5c 100644 --- a/examples/declarative/loader/loader.qrc +++ b/examples/declarative/loader/loader.qrc @@ -2,5 +2,7 @@ loader.qml Browser.qml + images/fileopen.png + images/up.png diff --git a/examples/declarative/loader/main.cpp b/examples/declarative/loader/main.cpp index 23125ce..aa86f8f 100644 --- a/examples/declarative/loader/main.cpp +++ b/examples/declarative/loader/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "qmlpalette.h" QFxView *canvas = 0; @@ -61,6 +62,7 @@ int main(int argc, char *argv[]) canvas = new QFxView; QmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("qmlLauncher", launcher); + ctxt->setContextProperty("activePalette", new QmlPalette); canvas->setUrl(QUrl("qrc:/loader.qml")); canvas->execute(); canvas->show(); -- cgit v0.12 From 84637da766fe1e3a4b4240601a6002f94f1b07c9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 11:45:33 +1000 Subject: Fix crash on object destruction --- src/declarative/qml/qmlbasicscript.cpp | 9 ++++++--- src/declarative/qml/qmlcontext.cpp | 11 +++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 478491f..d6d6625 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -181,6 +181,9 @@ static QVariant toObjectOrVariant(const QVariant &v) static QVariant fetch_value(QObject *o, int idx, int type) { + if (!o) + return QVariant(); + switch(type) { case QVariant::String: { @@ -823,7 +826,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c QObject *obj = contextPrivate->defaultObjects.at(0); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (instr.constant.notify != 0) + if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); state = Reset; @@ -835,7 +838,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c QObject *obj = contextPrivate->defaultObjects.at(1); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (instr.constant.notify != 0) + if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); state = Reset; @@ -848,7 +851,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c QObject *obj = qvariant_cast(o); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); - if (instr.constant.notify != 0) + if (obj && instr.constant.notify != 0) enginePrivate->capturedProperties << QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify); state = Reset; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index b605869..440f4b8 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -86,8 +86,15 @@ void QmlContextPrivate::destroyed(QObject *obj) } } - for (int ii = 0; ii < notifies.count(); ++ii) { - QMetaObject::activate(q, notifies[ii] + notifyIndex, 0); + // There is no need to emit these notifications if our parent is in the + // process of being deleted (which is *probably* why obj has been destroyed + // anyway), as we're about to get deleted which will invalidate all the + // expressions that could depend on us + QObject *parent = q->parent(); + if (!parent || !QObjectPrivate::get(parent)->wasDeleted) { + for (int ii = 0; ii < notifies.count(); ++ii) { + QMetaObject::activate(q, notifies[ii] + notifyIndex, 0); + } } } -- cgit v0.12 From 0dfe225df98a1b204e4a90bb8b1b66aefbe74d81 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 12:35:08 +1000 Subject: Add FINAL attribute to Q_PROPERTY() This will be used by the declarative module to optimize property bindings. --- doc/src/properties.qdoc | 5 +++++ doc/src/snippets/code/doc_src_properties.qdoc | 3 ++- src/corelib/kernel/qmetaobject.cpp | 17 ++++++++++++++++- src/corelib/kernel/qmetaobject.h | 1 + src/tools/moc/generator.cpp | 5 ++++- src/tools/moc/moc.cpp | 3 +++ src/tools/moc/moc.h | 3 ++- tests/auto/qmetaobject/tst_qmetaobject.cpp | 17 +++++++++++++++++ 8 files changed, 50 insertions(+), 4 deletions(-) diff --git a/doc/src/properties.qdoc b/doc/src/properties.qdoc index 1aa41a9..b7f773a 100644 --- a/doc/src/properties.qdoc +++ b/doc/src/properties.qdoc @@ -128,6 +128,11 @@ constant value may be different for different instances of the object. A constant property cannot have a \c WRITE method or a \c NOTIFY signal. + \o The presence of the \c FINAL attribute indicates that the property + will not be overridden by a derived class. This can be used for performance + optimizations in some cases, but is not enforced by moc. Care must be taken + never to override a \c FINAL property. + \endlist The \c READ, \c WRITE, and \c RESET functions can be inherited. diff --git a/doc/src/snippets/code/doc_src_properties.qdoc b/doc/src/snippets/code/doc_src_properties.qdoc index 64e5377..3c9109f 100644 --- a/doc/src/snippets/code/doc_src_properties.qdoc +++ b/doc/src/snippets/code/doc_src_properties.qdoc @@ -8,7 +8,8 @@ Q_PROPERTY(type name [SCRIPTABLE bool] [STORED bool] [USER bool] - [CONSTANT]) + [CONSTANT] + [FINAL]) //! [0] diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index a06e974..a4c4ba2 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -161,7 +161,8 @@ enum PropertyFlags { ResolveUser = 0x00200000, Notify = 0x00400000, Dynamic = 0x00800000, - Constant = 0x00000400 + Constant = 0x00000400, + Final = 0x00000800 }; enum MethodFlags { @@ -2507,6 +2508,20 @@ bool QMetaProperty::isConstant() const } /*! + Returns true if the property is final; otherwise returns false. + + A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute + is set. +*/ +bool QMetaProperty::isFinal() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Final; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index adc31d1..9f36106 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -191,6 +191,7 @@ public: bool isUser(const QObject *obj = 0) const; bool isDynamic() const; bool isConstant() const; + bool isFinal() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 328717c..990d20a 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -68,7 +68,8 @@ enum PropertyFlags { ResolveUser = 0x00200000, Notify = 0x00400000, Dynamic = 0x00800000, - Constant = 0x00000400 + Constant = 0x00000400, + Final = 0x00000800 }; enum MethodFlags { AccessPrivate = 0x00, @@ -604,6 +605,8 @@ void Generator::generateProperties() if (p.constant) flags |= Constant; + if (p.final) + flags |= Final; fprintf(out, " %4d, %4d, ", strreg(p.name), diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7ad67c9..d2f40ee 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -917,6 +917,9 @@ void Moc::parseProperty(ClassDef *def) if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; + } else if(l[0] == 'F' && l == "FINAL") { + propDef.final = true; + continue; } QByteArray v, v2; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index f459032..d68907f 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -115,10 +115,11 @@ struct FunctionDef struct PropertyDef { - PropertyDef():notifyId(-1), constant(false), gspec(ValueSpec){} + PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; int notifyId; bool constant; + bool final; enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; Specification gspec; bool stdCppSet() const { diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index f4cff2b..ac2858c 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -109,6 +109,7 @@ class tst_QMetaObject : public QObject Q_PROPERTY(MyStruct value7 READ value7 WRITE setVal7 NOTIFY value7Changed) Q_PROPERTY(int value8 READ value8 NOTIFY value8Changed) Q_PROPERTY(int value9 READ value9 CONSTANT) + Q_PROPERTY(int value10 READ value10 FINAL) public: enum EnumType { EnumType1 }; @@ -140,6 +141,8 @@ public: int value9() const { return 1; } + int value10() const { return 1; } + QList value4; QVariantList value5; @@ -163,6 +166,7 @@ private slots: void checkScope(); void propertyNotify(); void propertyConstant(); + void propertyFinal(); void stdSet(); void classInfo(); @@ -802,6 +806,19 @@ void tst_QMetaObject::propertyConstant() QVERIFY(prop.isConstant()); } +void tst_QMetaObject::propertyFinal() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value10")); + QVERIFY(prop.isValid()); + QVERIFY(prop.isFinal()); + + prop = mo->property(mo->indexOfProperty("value9")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.isFinal()); +} + class ClassInfoTestObjectA : public QObject { Q_OBJECT -- cgit v0.12 From 58e541dd805046b912bb82468d3251b0d5141710 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 13:03:39 +1000 Subject: Remove some unreliable binary expression support --- src/declarative/qml/qmlbasicscript.cpp | 64 +--------------------------------- 1 file changed, 1 insertion(+), 63 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index d6d6625..cc8d528 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -64,12 +64,7 @@ struct ScriptInstruction { FetchD0Constant, // constant FetchD1Constant, // constant - - Add, // NA - Subtract, // NA - Multiply, // NA Equals, // NA - And, // NA Int, // integer Bool, // boolean @@ -448,15 +443,6 @@ void QmlBasicScript::dump() qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t" << QByteArray(data + instr.fetch.idx); break; - case ScriptInstruction::Add: - qWarning().nospace() << "ADD"; - break; - case ScriptInstruction::Subtract: - qWarning().nospace() << "SUBTRACT"; - break; - case ScriptInstruction::Multiply: - qWarning().nospace() << "MULTIPLY"; - break; case ScriptInstruction::Equals: qWarning().nospace() << "EQUALS"; break; @@ -682,11 +668,7 @@ bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node) AST::BinaryExpression *expr = static_cast(node); - if (expr->op == QSOperator::Add || - expr->op == QSOperator::Sub || - expr->op == QSOperator::Equal || - expr->op == QSOperator::And || - expr->op == QSOperator::Mul) + if (expr->op == QSOperator::Equal) return true; } return false; @@ -703,21 +685,9 @@ bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node) ScriptInstruction instr; switch (expr->op) { - case QSOperator::Add: - instr.type = ScriptInstruction::Add; - break; - case QSOperator::Sub: - instr.type = ScriptInstruction::Subtract; - break; case QSOperator::Equal: instr.type = ScriptInstruction::Equals; break; - case QSOperator::And: - instr.type = ScriptInstruction::And; - break; - case QSOperator::Mul: - instr.type = ScriptInstruction::Multiply; - break; default: return false; } @@ -916,30 +886,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c case ScriptInstruction::Bool: stack.push(QVariant(instr.boolean.value)); break; - case ScriptInstruction::Add: - { - QVariant rhs = stack.pop(); - QVariant lhs = stack.pop(); - - stack.push(rhs.toDouble() + lhs.toDouble()); - } - break; - case ScriptInstruction::Subtract: - { - QVariant rhs = stack.pop(); - QVariant lhs = stack.pop(); - - stack.push(lhs.toDouble() - rhs.toDouble()); - } - break; - case ScriptInstruction::Multiply: - { - QVariant rhs = stack.pop(); - QVariant lhs = stack.pop(); - - stack.push(rhs.toDouble() * lhs.toDouble()); - } - break; case ScriptInstruction::Equals: { QVariant rhs = stack.pop(); @@ -948,14 +894,6 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c stack.push(rhs == lhs); } break; - case ScriptInstruction::And: - { - QVariant rhs = stack.pop(); - QVariant lhs = stack.pop(); - - stack.push(rhs.toBool() && lhs.toBool()); - } - break; default: break; } -- cgit v0.12 From 1734f968773fade53a73c8ce04ea86de8df0b875 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 13:51:21 +1000 Subject: Indenting fix --- src/declarative/qml/qmlengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index acbeb26..44b857c 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -1,4 +1,4 @@ - /**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) -- cgit v0.12 From 1962eaef07cb3adf73e7d8815ac470f62003a192 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 15:02:25 +1000 Subject: Small cleanups --- src/declarative/qml/qmlbasicscript.cpp | 6 +- src/declarative/qml/qmlbasicscript_p.h | 2 +- src/declarative/qml/qmlcompileddata.cpp | 5 - src/declarative/qml/qmlcompiler.cpp | 277 ++++++++++++--------- src/declarative/qml/qmlcompiler_p.h | 24 +- src/declarative/qml/qmldom.cpp | 2 +- src/declarative/qml/qmldom.h | 2 +- src/declarative/qml/qmlparser.cpp | 5 +- src/declarative/qml/qmlparser_p.h | 7 +- .../qmlparser/listAssignment.1.errors.txt | 2 +- .../qmlparser/listAssignment.2.errors.txt | 2 +- .../qmlparser/listAssignment.3.errors.txt | 2 +- 12 files changed, 179 insertions(+), 157 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index cc8d528..40ffffe 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -289,7 +289,7 @@ struct QmlBasicScriptCompiler QmlParser::Object *context; QmlParser::Object *component; - QHash > ids; + QHash ids; bool compile(QmlJS::AST::Node *); @@ -577,10 +577,10 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node, if (ids.contains(name)) { instr.type = ScriptInstruction::LoadIdObject; - instr.fetch.idx = ids.value(name).second; + instr.fetch.idx = ids.value(name)->idIndex; if (type) - *type = ids.value(name).first; + *type = ids.value(name); } else { int d0Idx = context->metaObject()->indexOfProperty(name.toUtf8().constData()); diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 0c69397..77d59eb 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -85,7 +85,7 @@ public: QmlParser::Object *context; QmlParser::Property *property; QmlParser::Variant expression; - QHash > ids; + QHash ids; }; bool compile(const Expression &); diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index 0834794..0563891 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE -DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); - int QmlCompiledData::pack(const char *data, size_t size) { const char *p = packData.constData(); @@ -193,9 +191,6 @@ const QMetaObject *QmlCompiledData::TypeReference::metaObject() const void QmlCompiledData::dumpInstructions() { - if (!compilerDump()) - return; - if (!name.isEmpty()) qWarning() << name; qWarning() << "Index\tLine\tOperation\t\tData1\tData2\t\tComments"; diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index ed9df03..182495a 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -68,23 +68,43 @@ QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); + using namespace QmlParser; +/*! + Instantiate a new QmlCompiler. +*/ QmlCompiler::QmlCompiler() : output(0) { } +/*! + Returns true if the last call to compile() caused errors. + + \sa errors() +*/ bool QmlCompiler::isError() const { return !exceptions.isEmpty(); } +/*! + Return the list of errors from the last call to compile(), or an empty list + if there were no errors. +*/ QList QmlCompiler::errors() const { return exceptions; } +/*! + Returns true if \a val is a legal object id, false otherwise. + + Legal ids must start with a letter or underscore, and contain only + letters, numbers and underscores. +*/ bool QmlCompiler::isValidId(const QString &val) { if (val.isEmpty()) @@ -122,7 +142,20 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) 'A' <= name.at(2) && 'Z' >= name.at(2); } -#define COMPILE_EXCEPTION2(token, desc) \ +/*! + Inserts an error into the QmlCompiler error list, and returns false + (failure). + + \a token is used to source the error line and column, and \a desc is the + error itself. \a desc can be an expression that can be piped into QDebug. + + For example: + + \code + COMPILE_EXCEPTION(property, "Error for property" << property->name); + \endcode +*/ +#define COMPILE_EXCEPTION(token, desc) \ { \ QString exceptionDescription; \ QmlError error; \ @@ -136,33 +169,28 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) return false; \ } -#define COMPILE_EXCEPTION(desc) \ - { \ - QString exceptionDescription; \ - QmlError error; \ - error.setUrl(output->url); \ - error.setLine(obj->location.start.line); \ - error.setColumn(obj->location.start.column); \ - QDebug d(&exceptionDescription); \ - d << desc; \ - error.setDescription(exceptionDescription.trimmed()); \ - exceptions << error; \ - return false; \ - } - +/*! + Returns false if \a is false, otherwise does nothing. +*/ #define COMPILE_CHECK(a) \ { \ if (!a) return false; \ } -// Compile a simple assignment of v to prop into instr +/*! + Returns true if literal \a v can be assigned to property \a prop, otherwise + false. + + This test corresponds to action taken by genLiteralAssignment(). Any change + made here, must have a corresponding action in genLiteralAssigment(). +*/ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *v) { QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION2(v, "Invalid property assignment: read-only property"); + COMPILE_EXCEPTION(v, "Invalid property assignment: read-only property"); if (prop.isEnumType()) { int value; @@ -171,7 +199,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, } else value = prop.enumerator().keyToValue(string.toLatin1().constData()); if (value == -1) - COMPILE_EXCEPTION2(v, "Invalid property assignment: unknown enumeration"); + COMPILE_EXCEPTION(v, "Invalid property assignment: unknown enumeration"); return true; } int type = prop.userType(); @@ -179,61 +207,61 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, case -1: break; case QVariant::String: - if (!v->value.isString()) COMPILE_EXCEPTION2(v, "Invalid property assignment: string expected"); + if (!v->value.isString()) COMPILE_EXCEPTION(v, "Invalid property assignment: string expected"); break; case QVariant::Url: - if (!v->value.isString()) COMPILE_EXCEPTION2(v, "Invalid property assignment: url expected"); + if (!v->value.isString()) COMPILE_EXCEPTION(v, "Invalid property assignment: url expected"); break; case QVariant::UInt: { bool ok; string.toUInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: unsigned int expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: unsigned int expected"); } break; case QVariant::Int: { bool ok; string.toInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: int expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: int expected"); } break; case QMetaType::Float: { bool ok; string.toFloat(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: float expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: float expected"); } break; case QVariant::Double: { bool ok; string.toDouble(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: double expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: double expected"); } break; case QVariant::Color: { QColor c = QmlStringConverters::colorFromString(string); - if (!c.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: color expected"); + if (!c.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: color expected"); } break; case QVariant::Date: { QDate d = QDate::fromString(string, Qt::ISODate); - if (!d.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: date expected"); + if (!d.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: date expected"); } break; case QVariant::Time: { QTime time = QTime::fromString(string, Qt::ISODate); - if (!time.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: time expected"); + if (!time.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: time expected"); } break; case QVariant::DateTime: { QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); - if (!dateTime.isValid()) COMPILE_EXCEPTION2(v, "Invalid property assignment: datetime expected"); + if (!dateTime.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: datetime expected"); } break; case QVariant::Point: @@ -241,7 +269,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QPointF point = QmlStringConverters::pointFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: point expected"); + if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: point expected"); } break; case QVariant::Size: @@ -249,7 +277,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QSizeF size = QmlStringConverters::sizeFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: size expected"); + if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: size expected"); } break; case QVariant::Rect: @@ -257,12 +285,12 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QRectF rect = QmlStringConverters::rectFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION2(v, "Invalid property assignment: rect expected"); + if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: rect expected"); } break; case QVariant::Bool: { - if (!v->value.isBoolean()) COMPILE_EXCEPTION2(v, "Invalid property assignment: boolean expected"); + if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, "Invalid property assignment: boolean expected"); } break; default: @@ -273,13 +301,19 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(t); if (!converter) - COMPILE_EXCEPTION2(v, "Invalid property assignment: unknown type" << prop.type()); + COMPILE_EXCEPTION(v, "Invalid property assignment: unknown type" << prop.type()); } break; } return true; } +/*! + Generate a store instruction for assigning literal \a v to property \a prop. + + Any literal assignment that is approved in testLiteralAssignment() must have + a corresponding action in this method. +*/ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *v) { @@ -469,17 +503,31 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, output->bytecode << instr; } -void QmlCompiler::reset(QmlCompiledData *cc) +/*! + Resets data by clearing the lists that the QmlCompiler modifies. +*/ +void QmlCompiler::reset(QmlCompiledData *data) { - cc->types.clear(); - cc->primitives.clear(); - cc->floatData.clear(); - cc->intData.clear(); - cc->customTypeData.clear(); - cc->datas.clear(); - cc->bytecode.clear(); + data->types.clear(); + data->primitives.clear(); + data->floatData.clear(); + data->intData.clear(); + data->customTypeData.clear(); + data->datas.clear(); + data->bytecode.clear(); } +/*! + Compile \a unit, and store the output in \a out. \a engine is the QmlEngine + with which the QmlCompiledData will be associated. + + Returns true on success, false on failure. On failure, the compile errors + are available from errors(). + + If the environment variant QML_COMPILER_DUMP is set + (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr + on a successful compiler. +*/ bool QmlCompiler::compile(QmlEngine *engine, QmlCompositeTypeData *unit, QmlCompiledData *out) @@ -526,11 +574,14 @@ bool QmlCompiler::compile(QmlEngine *engine, compileTree(root); if (!isError()) { - out->dumpInstructions(); + if (compilerDump()) + out->dumpInstructions(); } else { reset(out); } + compileState = ComponentCompileState(); + savedCompileStates.clear(); output = 0; return !isError(); @@ -622,7 +673,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) bool canDefer = false; if (isCustomParser) { - if (testProperty(prop, obj)) { + if (doesPropertyExist(prop, obj)) { int ids = compileState.ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); canDefer = ids == compileState.ids.count(); @@ -651,7 +702,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) bool canDefer = false; if (isCustomParser) { - if (testProperty(prop, obj)) { + if (doesPropertyExist(prop, obj)) { int ids = compileState.ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); canDefer = ids == compileState.ids.count(); @@ -676,7 +727,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) QmlCustomParser *cp = output->types.at(obj->type).type->customParser(); obj->custom = cp->compile(customProps, &ok); if(!ok) - COMPILE_EXCEPTION("Failure compiling custom type"); + COMPILE_EXCEPTION(obj, "Failure compiling custom type"); } return true; @@ -876,36 +927,36 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, Property *idProp = 0; if (obj->properties.count() > 1 || (obj->properties.count() == 1 && obj->properties.begin().key() != "id")) - COMPILE_EXCEPTION("Invalid component specification"); + COMPILE_EXCEPTION(obj, "Invalid component specification"); if (obj->properties.count()) idProp = *obj->properties.begin(); if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive()))) - COMPILE_EXCEPTION("Invalid component id specification"); + COMPILE_EXCEPTION(obj, "Invalid component id specification"); if (idProp) { QString idVal = idProp->values.first()->primitive().toUtf8(); if (compileState.ids.contains(idVal)) - COMPILE_EXCEPTION("id is not unique"); + COMPILE_EXCEPTION(obj, "id is not unique"); addId(idVal, obj); - obj->id = idVal.toUtf8(); + obj->id = idVal; } // Check the Component tree is well formed if (obj->defaultProperty && (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 || (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) - COMPILE_EXCEPTION("Invalid component body specification"); + COMPILE_EXCEPTION(obj, "Invalid component body specification"); Object *root = 0; if (obj->defaultProperty && obj->defaultProperty->values.count()) root = obj->defaultProperty->values.first()->object; if (!root) - COMPILE_EXCEPTION("Cannot create empty component specification"); + COMPILE_EXCEPTION(obj, "Cannot create empty component specification"); // Build the component tree COMPILE_CHECK(buildComponentFromRoot(root, ctxt)); @@ -989,7 +1040,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, Q_ASSERT(obj->metaObject()); if (prop->isEmpty()) - COMPILE_EXCEPTION2(prop, "Empty property assignment"); + COMPILE_EXCEPTION(prop, "Empty property assignment"); QByteArray name = prop->name; Q_ASSERT(name.startsWith("on")); @@ -1008,7 +1059,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, } else { if (prop->value || prop->values.count() > 1) - COMPILE_EXCEPTION("Incorrectly specified signal"); + COMPILE_EXCEPTION(prop, "Incorrectly specified signal"); prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1025,9 +1076,11 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, } -// Returns true if prop exists on obj, false otherwise -bool QmlCompiler::testProperty(QmlParser::Property *prop, - QmlParser::Object *obj) +/*! + Returns true if (value) property \a prop exists on obj, false otherwise. +*/ +bool QmlCompiler::doesPropertyExist(QmlParser::Property *prop, + QmlParser::Object *obj) { if(isAttachedPropertyName(prop->name) || prop->name == "id") return true; @@ -1051,7 +1104,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, const BindingContext &ctxt) { if (prop->isEmpty()) - COMPILE_EXCEPTION2(prop, "Empty property assignment"); + COMPILE_EXCEPTION(prop, "Empty property assignment"); const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); @@ -1063,16 +1116,16 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, // Attached properties cannot be used on sub-objects. Sub-objects // always exist in a binding sub-context, which is what we test // for here. - COMPILE_EXCEPTION2(prop, "Attached properties cannot be used here"); + COMPILE_EXCEPTION(prop, "Attached properties cannot be used here"); } QmlType *type = QmlMetaType::qmlType(prop->name); if (!type || !type->attachedPropertiesType()) - COMPILE_EXCEPTION2(prop, "Non-existant attached object"); + COMPILE_EXCEPTION(prop, "Non-existant attached object"); if (!prop->value) - COMPILE_EXCEPTION2(prop, "Invalid attached object assignment"); + COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); prop->value->metatype = type->attachedPropertiesType(); } else { @@ -1125,9 +1178,9 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } else if (prop->index == -1) { if (prop->isDefault) { - COMPILE_EXCEPTION2(prop->values.first(), "Cannot assign to non-existant default property"); + COMPILE_EXCEPTION(prop->values.first(), "Cannot assign to non-existant default property"); } else { - COMPILE_EXCEPTION2(prop, "Cannot assign to non-existant property" << prop->name); + COMPILE_EXCEPTION(prop, "Cannot assign to non-existant property" << prop->name); } } else if (prop->value) { @@ -1280,17 +1333,17 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, if (prop->value || prop->values.count() > 1 || prop->values.at(0)->object) - COMPILE_EXCEPTION2(prop, "Invalid use of id property"); + COMPILE_EXCEPTION(prop, "Invalid use of id property"); QString val = prop->values.at(0)->primitive(); if (!isValidId(val)) - COMPILE_EXCEPTION2(prop, val << "is not a valid object id"); + COMPILE_EXCEPTION(prop, val << "is not a valid object id"); if (compileState.ids.contains(val)) - COMPILE_EXCEPTION2(prop, "id is not unique"); + COMPILE_EXCEPTION(prop, "id is not unique"); - obj->id = val.toUtf8(); + obj->id = val; prop->values.at(0)->type = Value::Id; @@ -1301,18 +1354,16 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, void QmlCompiler::addId(const QString &id, QmlParser::Object *obj) { - IdReference reference; - reference.id = id; - reference.object = obj; - reference.idx = compileState.ids.count(); - compileState.ids.insert(id, reference); + Q_ASSERT(!compileState.ids.contains(id)); + Q_ASSERT(obj->id == id); + obj->idIndex = compileState.ids.count(); + compileState.ids.insert(id, obj); } void QmlCompiler::addBindingReference(const BindingReference &ref) { - int id = compileState.bindings.count(); - compileState.bindings << ref; - compileState.bindingMap.insert(ref.value, id); + Q_ASSERT(ref.value && !compileState.bindings.contains(ref.value)); + compileState.bindings.insert(ref.value, ref); } void QmlCompiler::saveComponentState() @@ -1368,7 +1419,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, // Load the nested property's meta type prop->value->metatype = QmlMetaType::metaObjectForType(prop->type); if (!prop->value->metatype) - COMPILE_EXCEPTION2(prop, "Cannot nest non-QObject property" << prop->name); + COMPILE_EXCEPTION(prop, "Cannot nest non-QObject property" << prop->name); obj->addGroupedProperty(prop); @@ -1408,12 +1459,12 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION("Cannot assign object to list"); + COMPILE_EXCEPTION(v, "Cannot assign object to list"); } } } else { - COMPILE_EXCEPTION("Cannot assign primitives to lists"); + COMPILE_EXCEPTION(v, "Cannot assign primitives to lists"); } } @@ -1432,19 +1483,19 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION("Cannot assign object to list"); + COMPILE_EXCEPTION(v, "Cannot assign object to list"); } } } else if (v->value.isScript()) { if (assignedBinding) - COMPILE_EXCEPTION("Can only assign one binding to lists"); + COMPILE_EXCEPTION(v, "Can only assign one binding to lists"); assignedBinding = true; COMPILE_CHECK(buildBinding(v, prop, ctxt)); v->type = Value::PropertyBinding; } else { - COMPILE_EXCEPTION("Cannot assign primitives to lists"); + COMPILE_EXCEPTION(v, "Cannot assign primitives to lists"); } } @@ -1570,7 +1621,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, v->type = Value::ValueSource; } else { - COMPILE_EXCEPTION2(v->object, "Cannot assign object to property"); + COMPILE_EXCEPTION(v->object, "Cannot assign object to property"); } } @@ -1615,12 +1666,12 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) if (prop.isDefaultProperty) { if (seenDefaultProperty) - COMPILE_EXCEPTION("Duplicate default property"); + COMPILE_EXCEPTION(obj, "Duplicate default property"); seenDefaultProperty = true; } if (propNames.contains(prop.name)) - COMPILE_EXCEPTION("Duplicate property name"); + COMPILE_EXCEPTION(obj, "Duplicate property name"); propNames.insert(prop.name); } @@ -1628,13 +1679,13 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { QByteArray name = obj->dynamicSignals.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION("Duplicate signal name"); + COMPILE_EXCEPTION(obj, "Duplicate signal name"); methodNames.insert(name); } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { QByteArray name = obj->dynamicSlots.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION("Duplicate method name"); + COMPILE_EXCEPTION(obj, "Duplicate method name"); methodNames.insert(name); } @@ -1656,7 +1707,7 @@ bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj) property = obj->getProperty(p.name); if (property->value) - COMPILE_EXCEPTION2(property, "Invalid property nesting"); + COMPILE_EXCEPTION(property, "Invalid property nesting"); for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) { Value *v = p.defaultValue->values.at(ii); @@ -1797,14 +1848,8 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) obj->metadata = builder.toRelocatableData(); builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata); - // ### Remove me - obj->extObjectData = &obj->extObject; - - if (mode == IgnoreAliases && hasAlias) { - AliasReference alias; - alias.object = obj; - compileState.aliases << alias; - } + if (mode == IgnoreAliases && hasAlias) + compileState.aliasingObjects << obj; obj->synthdata = dynamicData; @@ -1836,34 +1881,34 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, const Object::DynamicProperty &prop) { if (!prop.defaultValue) - COMPILE_EXCEPTION("No property alias location"); + COMPILE_EXCEPTION(obj, "No property alias location"); if (prop.defaultValue->values.count() != 1 || prop.defaultValue->values.at(0)->object || !prop.defaultValue->values.at(0)->value.isScript()) - COMPILE_EXCEPTION2(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); QmlJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST(); if (!node) - COMPILE_EXCEPTION("No property alias location"); // ### Can this happen? + COMPILE_EXCEPTION(obj, "No property alias location"); // ### Can this happen? QStringList alias = astNodeToStringList(node); if (alias.count() != 2) - COMPILE_EXCEPTION2(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); if (!compileState.ids.contains(alias.at(0))) - COMPILE_EXCEPTION2(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); - const IdReference &id = compileState.ids[alias.at(0)]; - int propIdx = id.object->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + Object *idObject = compileState.ids[alias.at(0)]; + int propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); if (-1 == propIdx) - COMPILE_EXCEPTION2(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); - QMetaProperty aliasProperty = id.object->metaObject()->property(propIdx); + QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); - data.append((const char *)&id.idx, sizeof(id.idx)); + data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); builder.addSignal(prop.name + "Changed()"); @@ -1881,13 +1926,12 @@ bool QmlCompiler::buildBinding(QmlParser::Value *value, QMetaProperty mp = prop->parent->metaObject()->property(prop->index); if (!mp.isWritable() && !QmlMetaType::isList(prop->type)) - COMPILE_EXCEPTION2(prop, "Invalid property assignment: read-only property"); + COMPILE_EXCEPTION(prop, "Invalid property assignment: read-only property"); BindingReference reference; reference.expression = value->value; reference.property = prop; reference.value = value; - reference.instructionIdx = output->bytecode.count(); reference.bindingContext = ctxt; addBindingReference(reference); @@ -1898,10 +1942,9 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, QmlParser::Property *prop, QmlParser::Object *obj) { - Q_ASSERT(compileState.bindingMap.contains(binding)); + Q_ASSERT(compileState.bindings.contains(binding)); - const BindingReference &ref = - compileState.bindings.at(compileState.bindingMap.value(binding)); + const BindingReference &ref = compileState.bindings.value(binding); QMetaProperty mp = obj->metaObject()->property(prop->index); @@ -1927,21 +1970,17 @@ bool QmlCompiler::completeComponentBuild() { saveComponentState(); - for (int ii = 0; ii < compileState.aliases.count(); ++ii) { - const AliasReference &alias = compileState.aliases.at(ii); - COMPILE_CHECK(buildDynamicMeta(alias.object, ResolveAliases)); + for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) { + Object *aliasObject = compileState.aliasingObjects.at(ii); + COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases)); } - QmlBasicScript::Expression expr; expr.component = compileState.root; - foreach (const IdReference &id, compileState.ids) { - expr.ids.insert(id.id, qMakePair(id.object, id.idx)); - } - - for (int ii = 0; ii < compileState.bindings.count(); ++ii) { - BindingReference &binding = compileState.bindings[ii]; + expr.ids = compileState.ids; + for (QHash::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) { + BindingReference &binding = *iter; QmlBasicScript bs; expr.context = binding.bindingContext.object; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index e09665f..86e6590 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -137,7 +137,7 @@ public: static bool isSignalPropertyName(const QByteArray &); private: - void reset(QmlCompiledData *); + static void reset(QmlCompiledData *); struct BindingContext { BindingContext() @@ -185,7 +185,7 @@ private: QmlParser::Object *obj, QmlParser::Value *value, const BindingContext &ctxt); - bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj); + bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj); bool testLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *value); enum DynamicMetaMode { IgnoreAliases, ResolveAliases }; @@ -224,25 +224,13 @@ private: QStringList deferredProperties(QmlParser::Object *); - struct IdReference { - QString id; - QmlParser::Object *object; - int instructionIdx; - int idx; - }; void addId(const QString &, QmlParser::Object *); - struct AliasReference { - QmlParser::Object *object; - int instructionIdx; - }; - struct BindingReference { QmlParser::Variant expression; QmlParser::Property *property; QmlParser::Value *value; QByteArray compiledData; - int instructionIdx; BindingContext bindingContext; }; void addBindingReference(const BindingReference &); @@ -252,13 +240,13 @@ private: ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {} - QHash ids; + QHash ids; int parserStatusCount; int savedObjects; int pushedProperties; - QList bindings; - QHash bindingMap; - QList aliases; + + QHash bindings; + QList aliasingObjects; QmlParser::Object *root; }; ComponentCompileState compileState; diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index e3cb563..505d872 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -769,7 +769,7 @@ QByteArray QmlDomObject::objectType() const Text { id: MyText } \endqml */ -QByteArray QmlDomObject::objectId() const +QString QmlDomObject::objectId() const { if (d->object) return d->object->id; else return QByteArray(); diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h index 456202a..339570b 100644 --- a/src/declarative/qml/qmldom.h +++ b/src/declarative/qml/qmldom.h @@ -150,7 +150,7 @@ public: bool isValid() const; QByteArray objectType() const; - QByteArray objectId() const; + QString objectId() const; void setObjectId(const QByteArray &); diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8ee3b4e..e2d334e 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -62,8 +62,7 @@ QT_BEGIN_NAMESPACE using namespace QmlParser; QmlParser::Object::Object() -: type(-1), metatype(0), extObjectData(0), defaultProperty(0), - parserStatusCast(-1) +: type(-1), idIndex(-1), metatype(0), defaultProperty(0), parserStatusCast(-1) { } @@ -84,7 +83,7 @@ QmlParser::Object::~Object() const QMetaObject *Object::metaObject() const { - if (extObjectData && metatype) + if (!metadata.isEmpty() && metatype) return &extObject; else return metatype; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index d96a43e..84e6dd4 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -117,8 +117,10 @@ namespace QmlParser QUrl url; // The name of this type QByteArray typeName; - // The id assigned to the object (if any). - QByteArray id; + // The id assigned to the object (if any). Set by the QmlCompiler + QString id; + // The id index assigned to the object (if any). Set by the QmlCompiler + int idIndex; // Custom parsed data QByteArray custom; // Returns the metaobject for this type, or 0 if not available. @@ -129,7 +131,6 @@ namespace QmlParser const QMetaObject *metatype; // The synthesized metaobject, if QML added signals or properties to // this type. Otherwise null - QMetaObject *extObjectData; QAbstractDynamicMetaObject extObject; QByteArray metadata; // Generated by compiler QByteArray synthdata; // Generated by compiler diff --git a/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt index 44a275b..8bcd71e 100644 --- a/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt +++ b/tests/auto/declarative/qmlparser/listAssignment.1.errors.txt @@ -1 +1 @@ -1:1:Cannot assign primitives to lists +2:24:Cannot assign primitives to lists diff --git a/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt index 572d662..312ba8a 100644 --- a/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt +++ b/tests/auto/declarative/qmlparser/listAssignment.2.errors.txt @@ -1,2 +1,2 @@ -1:1:Cannot assign primitives to lists +2:15:Cannot assign primitives to lists diff --git a/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt b/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt index ab6fec8..c52debf 100644 --- a/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt +++ b/tests/auto/declarative/qmlparser/listAssignment.3.errors.txt @@ -1 +1 @@ -1:1:Can only assign one binding to lists +3:15:Can only assign one binding to lists -- cgit v0.12 From d03ef52960576837f4454da0b3bf196d92ee558c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 15:08:59 +1000 Subject: Types should not modify the active context --- src/declarative/extra/qmlbehaviour.cpp | 26 +------------------------- src/declarative/extra/qmlbehaviour.h | 8 +------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/src/declarative/extra/qmlbehaviour.cpp b/src/declarative/extra/qmlbehaviour.cpp index 4165d56..c7ab1da 100644 --- a/src/declarative/extra/qmlbehaviour.cpp +++ b/src/declarative/extra/qmlbehaviour.cpp @@ -75,15 +75,12 @@ private: class QmlBehaviourPrivate : public QObjectPrivate { public: - QmlBehaviourPrivate() - : context(0), valueData(0), operations(this) {} + QmlBehaviourPrivate() : operations(this) {} QmlMetaProperty property; QVariant currentValue; QVariant fromValue; QVariant toValue; - QmlContext *context; - QmlBehaviourData *valueData; class AnimationList : public QmlConcreteList { public: @@ -128,7 +125,6 @@ QmlBehaviour::QmlBehaviour(QObject *parent) : QmlPropertyValueSource(*(new QmlBehaviourPrivate), parent) { Q_D(QmlBehaviour); - d->valueData = new QmlBehaviourData(this); d->group = new QParallelAnimationGroup(this); } @@ -200,10 +196,6 @@ void QmlBehaviour::propertyValueChanged() //### does this clean up everything needed? d->group->stop(); - d->valueData->e = newValue; - d->valueData->s = d->currentValue; - emit d->valueData->valuesChanged(); - QmlStateOperation::ActionList actions; Action action; action.property = d->property; @@ -238,22 +230,6 @@ void QmlBehaviour::setTarget(const QmlMetaProperty &property) } } -void QmlBehaviour::classBegin() -{ - Q_D(QmlBehaviour); - if (!d->context) { - d->context = new QmlContext(qmlContext(this), this); - d->context->addDefaultObject(d->valueData); - } - d->context->activate(); -} - -void QmlBehaviour::classComplete() -{ - Q_D(QmlBehaviour); - d->context->deactivate(); -} - QT_END_NAMESPACE #include "qmlbehaviour.moc" diff --git a/src/declarative/extra/qmlbehaviour.h b/src/declarative/extra/qmlbehaviour.h index 1b5f524..99fc779 100644 --- a/src/declarative/extra/qmlbehaviour.h +++ b/src/declarative/extra/qmlbehaviour.h @@ -54,12 +54,10 @@ QT_MODULE(Declarative) class QmlAbstractAnimation; class QmlBehaviourPrivate; -class Q_DECLARATIVE_EXPORT QmlBehaviour : public QmlPropertyValueSource, - public QmlParserStatus +class Q_DECLARATIVE_EXPORT QmlBehaviour : public QmlPropertyValueSource { Q_OBJECT Q_DECLARE_PRIVATE(QmlBehaviour) - Q_INTERFACES(QmlParserStatus) Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue) Q_PROPERTY(QVariant to READ toValue WRITE setToValue) @@ -80,10 +78,6 @@ public: static bool _ignore; -protected: - virtual void classBegin(); - virtual void classComplete(); - private Q_SLOTS: void propertyValueChanged(); }; -- cgit v0.12 From a5e11573712fcf1c95696bed4ce4bfd04bc17e01 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 15:28:48 +1000 Subject: Remove unnecessary global context management stuff --- src/declarative/qml/qmlcomponent.cpp | 10 +-- src/declarative/qml/qmlcontext.cpp | 50 ------------ src/declarative/qml/qmlcontext.h | 5 -- src/declarative/qml/qmlengine.cpp | 130 ++------------------------------ src/declarative/qml/qmlengine.h | 3 - src/declarative/qml/qmlengine_p.h | 3 - src/declarative/qml/qmlmetaproperty.cpp | 3 +- src/declarative/qml/qmlvme.cpp | 22 ++---- 8 files changed, 16 insertions(+), 210 deletions(-) diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 0e68f8a..c7d45fd 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -405,9 +405,10 @@ QString QmlComponent::errorsString() const QString ret; if(!isError()) return ret; - foreach(const QmlError &e, d->errors){ - ret += e.url().toString() + ":" + QString::number(e.line()) + " " - + e.description() + "\n"; + foreach(const QmlError &e, d->errors) { + ret += e.url().toString() + QLatin1String(":") + + QString::number(e.line()) + QLatin1String(" ") + + e.description() + QLatin1String("\n"); } return ret; } @@ -532,7 +533,6 @@ QObject *QmlComponent::beginCreate(QmlContext *context) static_cast(ctxt->d_ptr)->startLine = d->cc->bytecode.at(d->start - 1).line; static_cast(ctxt->d_ptr)->endLine = d->cc->bytecode.at(d->start - 1).createComponent.endLine; } - ctxt->activate(); QmlVME vme; QObject *rv = vme.run(ctxt, d->cc, d->start, d->count); @@ -540,8 +540,6 @@ QObject *QmlComponent::beginCreate(QmlContext *context) if (vme.isError()) d->errors = vme.errors(); - ctxt->deactivate(); - QmlEnginePrivate *ep = d->engine->d_func(); if (ep->rootComponent == this) { ep->rootComponent = 0; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 440f4b8..5bc70bc 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -405,56 +405,6 @@ void QmlContext::setContextProperty(const QString &name, QObject *value) } /*! - Activate this bind context. - - \sa QmlEngine::activeContext() QmlContext::activeContext() -*/ -void QmlContext::activate() -{ - QmlEnginePrivate *ep = engine()->d_func(); - ep->activeContexts.push(this); - ep->setCurrentBindContext(this); - ep->contextActivated(this); -} - -/*! - Deactivate this bind context. The previously active bind context will - become active, or, if there was no previously active bind context, no - context will be active. - - \sa QmlEngine::activeContext() QmlContext::activeContext() -*/ -void QmlContext::deactivate() -{ - QmlEnginePrivate *ep = engine()->d_func(); - Q_ASSERT(ep->activeContexts.top() == this); - ep->activeContexts.pop(); - if (ep->activeContexts.isEmpty()) - ep->setCurrentBindContext(0); - else - ep->setCurrentBindContext(ep->activeContexts.top()); - ep->contextDeactivated(this); -} - -/*! - Returns the currently active context, or 0 if no context is active. - - This method is thread-safe. The active context is maintained individually - for each thread. This method is equivalent to - \code - QmlEngine::activeEngine()->activeContext() - \endcode -*/ -QmlContext *QmlContext::activeContext() -{ - QmlEngine *engine = QmlEngine::activeEngine(); - if (engine) - return engine->activeContext(); - else - return 0; -} - -/*! Resolves the URL \a src relative to the URL of the containing component. If \a src is absolute, it is simply returned. If there is no containing component, diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 77f6634..877ff0f 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -73,11 +73,6 @@ public: void setContextProperty(const QString &, QObject *); void setContextProperty(const QString &, const QVariant &); - void activate(); - void deactivate(); - - static QmlContext *activeContext(); - QUrl resolvedUrl(const QUrl &); void setBaseUrl(const QUrl &); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 44b857c..d724c49 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -90,49 +90,6 @@ struct StaticQtMetaObject : public QObject { return &static_cast (0)->staticQtMetaObject; } }; - -struct QmlEngineStack { - QmlEngineStack(); - - QStack mainThreadEngines; - QThread *mainThread; - - QThreadStorage *> storage; - - QStack *engines(); -}; - -Q_GLOBAL_STATIC(QmlEngineStack, engineStack); - -QmlEngineStack::QmlEngineStack() -: mainThread(0) -{ -} - -QStack *QmlEngineStack::engines() -{ - if (mainThread== 0) { - if (!QCoreApplication::instance()) - return 0; - mainThread = QCoreApplication::instance()->thread(); - } - - // Note: This is very slightly faster than just using the thread storage - // for everything. - QStack *engines = 0; - if (QThread::currentThread() == mainThread) { - engines = &mainThreadEngines; - } else { - engines = storage.localData(); - if (!engines) { - engines = new QStack; - storage.setLocalData(engines); - } - } - return engines; -} - - QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) : rootContext(0), currentBindContext(0), currentExpression(0), q(e), isDebugging(false), rootComponent(0), networkAccessManager(0), typeManager(e), @@ -295,30 +252,6 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, return QScriptValue(); } -void QmlEnginePrivate::contextActivated(QmlContext *) -{ - Q_Q(QmlEngine); - QmlEngineStack *stack = engineStack(); - if (!stack) - return; - QStack *engines = stack->engines(); - if (engines) - engines->push(q); -} - -void QmlEnginePrivate::contextDeactivated(QmlContext *) -{ - QmlEngineStack *stack = engineStack(); - if (!stack) - return; - QStack *engines = stack->engines(); - if (engines) { - Q_ASSERT(engines->top() == q_func()); - engines->pop(); - } -} - - //////////////////////////////////////////////////////////////////// bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj) @@ -469,40 +402,12 @@ QmlContext *QmlEngine::rootContext() } /*! - Returns this engine's active context, or 0 if no context is active on this - engine. - - Contexts are activated and deactivated by calling QmlContext::activate() and - QmlContext::deactivate() respectively. - - Context activation holds no special semantic, other than it allows types - instantiated by QML to access "their" context without having it passed as - a parameter in their constructor, as shown below. - \code - class MyClass : ... { - ... - MyClass() { - qWarning() << "I was instantiated in this context:" - << QmlContext::activeContext(); - } - }; - \endcode -*/ -QmlContext *QmlEngine::activeContext() -{ - Q_D(QmlEngine); - if (d->currentBindContext) - return d->currentBindContext; - else - return 0; -} - -/*! - Sets the common QNetworkAccessManager, \a network, used by all QML elements instantiated - by this engine. + Sets the common QNetworkAccessManager, \a network, used by all QML elements + instantiated by this engine. - Any previously set manager is deleted and \a network is owned by the QmlEngine. This - method should only be called before any QmlComponents are instantiated. + Any previously set manager is deleted and \a network is owned by the + QmlEngine. This method should only be called before any QmlComponents are + instantiated. */ void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network) { @@ -669,30 +574,6 @@ QScriptEngine *QmlEngine::scriptEngine() } /*! - Returns the currently active QmlEngine. - - The active engine is the engine associated with the last activated - QmlContext. This method is thread-safe - the "active" engine is maintained - independently for each thread. -*/ -QmlEngine *QmlEngine::activeEngine() -{ - QmlEngineStack *stack = engineStack(); - if (!stack) return 0; - - QStack *engines = stack->engines(); - if (!engines) { - qWarning("QmlEngine::activeEngine() cannot be called before the construction of QCoreApplication"); - return 0; - } - - if (engines->isEmpty()) - return 0; - else - return engines->top(); -} - -/*! Creates a QScriptValue allowing you to use \a object in QML script. \a engine is the QmlEngine it is to be created in. @@ -777,7 +658,6 @@ QScriptValue QmlEngine::createComponent(QScriptContext *ctxt, QScriptEngine *eng QUrl url = QUrl(activeEngine->d_func()->currentExpression->context() ->resolvedUrl(ctxt->argument(0).toString())); if(!url.isValid()){ - qDebug() << "Error A:" << url << activeEngine->activeContext() << QmlEngine::activeEngine() << activeEngine; url = QUrl(ctxt->argument(0).toString()); } c = new QmlComponent(activeEngine, url, activeEngine); diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index 6a418b5..38bf423 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -70,10 +70,7 @@ public: QmlEngine(QObject *p = 0); virtual ~QmlEngine(); - static QmlEngine *activeEngine(); - QmlContext *rootContext(); - QmlContext *activeContext(); void clearComponentCache(); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index e0824cc..f459dc5 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -93,9 +93,6 @@ public: void init(); - void contextActivated(QmlContext *); - void contextDeactivated(QmlContext *); - bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *); bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 6602021..dea3467 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -643,8 +643,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) if (!expr.isEmpty()) { // XXX scope - (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object, - coreIdx, object); + (void *)new QmlBoundSignal(qmlContext(object), expr, object, coreIdx, object); } } diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 3b33686..f468cd0 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -116,7 +116,6 @@ void QmlVME::runDeferred(QObject *object) return; QmlContext *ctxt = data->context; - ctxt->activate(); QmlCompiledData *comp = data->deferredComponent; int start = data->deferredIdx + 1; int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount; @@ -124,17 +123,10 @@ void QmlVME::runDeferred(QObject *object) stack.push(object); run(stack, ctxt, comp, start, count); - ctxt->deactivate(); } QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData *comp, int start, int count) { - // XXX - All instances of QmlContext::activeContext() here should be - // replaced with the use of ctxt. However, this cannot be done until - // behaviours stop modifying the active context and expecting the - // instantiation to notice. Instead, QmlParserStatus::beginClass() should - // be able to return a QmlContext that is used for expressions and - // sub-instances on that type. Q_ASSERT(comp); Q_ASSERT(ctxt); const QList &types = comp->types; @@ -169,7 +161,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::CreateObject: { - QObject *o = types.at(instr.create.type).createInstance(QmlContext::activeContext()); + QObject *o = types.at(instr.create.type).createInstance(ctxt); if (!o) { if(types.at(instr.create.type).component) vmeErrors << types.at(instr.create.type).component->errors(); @@ -203,8 +195,6 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::SetId: { QObject *target = stack.top(); - QmlContext *ctxt = - QmlContext::activeContext(); ctxt->setContextProperty(primitives.at(instr.setId.value), target); } break; @@ -213,7 +203,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::SetDefault: { QObject *target = stack.top(); - QmlContext::activeContext()->addDefaultObject(target); + ctxt->addDefaultObject(target); } break; @@ -515,9 +505,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData target->metaObject()->method(instr.storeSignal.signalIndex); if (signal.parameterTypes().isEmpty()) { - (void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); + (void *)new QmlBoundSignal(ctxt, primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); } else { - (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target, true), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); + (void *)new QmlBoundSignalProxy(new QmlContext(ctxt, target, true), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); } } break; @@ -550,7 +540,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlMetaProperty mp(target, instr.assignBinding.property, (QmlMetaProperty::PropertyCategory)instr.assignBinding.category); - QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, QmlContext::activeContext(), 0); + QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); bindValues.append(bind); QmlBindableValuePrivate *p = static_cast(QObjectPrivate::get(bind)); @@ -570,7 +560,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlMetaProperty mp(target, instr.assignBinding.property, (QmlMetaProperty::PropertyCategory)instr.assignBinding.category); - QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, QmlContext::activeContext()); + QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, ctxt); bindValues.append(bind); QmlBindableValuePrivate *p = static_cast(QObjectPrivate::get(bind)); -- cgit v0.12 From d080c1c2ded0d59974f86f9f3dac91b099bda0a9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 15:49:44 +1000 Subject: Move the QML rewriting stuff into a central location --- src/declarative/qml/qml.pri | 2 + src/declarative/qml/qmlexpression.cpp | 98 +------------------- src/declarative/qml/qmlrewrite.cpp | 157 ++++++++++++++++++++++++++++++++ src/declarative/qml/qmlrewrite_p.h | 103 +++++++++++++++++++++ src/declarative/qml/qmlscriptparser.cpp | 46 +--------- 5 files changed, 266 insertions(+), 140 deletions(-) create mode 100644 src/declarative/qml/qmlrewrite.cpp create mode 100644 src/declarative/qml/qmlrewrite_p.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 7f1c3f7..0b91ed3 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -26,6 +26,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlerror.cpp \ qml/qmlscriptparser.cpp \ qml/qmlenginedebug.cpp \ + qml/qmlrewrite.cpp \ qml/qmlbasicscript.cpp HEADERS += qml/qmlparser_p.h \ @@ -67,6 +68,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlscriptparser_p.h \ qml/qmlbasicscript_p.h \ qml/qmlenginedebug_p.h \ + qml/qmlrewrite_p.h \ qml/qpodvector_p.h # for qtscript debugger diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 4fe7d0c..2aa1a8a 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -43,10 +43,7 @@ #include "qmlexpression_p.h" #include "qmlengine_p.h" #include "qmlcontext_p.h" -#include "rewriter/textwriter_p.h" -#include "parser/qmljslexer_p.h" -#include "parser/qmljsparser_p.h" -#include "parser/qmljsnodepool_p.h" +#include "qmlrewrite_p.h" #include "QtCore/qdebug.h" Q_DECLARE_METATYPE(QList); @@ -55,97 +52,6 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER) -namespace { - -using namespace QmlJS; - -class RewriteBinding: protected AST::Visitor -{ - unsigned _position; - TextWriter *_writer; - -public: - QString operator()(const QString &code) - { - Engine engine; - NodePool pool(QString(), &engine); - Lexer lexer(&engine); - Parser parser(&engine); - lexer.setCode(code, 0); - parser.parseStatement(); - return rewrite(code, 0, parser.statement()); - } - -protected: - using AST::Visitor::visit; - - void accept(AST::Node *node) - { - AST::Node::acceptChild(node, this); - } - - QString rewrite(QString code, unsigned position, AST::Statement *node) - { - TextWriter w; - _writer = &w; - _position = position; - - accept(node); - - unsigned startOfStatement = node->firstSourceLocation().begin() - _position; - unsigned endOfStatement = node->lastSourceLocation().end() - _position; - - _writer->replace(startOfStatement, 0, QLatin1String("function() {\n")); - _writer->replace(endOfStatement, 0, QLatin1String("\n}")); - - w.write(&code); - - return code; - } - - virtual bool visit(AST::Block *ast) - { - for (AST::StatementList *it = ast->statements; it; it = it->next) { - if (! it->next) { - // we need to rewrite only the last statement of a block. - accept(it->statement); - } - } - - return false; - } - - virtual bool visit(AST::ExpressionStatement *ast) - { - unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position; - _writer->replace(startOfExpressionStatement, 0, QLatin1String("return ")); - - return false; - } - - virtual bool visit(AST::NumericLiteral *node) - { - if (node->suffix != AST::NumericLiteral::noSuffix) { - const int suffixLength = AST::NumericLiteral::suffixLength[node->suffix]; - const char *suffixSpell = AST::NumericLiteral::suffixSpell[node->suffix]; - QString pre; - pre += QLatin1String("qmlNumberFrom"); - pre += QChar(QLatin1Char(suffixSpell[0])).toUpper(); - pre += QLatin1String(&suffixSpell[1]); - pre += QLatin1Char('('); - _writer->replace(node->literalToken.begin() - _position, 0, pre); - _writer->replace(node->literalToken.end() - _position - suffixLength, - suffixLength, - QLatin1String(")")); - } - - return false; - } -}; - -} // end of anonymous namespace - - QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b) : q(b), ctxt(0), expressionFunctionValid(false), sseData(0), proxy(0), me(0), trackChange(false), line(-1), id(0), log(0) { @@ -332,7 +238,7 @@ QVariant QmlExpressionPrivate::evalQtScript() scriptEngine->currentContext()->pushScope(ctxtPriv->scopeChain.at(i)); if (!expressionFunctionValid) { - RewriteBinding rewriteBinding; + QmlRewrite::RewriteBinding rewriteBinding; const QString code = rewriteBinding(expression); expressionFunction = scriptEngine->evaluate(code, fileName.toString(), line); diff --git a/src/declarative/qml/qmlrewrite.cpp b/src/declarative/qml/qmlrewrite.cpp new file mode 100644 index 0000000..02bf8fa --- /dev/null +++ b/src/declarative/qml/qmlrewrite.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlrewrite_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlRewrite { + +QString RewriteBinding::operator()(const QString &code) +{ + Engine engine; + NodePool pool(QString(), &engine); + Lexer lexer(&engine); + Parser parser(&engine); + lexer.setCode(code, 0); + parser.parseStatement(); + return rewrite(code, 0, parser.statement()); +} + +void RewriteBinding::accept(AST::Node *node) +{ + AST::Node::acceptChild(node, this); +} + +QString RewriteBinding::rewrite(QString code, unsigned position, + AST::Statement *node) +{ + TextWriter w; + _writer = &w; + _position = position; + + accept(node); + + unsigned startOfStatement = node->firstSourceLocation().begin() - _position; + unsigned endOfStatement = node->lastSourceLocation().end() - _position; + + _writer->replace(startOfStatement, 0, QLatin1String("function() {\n")); + _writer->replace(endOfStatement, 0, QLatin1String("\n}")); + + w.write(&code); + + return code; +} + +bool RewriteBinding::visit(AST::Block *ast) +{ + for (AST::StatementList *it = ast->statements; it; it = it->next) { + if (! it->next) { + // we need to rewrite only the last statement of a block. + accept(it->statement); + } + } + + return false; +} + +bool RewriteBinding::visit(AST::ExpressionStatement *ast) +{ + unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position; + _writer->replace(startOfExpressionStatement, 0, QLatin1String("return ")); + + return false; +} + +bool RewriteBinding::visit(AST::NumericLiteral *node) +{ + if (node->suffix != AST::NumericLiteral::noSuffix) { + const int suffixLength = AST::NumericLiteral::suffixLength[node->suffix]; + const char *suffixSpell = AST::NumericLiteral::suffixSpell[node->suffix]; + QString pre; + pre += QLatin1String("qmlNumberFrom"); + pre += QChar(QLatin1Char(suffixSpell[0])).toUpper(); + pre += QLatin1String(&suffixSpell[1]); + pre += QLatin1Char('('); + _writer->replace(node->literalToken.begin() - _position, 0, pre); + _writer->replace(node->literalToken.end() - _position - suffixLength, + suffixLength, + QLatin1String(")")); + } + + return false; +} + +QString RewriteNumericLiterals::operator()(QString code, unsigned position, AST::Node *node) +{ + TextWriter w; + _writer = &w; + _position = position; + + AST::Node::acceptChild(node, this); + + w.write(&code); + + return code; +} + +bool RewriteNumericLiterals::visit(AST::NumericLiteral *node) +{ + if (node->suffix != AST::NumericLiteral::noSuffix) { + const int suffixLength = AST::NumericLiteral::suffixLength[node->suffix]; + const char *suffixSpell = AST::NumericLiteral::suffixSpell[node->suffix]; + QString pre; + pre += QLatin1String("qmlNumberFrom"); + pre += QChar(QLatin1Char(suffixSpell[0])).toUpper(); + pre += QLatin1String(&suffixSpell[1]); + pre += QLatin1Char('('); + _writer->replace(node->literalToken.begin() - _position, 0, pre); + _writer->replace(node->literalToken.end() - _position - suffixLength, + suffixLength, + QLatin1String(")")); + } + + return false; +} + +} // namespace QmlRewrite + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlrewrite_p.h b/src/declarative/qml/qmlrewrite_p.h new file mode 100644 index 0000000..51a8015 --- /dev/null +++ b/src/declarative/qml/qmlrewrite_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLREWRITE_P_H +#define QMLREWRITE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "rewriter/textwriter_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsparser_p.h" +#include "parser/qmljsnodepool_p.h" + +QT_BEGIN_NAMESPACE + +namespace QmlRewrite { +using namespace QmlJS; + +class RewriteBinding: protected AST::Visitor +{ + unsigned _position; + TextWriter *_writer; + +public: + QString operator()(const QString &code); + +protected: + using AST::Visitor::visit; + + void accept(AST::Node *node); + QString rewrite(QString code, unsigned position, AST::Statement *node); + virtual bool visit(AST::Block *ast); + virtual bool visit(AST::ExpressionStatement *ast); + virtual bool visit(AST::NumericLiteral *node); +}; + +class RewriteNumericLiterals: protected AST::Visitor +{ + unsigned _position; + TextWriter *_writer; + +public: + QString operator()(QString code, unsigned position, AST::Node *node); + +protected: + using AST::Visitor::visit; + + virtual bool visit(AST::NumericLiteral *node); +}; + +} // namespace QmlRewrite + +QT_END_NAMESPACE + +#endif // QMLREWRITE_P_H + diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index f26266b..5f97c71 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -49,7 +49,7 @@ #include "parser/qmljsastvisitor_p.h" #include "parser/qmljsast_p.h" -#include "rewriter/textwriter_p.h" +#include "qmlrewrite_p.h" #include #include @@ -64,48 +64,6 @@ using namespace QmlParser; namespace { -class RewriteNumericLiterals: protected AST::Visitor -{ - unsigned _position; - TextWriter *_writer; - -public: - QString operator()(QString code, unsigned position, AST::Node *node) - { - TextWriter w; - _writer = &w; - _position = position; - - AST::Node::acceptChild(node, this); - - w.write(&code); - - return code; - } - -protected: - using AST::Visitor::visit; - - virtual bool visit(AST::NumericLiteral *node) - { - if (node->suffix != AST::NumericLiteral::noSuffix) { - const int suffixLength = AST::NumericLiteral::suffixLength[node->suffix]; - const char *suffixSpell = AST::NumericLiteral::suffixSpell[node->suffix]; - QString pre; - pre += QLatin1String("qmlNumberFrom"); - pre += QChar(QLatin1Char(suffixSpell[0])).toUpper(); - pre += QLatin1String(&suffixSpell[1]); - pre += QLatin1Char('('); - _writer->replace(node->literalToken.begin() - _position, 0, pre); - _writer->replace(node->literalToken.end() - _position - suffixLength, - suffixLength, - QLatin1String(")")); - } - - return false; - } -}; - class ProcessAST: protected AST::Visitor { struct State { @@ -196,7 +154,7 @@ protected: const AST::SourceLocation &last) const { return _contents.mid(first.offset, last.offset + last.length - first.offset); } - RewriteNumericLiterals rewriteNumericLiterals; + QmlRewrite::RewriteNumericLiterals rewriteNumericLiterals; QString asString(AST::ExpressionNode *expr) { -- cgit v0.12 From d71ef06fc1261968b8c5ecf7a438db02e2654b29 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 17:08:50 +1000 Subject: Protect against overriding FINAL properties --- src/declarative/qml/qmlcompiler.cpp | 12 ++++++++++-- src/declarative/qml/qmldom.cpp | 4 ++-- src/declarative/qml/qmlparser.cpp | 2 +- src/declarative/qml/qmlparser_p.h | 2 +- src/declarative/qml/qmlscriptparser.cpp | 4 ++-- tests/auto/declarative/qmlparser/finalOverride.errors.txt | 1 + tests/auto/declarative/qmlparser/finalOverride.txt | 3 +++ tests/auto/declarative/qmlparser/testtypes.h | 2 +- tests/auto/declarative/qmlparser/tst_qmlparser.cpp | 1 + 9 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 tests/auto/declarative/qmlparser/finalOverride.errors.txt create mode 100644 tests/auto/declarative/qmlparser/finalOverride.txt diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 182495a..b0bc6e8 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -160,8 +160,8 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) QString exceptionDescription; \ QmlError error; \ error.setUrl(output->url); \ - error.setLine(token->location.start.line); \ - error.setColumn(token->location.start.column); \ + error.setLine((token)->location.start.line); \ + error.setColumn((token)->location.start.column); \ QDebug d(&exceptionDescription); \ d << desc; \ error.setDescription(exceptionDescription.trimmed()); \ @@ -1738,6 +1738,14 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + int propIdx = + obj->metaObject()->indexOfProperty(p.name.constData()); + if (-1 != propIdx) { + QMetaProperty prop = obj->metaObject()->property(propIdx); + if (prop.isFinal()) + COMPILE_EXCEPTION(&p, "Cannot override FINAL property"); + } + if (p.isDefaultProperty && (p.type != Object::DynamicProperty::Alias || mode == ResolveAliases)) diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index 505d872..293ea6a 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -587,7 +587,7 @@ QmlDomProperty QmlDomDynamicProperty::defaultValue() const int QmlDomDynamicProperty::position() const { if (isValid()) { - return d->property.range.offset; + return d->property.location.range.offset; } else return -1; } @@ -599,7 +599,7 @@ int QmlDomDynamicProperty::position() const int QmlDomDynamicProperty::length() const { if (isValid()) - return d->property.range.length; + return d->property.location.range.length; else return -1; } diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index e2d334e..8eb58c8 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -146,7 +146,7 @@ QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o) type(o.type), name(o.name), defaultValue(o.defaultValue), - range(o.range) + location(o.location) { } diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 84e6dd4..d23b4ea 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -169,7 +169,7 @@ namespace QmlParser Type type; QByteArray name; QmlParser::Property *defaultValue; - LocationRange range; + LocationSpan location; }; struct DynamicSignal { DynamicSignal(); diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 5f97c71..c1c11c7 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -530,8 +530,8 @@ bool ProcessAST::visit(AST::UiPublicMember *node) property.isDefaultProperty = node->isDefaultMember; property.type = type; property.name = name.toUtf8(); - property.range.offset = node->firstSourceLocation().offset; - property.range.length = node->semicolonToken.end() - property.range.offset; + property.location = location(node->firstSourceLocation(), + node->lastSourceLocation()); if (node->expression) { // default value property.defaultValue = new Property; diff --git a/tests/auto/declarative/qmlparser/finalOverride.errors.txt b/tests/auto/declarative/qmlparser/finalOverride.errors.txt new file mode 100644 index 0000000..fc7070c --- /dev/null +++ b/tests/auto/declarative/qmlparser/finalOverride.errors.txt @@ -0,0 +1 @@ +2:5:Cannot override FINAL property diff --git a/tests/auto/declarative/qmlparser/finalOverride.txt b/tests/auto/declarative/qmlparser/finalOverride.txt new file mode 100644 index 0000000..54ea6fb --- /dev/null +++ b/tests/auto/declarative/qmlparser/finalOverride.txt @@ -0,0 +1,3 @@ +MyQmlObject { + property int value: 10 +} diff --git a/tests/auto/declarative/qmlparser/testtypes.h b/tests/auto/declarative/qmlparser/testtypes.h index ab67a4a..7528331 100644 --- a/tests/auto/declarative/qmlparser/testtypes.h +++ b/tests/auto/declarative/qmlparser/testtypes.h @@ -51,7 +51,7 @@ private: class MyQmlObject : public QObject, public MyInterface, public QmlParserStatus { Q_OBJECT - Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int value READ value WRITE setValue FINAL) Q_PROPERTY(QString readOnlyString READ readOnlyString) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) Q_PROPERTY(QRect rect READ rect WRITE setRect) diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp index 7023263..f722ca3 100644 --- a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp +++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp @@ -137,6 +137,7 @@ void tst_qmlparser::errors_data() QTest::newRow("missingObject") << "missingObject.txt" << "missingObject.errors.txt" << false; QTest::newRow("failingComponent") << "failingComponent.txt" << "failingComponent.errors.txt" << false; QTest::newRow("missingSignal") << "missingSignal.txt" << "missingSignal.errors.txt" << false; + QTest::newRow("finalOverride") << "finalOverride.txt" << "finalOverride.errors.txt" << false; } void tst_qmlparser::errors() -- cgit v0.12 From c0a922d3f6e1421b037316a54c62e615473dc5d6 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 17:09:01 +1000 Subject: Mark properties as FINAL --- src/declarative/fx/qfxitem.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 5fb4eff..a674df9 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -98,31 +98,31 @@ class Q_DECLARATIVE_EXPORT QFxItem : public QSimpleCanvasItem, public QmlParserS Q_OBJECT Q_INTERFACES(QmlParserStatus) - Q_PROPERTY(QFxItem * parent READ itemParent WRITE setItemParent NOTIFY parentChanged DESIGNABLE false) + Q_PROPERTY(QFxItem * parent READ itemParent WRITE setItemParent NOTIFY parentChanged DESIGNABLE false FINAL) Q_PROPERTY(QFxItem * moveToParent READ itemParent WRITE moveToParent NOTIFY parentChanged DESIGNABLE false) Q_PROPERTY(QString id READ id WRITE setId) Q_PROPERTY(QmlList* children READ children DESIGNABLE false) Q_PROPERTY(QmlList* resources READ resources DESIGNABLE false) - Q_PROPERTY(QFxAnchors * anchors READ anchors DESIGNABLE false CONSTANT) + Q_PROPERTY(QFxAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL) Q_PROPERTY(QmlList *data READ data DESIGNABLE false) - Q_PROPERTY(QFxContents * contents READ contents DESIGNABLE false CONSTANT) + Q_PROPERTY(QFxContents * contents READ contents DESIGNABLE false CONSTANT FINAL) Q_PROPERTY(QmlList* states READ states DESIGNABLE false) Q_PROPERTY(QmlList* transitions READ transitions DESIGNABLE false) Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged) Q_PROPERTY(QUrl qml READ qml WRITE setQml NOTIFY qmlChanged) Q_PROPERTY(QFxItem *qmlItem READ qmlItem NOTIFY qmlChanged) - Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) - Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) - Q_PROPERTY(qreal z READ z WRITE setZ) - Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged) - Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged) - Q_PROPERTY(QFxAnchorLine left READ left CONSTANT) - Q_PROPERTY(QFxAnchorLine right READ right CONSTANT) - Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter CONSTANT) - Q_PROPERTY(QFxAnchorLine top READ top CONSTANT) - Q_PROPERTY(QFxAnchorLine bottom READ bottom CONSTANT) - Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter CONSTANT) - Q_PROPERTY(QFxAnchorLine baseline READ baseline CONSTANT) + Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL) + Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL) + Q_PROPERTY(qreal z READ z WRITE setZ FINAL) + Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged FINAL) + Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged FINAL) + Q_PROPERTY(QFxAnchorLine left READ left CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine right READ right CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine top READ top CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine bottom READ bottom CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter CONSTANT FINAL) + Q_PROPERTY(QFxAnchorLine baseline READ baseline CONSTANT FINAL) Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged) Q_PROPERTY(bool flipVertically READ flipVertically WRITE setFlipVertically) Q_PROPERTY(bool flipHorizontally READ flipHorizontally WRITE setFlipHorizontally) @@ -131,11 +131,11 @@ class Q_DECLARATIVE_EXPORT QFxItem : public QSimpleCanvasItem, public QmlParserS Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) Q_PROPERTY(QSimpleCanvasFilter *filter READ filter WRITE setFilter) Q_PROPERTY(bool clip READ clip WRITE setClip) - Q_PROPERTY(bool focusable READ isFocusable WRITE setFocusable) - Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged) - Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged) + Q_PROPERTY(bool focusable READ isFocusable WRITE setFocusable FINAL) + Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL) + Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL) Q_PROPERTY(QList* transform READ transform) - Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged) + Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged FINAL) Q_CLASSINFO("DefaultProperty", "data") typedef QHash QmlChildren; -- cgit v0.12 From 14275363e5ae678ca92a6da4778035ca2ad1594c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 17:15:13 +1000 Subject: Add a QmlError::toString() method --- src/declarative/qml/qmlerror.cpp | 29 +++++++++++++++++------------ src/declarative/qml/qmlerror.h | 2 ++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp index 149e173..5ee9144 100644 --- a/src/declarative/qml/qmlerror.cpp +++ b/src/declarative/qml/qmlerror.cpp @@ -168,6 +168,21 @@ void QmlError::setColumn(int column) } /*! + Return the error as a human readable string. +*/ +QString QmlError::toString() const +{ + QString rv; + rv = url().toString() + QLatin1String(":") + QString::number(line()); + if(column() != -1) + rv += QLatin1String(":") + QString::number(column()); + + rv += QLatin1String(": ") + description(); + + return rv; +} + +/*! \relates QmlError \fn QDebug operator<<(QDebug debug, const QmlError &error) @@ -176,19 +191,9 @@ void QmlError::setColumn(int column) QDebug operator<<(QDebug debug, const QmlError &error) { - QUrl url = error.url(); - - QString output; - - output = url.toString() + QLatin1String(":") + - QString::number(error.line()); + debug << qPrintable(error.toString()); - if(error.column() != -1) - output += QLatin1String(":") + QString::number(error.column()); - - output += QLatin1String(": ") + error.description(); - - debug << qPrintable(output); + QUrl url = error.url(); if (error.line() > 0 && url.scheme() == QLatin1String("file")) { QString file = url.toLocalFile(); diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h index 57d2f8f..c1a8720 100644 --- a/src/declarative/qml/qmlerror.h +++ b/src/declarative/qml/qmlerror.h @@ -69,6 +69,8 @@ public: void setLine(int); int column() const; void setColumn(int); + + QString toString() const; private: QmlErrorPrivate *d; }; -- cgit v0.12 From c02bfff71cc56582e0898864d8c13047fa86756d Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 16 Jul 2009 16:45:36 +1000 Subject: Add an errors() signal to QFxView This is in addition to the logging to the console. Discussed with Aaron. --- src/declarative/util/qfxview.cpp | 64 +++++++++++----------------------------- src/declarative/util/qfxview.h | 2 +- 2 files changed, 18 insertions(+), 48 deletions(-) diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index 41f7db2..821dc25 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -246,44 +246,6 @@ void QFxView::execute() } } -/*! - \internal -*/ -void QFxView::printErrorLine(const QmlError &error) -{ - QUrl url = error.url(); - if (error.line() > 0 && error.column() > 0 && - url.scheme() == QLatin1String("file")) { - QString file = url.toLocalFile(); - QFile f(file); - if (f.open(QIODevice::ReadOnly)) { - QByteArray data = f.readAll(); - QTextStream stream(data, QIODevice::ReadOnly); - const QString code = stream.readAll(); - const QStringList lines = code.split(QLatin1Char('\n')); - - if (lines.count() >= error.line()) { - const QString &line = lines.at(error.line() - 1); - qWarning() << qPrintable(line); - - int column = qMax(0, error.column() - 1); - column = qMin(column, line.length()); - - QByteArray ind; - ind.reserve(column); - for (int i = 0; i < column; ++i) { - const QChar ch = line.at(i); - if (ch.isSpace()) - ind.append(ch.unicode()); - else - ind.append(' '); - } - ind.append('^'); - qWarning() << ind.constData(); - } - } - } -} /*! \internal @@ -292,14 +254,15 @@ void QFxView::continueExecute() { disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute())); - if (!d->component){ + if (!d->component) { qWarning() << "Error in loading" << d->source; return; } if(d->component->isError()) { - QList errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList errorList = d->component->errors(); + emit errors(errorList); + foreach (const QmlError &error, errorList) { qWarning() << error; } @@ -309,8 +272,9 @@ void QFxView::continueExecute() QObject *obj = d->component->create(); if(d->component->isError()) { - QList errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList errorList = d->component->errors(); + emit errors(errorList); + foreach (const QmlError &error, errorList) { qWarning() << error; } @@ -362,6 +326,10 @@ void QFxView::continueExecute() This signal is emitted when the view is resized to \a size. */ +/*! \fn void QFxView::error(const QList &errors) + This signal is emitted when the qml loaded contains errors. + */ + /*! \internal */ @@ -453,8 +421,9 @@ QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent) QmlComponent component(&d->engine, qml.toUtf8(), QUrl()); if(d->component->isError()) { - QList errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList errorList = d->component->errors(); + emit errors(errorList); + foreach (const QmlError &error, errorList) { qWarning() << error; } @@ -463,8 +432,9 @@ QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent) QObject *obj = component.create(); if(d->component->isError()) { - QList errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList errorList = d->component->errors(); + emit errors(errorList); + foreach (const QmlError &error, errorList) { qWarning() << error; } diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h index 05bf005..67de89b 100644 --- a/src/declarative/util/qfxview.h +++ b/src/declarative/util/qfxview.h @@ -88,9 +88,9 @@ public: void dumpRoot(); - static void printErrorLine(const QmlError &); Q_SIGNALS: void sceneResized(QSize size); + void errors(const QList &error); private Q_SLOTS: void continueExecute(); -- cgit v0.12 From e337d74c2be957d356216b01c93299a2992a128b Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 16 Jul 2009 17:34:46 +1000 Subject: Qualifiers and versioning for C++-defined types. (and a *TEST* hack for Qt/4.6/ - this is exactly NOT the way to do it) Two-step type resolution for Javascript (Aaron). --- src/declarative/qml/qml.h | 7 +- src/declarative/qml/qmlengine.cpp | 250 +++++++++++++++++++++++++----------- src/declarative/qml/qmlengine.h | 5 +- src/declarative/qml/qmlmetatype.cpp | 2 +- 4 files changed, 183 insertions(+), 81 deletions(-) diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h index cd01f6a..d43e693 100644 --- a/src/declarative/qml/qml.h +++ b/src/declarative/qml/qml.h @@ -73,14 +73,17 @@ QT_MODULE(Declarative) QT_BEGIN_NAMESPACE +//#define QML_FORCE_NAMESPACE "Qt/4.6/" +#define QML_FORCE_NAMESPACE + #define QML_DEFINE_INTERFACE(INTERFACE) \ template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterInterface(#INTERFACE)); #define QML_DEFINE_EXTENDED_TYPE(TYPE, NAME, EXTENSION) \ - template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterExtendedType(#NAME, #TYPE)); + template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterExtendedType(QML_FORCE_NAMESPACE #NAME, #TYPE)); #define QML_DEFINE_TYPE(TYPE, NAME) \ - template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterType(#NAME, #TYPE)); + template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterType(QML_FORCE_NAMESPACE #NAME, #TYPE)); #define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \ template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterExtendedType(#TYPE)); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index acbeb26..5adc2c3 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -1,4 +1,4 @@ - /**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#undef QT3_SUPPORT // don't want it here - it just causes bugs (which is why we removed it) + #include #include #include @@ -1113,11 +1115,73 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object, } +struct QmlEngine::ImportedNamespace { + QStringList urls; + QStringList versions; + QList isLibrary; + + QUrl find(const QString& type) const + { + for (int i=0; i=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1; + QStringRef maptype = line.leftRef(space1); + QStringRef mapversion = line.midRef(space1+1,space2<0?line.length()-space1-2:space2-space1-1); + QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-2); + if (maptype==type && mapversion==version) { + if (mapfile.isEmpty()) + return url; + else + return url.resolved(mapfile.toString()); + } + } while (!qmldir.atEnd()); + } + } + if (ok) + return url; + } + } + return QUrl(); + } + + QmlType *findBuiltin(const QByteArray& type, QByteArray* found=0) const + { + for (int i=0; iurls.append(url); s->versions.append(version); @@ -1155,9 +1222,9 @@ public: return true; } - QUrl find(const QUrl& base, const QString& type) + QUrl find(const QString& type) const { - TypeSet *s = 0; + const QmlEngine::ImportedNamespace *s = 0; int slash = type.indexOf(QLatin1Char('/')); if (slash >= 0) { while (!s) { @@ -1172,48 +1239,16 @@ public: s = &unqualifiedset; } QString unqualifiedtype = type.mid(slash+1); - if (s) { - for (int i=0; iurls.count(); ++i) { - QUrl url = base.resolved(QUrl(s->urls.at(i) +QLatin1String("/")+ unqualifiedtype + QLatin1String(".qml"))); - QString version = s->versions.at(i); - // XXX search non-files too! (eg. zip files, see QT-524) - QFileInfo f(url.toLocalFile()); - if (f.exists()) { - bool ok=true; - if (!version.isEmpty()) { - ok=false; - // Check version file - XXX cache these in QmlEngine! - QFile qmldir(s->urls.at(i)+QLatin1String("/qmldir")); - if (qmldir.open(QIODevice::ReadOnly)) { - do { - QString line = QString::fromUtf8(qmldir.readLine()); - if (line.at(0) == QLatin1Char('#')) - continue; - int space1 = line.indexOf(QLatin1Char(' ')); - int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1; - QStringRef maptype = line.leftRef(space1); - QStringRef mapversion = line.midRef(space1+1,space2<0?line.length()-space1-2:space2-space1-1); - QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-2); - if (maptype==unqualifiedtype && mapversion==version) { - if (mapfile.isEmpty()) - return url; - else - return url.resolved(mapfile.toString()); - } - } while (!qmldir.atEnd()); - } - } - if (ok) - return url; - } - } - } - return base.resolved(QUrl(type + QLatin1String(".qml"))); + if (s) + return s->find(unqualifiedtype); + else + return QUrl(); } - QmlType *findBuiltin(const QUrl& base, const QByteArray& type) + + QmlType *findBuiltin(const QByteArray& type, QByteArray* found=0) { - TypeSet *s = 0; + QmlEngine::ImportedNamespace *s = 0; int slash = type.indexOf('/'); if (slash >= 0) { while (!s) { @@ -1228,23 +1263,20 @@ public: s = &unqualifiedset; } QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower) - if (s) { - for (int i=0; iurls.count(); ++i) { - QmlType *t = QmlMetaType::qmlType(s->urls.at(i).toLatin1()+"/"+unqualifiedtype); - if (t) return t; - } - } - return QmlMetaType::qmlType(type); + if (s) + return s->findBuiltin(unqualifiedtype,found); + else + return 0; + } + + QmlEngine::ImportedNamespace *findNamespace(const QString& type) + { + return set.value(type); } private: - struct TypeSet { - QStringList urls; - QStringList versions; - QList isLibrary; - }; - TypeSet unqualifiedset; - QHash set; + QmlEngine::ImportedNamespace unqualifiedset; + QHash set; }; QmlEngine::Imports::Imports() : @@ -1256,11 +1288,24 @@ QmlEngine::Imports::~Imports() { } +/*! + Sets the base URL to be used for all relative file imports added. +*/ void QmlEngine::Imports::setBaseUrl(const QUrl& url) { base = url; } +/*! + Adds \a path as a directory where installed QML components are + defined in a URL-based directory structure. + + For example, if you add \c /opt/MyApp/lib/qml and then load QML + that imports \c com.mycompany.Feature, then QmlEngine will look + in \c /opt/MyApp/lib/qml/com/mycompany/Feature/ for the components + provided by that module (and in the case of versioned imports, + for the \c qmldir file definiting the type version mapping. +*/ void QmlEngine::addImportPath(const QString& path) { if (qmlImportTrace()) @@ -1269,36 +1314,87 @@ void QmlEngine::addImportPath(const QString& path) d->fileImportPath.prepend(path); } +/*! + Adds information to \a imports such that subsequent calls to resolveType() + will resolve types qualified by \a prefix by considering types found at the given \a uri. + + The uri is either a directory (if importType is FileImport), or a URI resolved using paths + added via addImportPath() (if importType is LibraryImport). + + The \a prefix may be empty, in which case the import location is considered for + unqualified types. + + The base URL must already have been set with Import::setBaseUrl(). +*/ bool QmlEngine::addToImport(Imports* imports, const QString& uri, const QString& prefix, const QString& version, ImportType importType) const { Q_D(const QmlEngine); - bool ok = imports->d->add(uri,prefix,version,importType,d->fileImportPath); + bool ok = imports->d->add(imports->base,uri,prefix,version,importType,d->fileImportPath); if (qmlImportTrace()) qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << version << (importType==LibraryImport ? "Library" : "File") << ": " << ok; return ok; } -bool QmlEngine::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return) const +/*! + Using the given \a imports, the given (namespace qualified) \a type is resolved to either + an ImportedNamespace stored at \a ns_return, + a QmlType stored at \a type_return, or + a component located at \a url_return. + + If any return pointer is 0, the corresponding search is not done. + + \sa addToImport() +*/ +bool QmlEngine::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, ImportedNamespace** ns_return) const { - Q_D(const QmlEngine); - QmlType* t = imports.d->findBuiltin(imports.base,type); - if (t) { - if (type_return) *type_return = t; - if (qmlImportTrace()) - qDebug() << "QmlEngine::resolveType" << type << "= (builtin)"; - return true; + if (ns_return) { + *ns_return = imports.d->findNamespace(QLatin1String(type)); + if (*ns_return) + return true; } - QUrl url = imports.d->find(imports.base,type); - if (url.isValid()) { - if (url_return) *url_return = url; - if (qmlImportTrace()) - qDebug() << "QmlEngine::resolveType" << type << "=" << url; - return true; + if (type_return) { + QmlType* t = imports.d->findBuiltin(type); + if (!t) t = QmlMetaType::qmlType(type); + if (t) { + if (type_return) *type_return = t; + if (qmlImportTrace()) + qDebug() << "QmlEngine::resolveType" << type << "= (builtin)"; + return true; + } + } + if (url_return) { + QUrl url = imports.d->find(QLatin1String(type)); + if (!url.isValid()) + url = imports.base.resolved(QUrl(QLatin1String(type + ".qml"))); + + if (url.isValid()) { + if (url_return) *url_return = url; + if (qmlImportTrace()) + qDebug() << "QmlEngine::resolveType" << type << "=" << url; + return true; + } } if (qmlImportTrace()) qDebug() << "QmlEngine::resolveType" << type << " not found"; return false; } +/*! + Searching \e only in the namespace \a ns (previously returned in a call to + resolveType(), \a type is found and returned to either + a QmlType stored at \a type_return, or + a component located at \a url_return. + + If either return pointer is 0, the corresponding search is not done. +*/ +void QmlEngine::resolveTypeInNamespace(ImportedNamespace* ns, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const +{ + if (type_return) { + *type_return = ns->findBuiltin(type); + } + if (url_return) { + *url_return = ns->find(QLatin1String(type)); + } +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index 6a418b5..3e402d8 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -87,10 +87,13 @@ public: QUrl base; QmlImportsPrivate *d; }; + struct ImportedNamespace; + void addImportPath(const QString& dir); enum ImportType { LibraryImport, FileImport }; bool addToImport(Imports*, const QString& uri, const QString& prefix, const QString& version, ImportType type) const; - bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const; + bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, ImportedNamespace** ns_return=0) const; + void resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const; void setNetworkAccessManager(QNetworkAccessManager *); QNetworkAccessManager *networkAccessManager() const; diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index e6c7376..16baf08 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -426,7 +426,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun for (int ii = 0; ii < name.count(); ++ii) { QChar ch = name.at(ii); - if (!ch.isLetterOrNumber() && ch != QChar::fromLatin1('/')) { + if (!ch.isLetterOrNumber() && ch != QChar::fromLatin1('/') && ch != QChar::fromLatin1('.')) { qWarning("QmlMetaType: Invalid QML name %s", cname); return -1; } -- cgit v0.12 From 3bd0062535aaa991fadf739f9362851afacb19eb Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 16 Jul 2009 15:43:28 +0200 Subject: Recognize T_MULTILINE_STRING_LITERAL as a primary expression and removed UiMultilineStringLiteral statements. --- src/declarative/qml/parser/qmljs.g | 29 +- src/declarative/qml/parser/qmljsgrammar.cpp | 1427 +++++++++++++-------------- src/declarative/qml/parser/qmljsgrammar_p.h | 18 +- src/declarative/qml/parser/qmljsparser.cpp | 428 ++++---- src/declarative/qml/parser/qmljsparser_p.h | 4 +- 5 files changed, 929 insertions(+), 977 deletions(-) diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g index 43cce40..20ee27d 100644 --- a/src/declarative/qml/parser/qmljs.g +++ b/src/declarative/qml/parser/qmljs.g @@ -750,26 +750,6 @@ case $rule_number: { } break; ./ -UiMultilineStringLiteral: T_MULTILINE_STRING_LITERAL ; -/. -case $rule_number: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -./ - -UiMultilineStringStatement: UiMultilineStringLiteral T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -UiMultilineStringStatement: UiMultilineStringLiteral T_SEMICOLON ; -/. -case $rule_number: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; -./ - - UiObjectMember: UiQualifiedId T_COLON Expression UiObjectInitializer ; /. case $rule_number: { @@ -798,12 +778,6 @@ UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ; /.case $rule_number:./ -UiObjectMember: UiQualifiedId T_COLON DebuggerStatement ; -/.case $rule_number:./ - -UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ; -/.case $rule_number:./ - UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding? /.case $rule_number:./ @@ -1053,6 +1027,9 @@ case $rule_number: { } break; ./ +PrimaryExpression: T_MULTILINE_STRING_LITERAL ; +/.case $rule_number:./ + PrimaryExpression: T_STRING_LITERAL ; /. case $rule_number: { diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp index 4fba480..1b23be6 100644 --- a/src/declarative/qml/parser/qmljsgrammar.cpp +++ b/src/declarative/qml/parser/qmljsgrammar.cpp @@ -2,7 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,7 +35,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -58,550 +58,541 @@ const int QmlJSGrammar::lhs [] = { 95, 95, 95, 96, 99, 99, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 101, 100, 107, 107, 109, 109, 110, 110, 106, 108, - 108, 111, 112, 112, 108, 108, 108, 108, 108, 108, - 108, 118, 118, 118, 119, 119, 120, 120, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 105, 105, 104, 104, 104, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 105, 105, 125, 125, 125, 125, 124, 124, - 127, 127, 129, 129, 129, 129, 129, 129, 130, 130, - 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, - 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, - 130, 130, 130, 130, 130, 130, 130, 130, 130, 131, - 131, 132, 132, 132, 132, 132, 135, 135, 136, 136, - 136, 136, 134, 134, 137, 137, 138, 138, 139, 139, - 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 141, 141, 141, 141, 142, 142, 142, 143, 143, - 143, 143, 144, 144, 144, 144, 144, 144, 144, 145, - 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, - 147, 147, 147, 147, 147, 148, 148, 149, 149, 150, - 150, 151, 151, 152, 152, 153, 153, 154, 154, 155, - 155, 156, 156, 157, 157, 158, 158, 159, 159, 128, - 128, 160, 160, 161, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 161, 98, 98, 162, 162, 163, - 163, 164, 164, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 113, 175, - 175, 174, 174, 122, 122, 176, 176, 177, 177, 179, - 179, 178, 180, 183, 181, 181, 184, 182, 182, 114, - 115, 115, 117, 117, 165, 165, 165, 165, 165, 165, - 165, 166, 166, 166, 166, 167, 167, 167, 167, 168, - 168, 169, 171, 185, 185, 188, 188, 186, 186, 189, - 187, 170, 170, 170, 172, 172, 173, 173, 173, 190, - 191, 116, 116, 121, 133, 195, 195, 192, 192, 193, - 193, 196, 197, 197, 198, 198, 194, 194, 126, 126, - 199}; + 108, 108, 108, 108, 108, 108, 115, 115, 115, 116, + 116, 117, 117, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 105, 105, 104, 104, 104, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 105, 105, + 122, 122, 122, 122, 121, 121, 124, 124, 126, 126, + 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 128, 128, 129, 129, 129, + 129, 129, 132, 132, 133, 133, 133, 133, 131, 131, + 134, 134, 135, 135, 136, 136, 136, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 138, 138, 138, + 138, 139, 139, 139, 140, 140, 140, 140, 141, 141, + 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, + 142, 143, 143, 143, 143, 143, 144, 144, 144, 144, + 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, + 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, + 154, 155, 155, 156, 156, 125, 125, 157, 157, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 98, 98, 159, 159, 160, 160, 161, 161, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 111, 173, 173, 172, 172, 119, + 119, 174, 174, 175, 175, 177, 177, 176, 178, 181, + 179, 179, 182, 180, 180, 112, 113, 113, 114, 114, + 162, 162, 162, 162, 162, 162, 162, 163, 163, 163, + 163, 164, 164, 164, 164, 165, 165, 166, 168, 183, + 183, 186, 186, 184, 184, 187, 185, 167, 167, 167, + 169, 169, 170, 170, 170, 188, 189, 171, 171, 118, + 130, 193, 193, 190, 190, 191, 191, 194, 195, 195, + 196, 196, 192, 192, 123, 123, 197}; const int QmlJSGrammar:: rhs[] = { 2, 2, 2, 2, 1, 1, 1, 2, 3, 3, 5, 5, 3, 3, 4, 4, 6, 6, 5, 5, 0, 1, 1, 2, 1, 3, 2, 3, 2, 1, - 5, 1, 2, 2, 4, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 0, 1, 2, 4, 5, 2, - 4, 4, 5, 5, 6, 6, 7, 7, 1, 1, + 5, 4, 3, 3, 3, 3, 1, 1, 1, 0, + 1, 2, 4, 5, 2, 4, 4, 5, 5, 6, + 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, - 4, 3, 1, 3, 1, 2, 3, 4, 1, 2, - 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 4, 5, 3, 4, 3, 1, 3, + 1, 2, 3, 4, 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 4, 3, 5, 1, 2, 4, 4, - 4, 3, 0, 1, 1, 3, 1, 1, 1, 2, - 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, - 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, + 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, + 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, - 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 5, 1, 5, 1, - 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 0, 1, 1, - 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, - 2, 0, 1, 3, 3, 1, 1, 1, 3, 1, - 3, 2, 2, 2, 0, 1, 2, 0, 1, 1, - 2, 2, 7, 5, 7, 7, 5, 9, 10, 7, - 8, 2, 2, 3, 3, 2, 2, 3, 3, 3, - 3, 5, 5, 3, 5, 1, 2, 0, 1, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, - 2, 2, 2, 8, 8, 1, 3, 0, 1, 0, - 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, - 2}; + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, + 3, 1, 1, 1, 3, 1, 3, 2, 2, 2, + 0, 1, 2, 0, 1, 1, 2, 2, 7, 5, + 7, 7, 5, 9, 10, 7, 8, 2, 2, 3, + 3, 2, 2, 3, 3, 3, 3, 5, 5, 3, + 5, 1, 2, 0, 1, 4, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 5, 2, 2, 2, 8, + 8, 1, 3, 0, 1, 0, 1, 1, 1, 2, + 1, 1, 0, 1, 0, 1, 2}; const int QmlJSGrammar::action_default [] = { - 0, 0, 0, 21, 0, 169, 236, 200, 208, 204, - 148, 220, 196, 3, 133, 67, 149, 212, 216, 137, - 166, 147, 152, 132, 186, 173, 0, 73, 74, 70, - 337, 63, 339, 0, 0, 0, 0, 0, 0, 68, - 71, 0, 0, 64, 65, 72, 66, 0, 69, 0, - 0, 162, 0, 0, 149, 168, 151, 150, 0, 0, - 0, 164, 165, 163, 167, 0, 197, 0, 0, 0, - 0, 187, 0, 0, 0, 0, 0, 0, 177, 0, - 0, 0, 171, 172, 170, 175, 179, 178, 176, 174, - 189, 188, 190, 0, 205, 0, 201, 0, 0, 143, - 130, 142, 131, 99, 100, 101, 126, 102, 127, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 128, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 129, 0, 0, 141, 237, 144, 0, - 145, 0, 146, 140, 0, 233, 226, 224, 231, 232, - 230, 229, 235, 228, 227, 225, 234, 221, 0, 209, - 0, 0, 213, 0, 0, 217, 0, 0, 143, 135, - 0, 134, 0, 139, 153, 0, 338, 328, 329, 0, - 326, 0, 327, 0, 330, 244, 251, 250, 258, 246, - 0, 247, 331, 0, 336, 248, 249, 254, 252, 333, - 332, 335, 255, 0, 266, 0, 0, 0, 0, 337, - 63, 0, 339, 64, 238, 280, 65, 0, 0, 0, - 267, 0, 0, 256, 257, 0, 245, 253, 281, 282, - 325, 334, 0, 296, 297, 298, 299, 0, 292, 293, - 294, 295, 322, 323, 0, 0, 0, 0, 0, 285, - 286, 242, 240, 202, 210, 206, 222, 198, 243, 0, - 149, 214, 218, 191, 180, 0, 0, 199, 0, 0, - 0, 0, 192, 0, 0, 0, 0, 0, 184, 182, - 185, 183, 181, 194, 193, 195, 0, 207, 0, 203, - 0, 241, 149, 0, 223, 238, 239, 0, 238, 0, - 0, 288, 0, 0, 0, 290, 0, 211, 0, 0, - 215, 0, 0, 219, 278, 0, 270, 279, 273, 0, - 277, 0, 238, 271, 0, 238, 0, 0, 289, 0, - 0, 0, 291, 338, 328, 0, 0, 330, 0, 324, - 0, 314, 0, 0, 0, 284, 0, 283, 0, 340, - 0, 98, 260, 263, 0, 99, 266, 102, 127, 104, - 105, 70, 109, 110, 63, 111, 114, 68, 71, 64, - 238, 65, 72, 117, 66, 119, 69, 121, 122, 267, - 124, 125, 129, 0, 91, 0, 0, 93, 97, 95, - 81, 94, 96, 0, 92, 80, 261, 259, 137, 138, - 143, 0, 136, 0, 313, 0, 300, 301, 0, 312, - 0, 0, 0, 303, 308, 306, 309, 0, 0, 307, - 308, 0, 304, 0, 305, 262, 311, 0, 262, 310, - 0, 315, 316, 0, 262, 317, 318, 0, 0, 319, - 0, 0, 0, 320, 321, 155, 154, 0, 0, 0, - 287, 0, 0, 0, 302, 275, 268, 0, 276, 272, - 0, 274, 264, 0, 265, 269, 85, 0, 0, 89, - 75, 0, 77, 87, 0, 78, 88, 90, 79, 86, - 76, 0, 82, 159, 157, 161, 158, 156, 160, 2, - 5, 0, 7, 6, 0, 1, 83, 61, 62, 0, - 0, 0, 9, 10, 0, 11, 12, 0, 13, 0, - 0, 14, 0, 19, 20, 84, 0, 15, 16, 0, - 17, 18, 8, 22, 0, 4, 0, 29, 59, 0, - 0, 64, 27, 65, 30, 23, 0, 0, 60, 0, - 44, 43, 42, 0, 0, 53, 0, 54, 0, 57, - 58, 0, 0, 0, 51, 0, 52, 0, 55, 56, - 50, 45, 46, 0, 0, 0, 0, 48, 49, 47, - 28, 24, 0, 36, 39, 37, 0, 38, 41, 262, - 0, 32, 0, 40, 35, 99, 266, 102, 127, 104, - 105, 70, 109, 110, 63, 111, 114, 68, 71, 64, - 238, 65, 72, 117, 66, 119, 69, 121, 122, 267, - 124, 125, 129, 67, 0, 25, 0, 31, 26, 33, - 34, 341}; + 0, 0, 0, 21, 0, 165, 232, 196, 204, 200, + 144, 216, 192, 3, 129, 62, 145, 208, 212, 133, + 162, 143, 148, 128, 182, 169, 0, 69, 70, 65, + 333, 58, 335, 0, 0, 0, 0, 67, 0, 0, + 63, 66, 0, 0, 59, 60, 68, 61, 0, 64, + 0, 0, 158, 0, 0, 145, 164, 147, 146, 0, + 0, 0, 160, 161, 159, 163, 0, 193, 0, 0, + 0, 0, 183, 0, 0, 0, 0, 0, 0, 173, + 0, 0, 0, 167, 168, 166, 171, 175, 174, 172, + 170, 185, 184, 186, 0, 201, 0, 197, 0, 0, + 139, 126, 138, 127, 95, 96, 97, 122, 98, 123, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 124, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 125, 0, 0, 137, 233, 140, + 0, 141, 0, 142, 136, 0, 229, 222, 220, 227, + 228, 226, 225, 231, 224, 223, 221, 230, 217, 0, + 205, 0, 0, 209, 0, 0, 213, 0, 0, 139, + 131, 0, 130, 0, 135, 149, 0, 334, 324, 325, + 0, 322, 0, 323, 0, 326, 240, 247, 246, 254, + 242, 0, 243, 327, 0, 332, 244, 245, 250, 248, + 329, 328, 331, 251, 0, 262, 0, 0, 0, 0, + 333, 58, 0, 335, 59, 234, 276, 60, 0, 0, + 0, 263, 0, 0, 252, 253, 0, 241, 249, 277, + 278, 321, 330, 0, 292, 293, 294, 295, 0, 288, + 289, 290, 291, 318, 319, 0, 0, 0, 0, 0, + 281, 282, 238, 236, 198, 206, 202, 218, 194, 239, + 0, 145, 210, 214, 187, 176, 0, 0, 195, 0, + 0, 0, 0, 188, 0, 0, 0, 0, 0, 180, + 178, 181, 179, 177, 190, 189, 191, 0, 203, 0, + 199, 0, 237, 145, 0, 219, 234, 235, 0, 234, + 0, 0, 284, 0, 0, 0, 286, 0, 207, 0, + 0, 211, 0, 0, 215, 274, 0, 266, 275, 269, + 0, 273, 0, 234, 267, 0, 234, 0, 0, 285, + 0, 0, 0, 287, 334, 324, 0, 0, 326, 0, + 320, 0, 310, 0, 0, 0, 280, 0, 279, 0, + 336, 0, 94, 256, 259, 0, 95, 262, 98, 123, + 100, 101, 65, 105, 106, 58, 107, 110, 63, 66, + 59, 234, 60, 68, 113, 61, 115, 64, 117, 118, + 263, 120, 121, 125, 0, 87, 0, 0, 89, 93, + 91, 77, 90, 92, 0, 88, 76, 257, 255, 133, + 134, 139, 0, 132, 0, 309, 0, 296, 297, 0, + 308, 0, 0, 0, 299, 304, 302, 305, 0, 0, + 303, 304, 0, 300, 0, 301, 258, 307, 0, 258, + 306, 0, 311, 312, 0, 258, 313, 314, 0, 0, + 315, 0, 0, 0, 316, 317, 151, 150, 0, 0, + 0, 283, 0, 0, 0, 298, 271, 264, 0, 272, + 268, 0, 270, 260, 0, 261, 265, 81, 0, 0, + 85, 71, 0, 73, 83, 0, 74, 84, 86, 75, + 82, 72, 0, 78, 155, 153, 157, 154, 152, 156, + 2, 5, 0, 7, 6, 0, 1, 79, 56, 57, + 0, 0, 0, 9, 10, 0, 11, 12, 0, 13, + 0, 0, 14, 0, 19, 20, 80, 0, 15, 16, + 0, 17, 18, 8, 22, 0, 4, 0, 29, 54, + 0, 0, 59, 27, 60, 30, 23, 0, 0, 55, + 0, 39, 38, 37, 0, 0, 48, 0, 49, 0, + 52, 53, 0, 0, 0, 46, 0, 47, 0, 50, + 51, 45, 40, 41, 0, 0, 0, 0, 43, 44, + 42, 28, 24, 0, 33, 34, 0, 35, 36, 258, + 0, 32, 95, 262, 98, 123, 100, 101, 65, 105, + 106, 58, 107, 110, 63, 66, 59, 234, 60, 68, + 113, 61, 115, 64, 117, 118, 263, 120, 121, 125, + 62, 0, 25, 0, 31, 26, 337}; const int QmlJSGrammar::goto_default [] = { - 4, 495, 352, 190, 494, 525, 490, 493, 492, 15, - 524, 534, 536, 535, 614, 527, 582, 583, 185, 189, - 191, 188, 195, 552, 563, 562, 194, 226, 23, 468, - 467, 350, 349, 6, 348, 351, 101, 19, 14, 139, - 21, 10, 138, 16, 22, 51, 20, 5, 25, 24, - 263, 12, 257, 7, 253, 9, 255, 8, 254, 17, - 261, 18, 262, 11, 256, 252, 293, 405, 258, 259, - 196, 187, 186, 198, 227, 197, 202, 223, 224, 354, - 353, 225, 457, 456, 315, 316, 459, 318, 458, 317, - 413, 417, 420, 416, 415, 435, 436, 179, 193, 175, - 178, 192, 200, 199, 0}; + 4, 496, 353, 191, 495, 526, 491, 494, 493, 15, + 525, 535, 537, 536, 611, 528, 186, 190, 192, 196, + 553, 564, 563, 195, 227, 23, 469, 468, 351, 350, + 6, 349, 352, 102, 19, 14, 140, 21, 10, 139, + 16, 22, 52, 20, 5, 25, 24, 264, 12, 258, + 7, 254, 9, 256, 8, 255, 17, 262, 18, 263, + 11, 257, 253, 294, 406, 259, 260, 197, 188, 187, + 199, 228, 198, 203, 224, 225, 189, 355, 354, 226, + 458, 457, 316, 317, 460, 319, 459, 318, 414, 418, + 421, 417, 416, 436, 437, 180, 194, 176, 179, 193, + 201, 200, 0}; const int QmlJSGrammar::action_index [] = { - 236, 824, 1879, -3, 176, 80, -95, 102, 36, -14, - 266, -95, 337, 90, -95, -95, 528, 100, 78, 344, - 220, -95, -95, -95, 565, 177, 824, -95, -95, -95, - 209, -95, 1697, 1083, 824, 824, 824, 740, 824, -95, - -95, 824, 824, -95, -95, -95, -95, 824, -95, 824, - 824, -95, 824, 824, 136, 183, -95, -95, 824, 824, - 824, -95, -95, -95, 146, 824, 342, 824, 824, 690, - 824, 565, 824, 824, 824, 824, 824, 824, 156, 824, - 824, 824, 134, 124, 84, 232, 255, 261, 260, 218, - 487, 472, 565, 824, 49, 824, 73, 1606, 824, 824, + 208, 808, 1863, 61, 100, 76, -95, 95, 59, 54, + 261, -95, 405, 86, -95, -95, 641, 91, 67, 187, + 200, -95, -95, -95, 446, 206, 808, -95, -95, -95, + 188, -95, 1681, 1412, 808, 808, 808, -95, 724, 808, + -95, -95, 808, 808, -95, -95, -95, -95, 808, -95, + 808, 808, -95, 808, 808, 131, 212, -95, -95, 808, + 808, 808, -95, -95, -95, 157, 808, 405, 808, 808, + 808, 808, 471, 808, 808, 808, 808, 808, 808, 161, + 808, 808, 808, 112, 119, 117, 154, 178, 173, 234, + 233, 456, 549, 409, 808, 9, 808, 72, 1590, 808, + 808, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -95, 137, 824, -95, -95, 63, 35, - -95, 824, -95, -95, 824, -95, -95, -95, -95, -95, - -95, -95, -95, -95, -95, -95, -95, -95, 824, 38, - 824, 824, 70, 62, 824, -95, 1606, 824, 824, -95, - 104, -95, 37, -95, -95, 40, -95, 198, 67, 46, - -95, 168, -95, 45, 1970, -95, -95, -95, -95, -95, - 205, -95, -95, 44, -95, -95, -95, -95, -95, -95, - 1970, -95, -95, 375, -95, 427, 82, 1879, 32, 243, - 59, 53, 2152, 74, 824, -95, 76, 58, 824, 57, - -95, 65, 64, -95, -95, 300, -95, -95, -95, -95, - -95, -95, 79, -95, -95, -95, -95, 77, -95, -95, - -95, -95, -95, -95, 50, 68, 824, 110, 72, -95, - -95, 996, -95, 60, 34, -8, -95, 421, 71, 19, - 582, 61, 92, 420, 287, 249, 824, 304, 824, 824, - 824, 824, 394, 824, 824, 824, 824, 824, 308, 279, - 286, 293, 294, 379, 373, 493, 824, -5, 824, 66, - 824, -95, 657, 824, -95, 824, 54, 30, 824, 33, - 1879, -95, 824, 117, 1879, -95, 824, 69, 824, 824, - 94, 52, 824, -95, 75, 111, 56, -95, -95, 824, - -95, 278, 824, -95, 55, 824, -15, 1879, -95, 824, - 122, 1879, -95, -22, 305, -42, -27, 1970, -51, -95, - 1879, -95, 824, 113, 1879, -1, 1879, -95, 6, 3, - -45, -95, -95, 1879, -32, 409, 14, 424, 107, 824, - 1879, 2, -34, 318, 81, -35, 740, -4, -7, -95, - 912, -95, 0, -12, 21, 824, 41, 20, 824, 43, - 824, 16, 15, 824, -95, 1788, 31, -95, -95, -95, - -95, -95, -95, 824, -95, -95, -95, -95, 269, -95, - 824, 17, -95, 1879, -95, 86, -95, -95, 1879, -95, - 824, 103, 23, -95, 42, -95, 26, 112, 824, -95, - 28, 25, -95, -25, -95, 1879, -95, 101, 1879, -95, - 281, -95, -95, 109, 1879, 9, -95, -10, 11, -95, - 272, -17, 8, -95, -95, -95, -95, 824, 99, 1879, - -95, 824, 106, 1879, -95, 22, -95, 190, -95, -95, - 824, -95, -95, 229, -95, -95, -95, 105, 1257, -95, - -95, 1344, -95, -95, 1170, -95, -95, -95, -95, -95, - -95, 97, -95, -95, -95, -95, -95, -95, -95, -95, - -95, 468, -95, -39, 334, -95, -95, -95, -95, 201, - 359, 194, -95, -95, 88, -95, -95, 202, -95, 207, - 164, -95, 129, -95, -95, -95, 181, -95, -95, 91, - -95, -95, -95, -95, 121, -95, 491, -95, -95, -9, - 225, 170, -95, 7, -95, -95, 477, 264, -95, 126, - -95, -95, -95, 5, 144, -95, 824, -95, 188, -95, - -95, 4, 13, 158, -95, 824, -95, 180, -95, -95, - 1, 133, 27, -33, 155, 127, 163, -95, -95, -95, - -95, -95, 1428, -95, -95, -95, 329, -95, -95, 2061, - 1515, -95, 125, -95, -95, 398, 51, 384, 118, 824, - 1879, 18, 24, 328, 81, 29, 740, 48, 47, -95, - 912, -95, 39, -28, -2, 824, 12, -11, 824, 10, - 824, -20, -24, -13, 115, -95, 395, -95, -95, -95, - -95, -95, + -95, -95, -95, -95, -95, 139, 808, -95, -95, 66, + 23, -95, 808, -95, -95, 808, -95, -95, -95, -95, + -95, -95, -95, -95, -95, -95, -95, -95, -95, 808, + 33, 808, 808, 69, 57, 808, -95, 1590, 808, 808, + -95, 126, -95, 8, -95, -95, 29, -95, 186, 62, + 60, -95, 207, -95, 36, 1954, -95, -95, -95, -95, + -95, 205, -95, -95, 35, -95, -95, -95, -95, -95, + -95, 1954, -95, -95, 386, -95, 398, 77, 1863, 50, + 162, 78, 42, 2136, 73, 808, -95, 85, 48, 808, + 56, -95, 43, 39, -95, -95, 328, -95, -95, -95, + -95, -95, -95, 75, -95, -95, -95, -95, 84, -95, + -95, -95, -95, -95, -95, 38, 55, 808, 102, 79, + -95, -95, 892, -95, 175, 47, 34, -95, 324, 74, + 16, 551, 65, 68, 477, 278, 328, 808, 292, 808, + 808, 808, 808, 402, 808, 808, 808, 808, 808, 302, + 306, 303, 282, 307, 385, 477, 477, 808, -2, 808, + 71, 808, -95, 641, 808, -95, 808, 58, 63, 808, + 51, 1863, -95, 808, 147, 1863, -95, 808, 14, 808, + 808, 96, 92, 808, -95, 80, 105, 70, -95, -95, + 808, -95, 255, 808, -95, -58, 808, -39, 1863, -95, + 808, 120, 1863, -95, -20, 259, -47, -21, 1954, -36, + -95, 1863, -95, 808, 101, 1863, 11, 1863, -95, 15, + 3, -45, -95, -95, 1863, -54, 401, 2, 337, 116, + 808, 1863, 0, -32, 318, -1, -28, 724, 81, -5, + -95, 980, -95, 45, 19, 46, 808, 44, 17, 808, + 41, 808, 13, -8, 808, -95, 1772, 49, -95, -95, + -95, -95, -95, -95, 808, -95, -95, -95, -95, 272, + -95, 808, -13, -95, 1863, -95, 64, -95, -95, 1863, + -95, 808, 98, 4, -95, 25, -95, 31, 93, 808, + -95, 40, 37, -95, -12, -95, 1863, -95, 123, 1863, + -95, 288, -95, -95, 109, 1863, 20, -95, -4, 1, + -95, 328, -14, 21, -95, -95, -95, -95, 808, 115, + 1863, -95, 808, 125, 1863, -95, 12, -95, 185, -95, + -95, 808, -95, -95, 252, -95, -95, -95, 97, 1154, + -95, -95, 1067, -95, -95, 1241, -95, -95, -95, -95, + -95, -95, 94, -95, -95, -95, -95, -95, -95, -95, + -95, -95, 407, -95, -73, 376, -95, -95, -95, -95, + 179, 321, 198, -95, -95, 110, -95, -95, 227, -95, + 248, 228, -95, 89, -95, -95, -95, 219, -95, -95, + 103, -95, -95, -95, -95, 127, -95, 475, -95, -95, + -46, 168, 165, -95, -6, -95, -95, 500, 189, -95, + 158, -95, -95, -95, 32, 176, -95, 808, -95, 262, + -95, -95, 6, 10, 128, -95, 808, -95, 148, -95, + -95, 5, 145, 30, -3, 213, 177, 216, -95, -95, + -95, -95, -95, 1325, -95, -95, 327, -95, -95, 2045, + 1499, -95, 345, 26, 330, 82, 808, 1863, 28, 22, + 310, 52, 27, 584, 81, 53, -95, 980, -95, 24, + -31, -7, 808, 7, -9, 808, 18, 808, -10, -19, + -15, 111, -95, 334, -95, -95, -95, - -105, 21, 23, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -45, -105, -105, -105, - -105, -105, -105, -105, -105, -105, 82, -105, -105, -105, - 35, -105, -105, 31, 33, 179, 161, 176, 165, -105, - -105, 183, 182, -105, -105, -105, -105, 140, -105, 143, - 139, -105, 159, 135, -105, -105, -105, -105, 156, 155, - 152, -105, -105, -105, -105, 90, -105, 126, 128, 130, - 160, -105, 169, 115, 87, 89, 124, 97, -105, 73, - 76, 39, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, 168, -105, 108, -105, 80, 74, 70, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, 62, -105, -105, -105, -105, - -105, 55, -105, -105, 66, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, 100, -105, - 148, -31, -105, -105, -33, -105, 206, 37, 103, -105, - -105, -105, -105, -105, -105, -105, -105, 22, -105, -105, - -105, 19, -105, -105, 28, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - 91, -105, -105, 64, -105, 50, -105, 41, -105, 43, - -105, -105, -105, -105, 54, -105, -105, -105, 42, 67, - -105, -105, -105, -105, -105, 4, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, 34, -105, -105, -105, - -105, 107, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, 17, 197, -105, 230, 234, - 242, 211, -105, 122, 116, 105, 96, 78, -105, -105, - -105, -105, -105, -105, -105, -105, 188, -105, 215, -105, - 214, -105, -105, 203, -105, 153, -105, -105, 273, -105, - 5, -105, 3, -105, 12, -105, 217, -105, 223, 190, - -105, -105, 187, -105, -105, -105, -105, -105, -105, 238, - -105, 129, 186, -105, -105, 189, -105, 52, -105, 53, - -105, 56, -105, -105, 137, -105, -105, 98, -105, -105, - 40, -105, 45, -105, 44, -105, 59, -105, -105, -105, - -105, -105, -105, 61, -105, 57, -105, 60, -105, 109, - 68, -105, -105, 46, -105, -105, 150, -105, -105, -105, - 29, -105, -105, -105, -105, 0, -105, 32, 86, -105, - 123, -105, -105, -6, -105, -26, -105, -105, -105, -105, - -105, -105, -105, -24, -105, -105, -105, -105, -105, -105, - 95, -105, -105, 16, -105, -105, -105, -105, 2, -105, - 8, -105, -105, -105, -105, -105, -19, -105, 75, -105, - -38, -105, -105, -105, -105, -17, -105, -105, -30, -105, - -105, -105, -105, -105, -105, -58, -105, -105, 58, -105, - 51, -105, 49, -105, -105, -105, -105, 171, -105, 72, - -105, 65, -105, 63, -105, -105, -105, -105, -105, -105, - 38, -105, -105, 184, -105, -105, -105, -105, 47, -105, - -105, 147, -105, -105, 48, -105, -105, -105, -105, -105, - -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, 88, -105, 71, 85, -105, -105, -105, -105, -105, - -105, 1, -105, -105, -105, -105, -105, -4, -105, 6, - -105, -105, -105, -105, -105, -105, 7, -105, -105, -105, - -105, -105, -105, -105, -105, -105, 369, -105, -105, -105, - 10, -105, -105, -105, -105, -105, 278, -105, -105, -22, - -105, -105, -105, -105, -105, -105, 69, -105, -105, -105, - -105, -105, -105, -105, -105, 9, -105, -105, -105, -105, - -105, 24, -105, -105, 11, 18, 25, -105, -105, -105, - -105, -105, 290, -105, -105, -105, 36, -105, -105, -105, - 210, -105, -105, -105, -105, 30, -105, 26, -105, 79, - 27, -105, -105, 13, -105, -105, 77, -105, -105, -105, - 20, -105, -105, -105, -105, 14, -105, 15, 117, -105, - 104, -105, -105, -105, -105, -105, 81, -105, -105, -105, - -105, -105}; + -103, 37, 13, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -55, -103, -103, -103, + -103, -103, -103, -103, -103, -103, 89, -103, -103, -103, + 24, -103, -103, 6, 15, 92, 100, -103, 154, 66, + -103, -103, 86, 143, -103, -103, -103, -103, 152, -103, + 144, 140, -103, 134, 135, -103, -103, -103, -103, 161, + 170, 176, -103, -103, -103, -103, 174, -103, 169, 153, + 162, 167, -103, 128, 126, 112, 116, 119, 113, -103, + 111, 104, 110, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, 63, -103, 120, -103, 88, 77, + 57, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, 28, -103, -103, -103, + -103, -103, 31, -103, -103, 36, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, 157, + -103, 125, -24, -103, -103, -14, -103, 210, 27, 160, + -103, -103, -103, -103, -103, -103, -103, -103, 8, -103, + -103, -103, -5, -103, -103, 74, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, 94, -103, -103, 44, -103, 35, -103, 81, -103, + 61, -103, -103, -103, -103, 75, -103, -103, -103, 4, + -7, -103, -103, -103, -103, -103, 26, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, 68, -103, -103, + -103, -103, 90, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, 70, 220, -103, 208, + 231, 230, 234, -103, 101, 82, 60, 76, 79, -103, + -103, -103, -103, -103, -103, -103, -103, 211, -103, 194, + -103, 192, -103, -103, 204, -103, 166, -103, -103, 197, + -103, 23, -103, -1, -103, 9, -103, 180, -103, 181, + 223, -103, -103, 227, -103, -103, -103, -103, -103, -103, + 184, -103, 93, 98, -103, -103, 108, -103, 83, -103, + 78, -103, 40, -103, -103, 109, -103, -103, 102, -103, + -103, 41, -103, 43, -103, 52, -103, 62, -103, -103, + -103, -103, -103, -103, 55, -103, 50, -103, 51, -103, + 107, 49, -103, -103, 73, -103, -103, 154, -103, -103, + -103, 64, -103, -103, -103, -103, 16, -103, 12, 147, + -103, 103, -103, -103, -4, -103, 0, -103, -103, -103, + -103, -103, -103, -103, 7, -103, -103, -103, -103, -103, + -103, 187, -103, -103, 25, -103, -103, -103, -103, 71, + -103, 65, -103, -103, -103, -103, -103, -44, -103, 46, + -103, -34, -103, -103, -103, -103, -21, -103, -103, -45, + -103, -103, -103, -103, -103, -103, -32, -103, -103, 53, + -103, 56, -103, 47, -103, -103, -103, -103, 42, -103, + 45, -103, 38, -103, 48, -103, -103, -103, -103, -103, + -103, 22, -103, -103, 124, -103, -103, -103, -103, 59, + -103, -103, 137, -103, -103, 54, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, 248, -103, -3, 114, -103, -103, -103, -103, + -103, -103, 5, -103, -103, -103, -103, -103, -8, -103, + 85, -103, -103, -103, -103, -103, -103, 11, -103, -103, + -103, -103, -103, -103, -103, -103, -103, 342, -103, -103, + -103, 29, -103, -103, -103, -103, -103, 273, -103, -103, + 3, -103, -103, -103, -103, -103, -103, 18, -103, -103, + -103, -103, -103, -103, -103, -103, 21, -103, -103, -103, + -103, -103, 2, -103, -103, 20, 14, 30, -103, -103, + -103, -103, -103, 284, -103, -103, -2, -103, -103, -103, + 222, -103, -9, -103, -6, -103, 96, 10, -103, -103, + 1, -103, -103, 80, -103, -103, -103, 72, -103, -103, + -103, -103, 69, -103, 58, 67, -103, 97, -103, -103, + -103, -103, -103, 84, -103, -103, -103}; const int QmlJSGrammar::action_info [] = { - -97, 342, 251, -115, 339, -118, 337, -96, 410, -107, - 395, 385, 451, 383, 334, 346, 447, -123, 336, -120, - -83, -126, 434, 397, 410, -107, 440, 568, -118, 438, - 424, 418, 425, 418, 544, 565, 560, 561, 393, 460, - 334, 434, 553, 442, 434, 327, -96, 418, -120, 491, - -123, 451, 447, 434, -97, -115, 414, 539, -126, 312, - 251, 266, 135, 306, 95, 342, 340, 266, 251, 164, - 288, 141, 158, 288, 65, 181, 177, 402, 184, 290, - 295, 403, 286, 408, 93, 491, 93, 329, -93, 342, - 434, 298, 319, 300, 410, 143, 306, 173, 135, 230, - 451, 447, 158, 65, 246, 135, 183, 135, 428, 135, - 0, 135, 135, 471, 135, 437, 325, 286, 135, 321, - 52, 135, 421, 616, 52, 135, 245, 95, 160, 438, - 135, 53, 161, 250, 249, 53, 509, 0, 241, 240, - 236, 235, 308, 243, 242, 135, 309, 407, 406, 506, - 505, 546, 521, 520, 526, 540, 540, 482, 58, 449, - 171, 472, 540, 412, 52, 555, 453, 422, 243, 242, - 248, 617, 322, 344, 52, 53, 621, 304, 56, 243, - 242, 79, 331, 80, 31, 53, 620, 619, 135, 57, - 514, 513, 31, 136, 81, 58, 135, 31, 463, 540, - 542, 542, 79, 59, 80, 547, 545, 542, 0, 60, - 31, 541, 541, 135, 0, 81, 0, 0, 541, 556, - 554, 43, 44, 31, 0, 518, 517, 31, 0, 43, - 44, 31, 58, 0, 43, 44, 31, 0, 31, 0, - 59, 559, 558, 79, 542, 80, 60, 43, 44, 550, - 549, 464, 462, 516, 31, 541, 81, 79, 31, 80, - 43, 44, 503, 502, 43, 44, 229, 228, 43, 44, - 81, 572, 31, 43, 44, 43, 44, 59, 31, 509, - 79, 97, 80, 60, 166, 79, 79, 80, 80, 135, - 501, 43, 44, 81, 0, 43, 44, 526, 81, 81, - 98, 31, 99, 167, 79, 400, 80, 31, 0, 43, - 44, 79, 79, 80, 80, 43, 44, 81, 79, 79, - 80, 80, 268, 269, 81, 81, 3, 2, 1, 31, - 0, 81, 81, 79, 31, 80, 0, 135, 43, 44, - 0, 0, 432, 431, 43, 44, 81, 31, 0, 270, - 271, 0, 0, 0, -337, 67, 68, 31, 0, 166, - 67, 68, 526, 31, -337, 0, 43, 44, 0, 0, - 0, 43, 44, 0, 509, 0, 0, 0, 167, 0, - 168, 0, 69, 70, 43, 44, 0, 69, 70, 0, - 229, 228, 0, 498, 43, 44, 273, 274, 0, 0, - 43, 44, 273, 274, 31, 275, 510, 0, 276, 0, - 277, 275, 0, 31, 276, 0, 277, 273, 274, 497, - 511, 508, 0, 0, 31, 0, 275, 31, 0, 276, - 0, 277, 0, 0, 0, 0, 234, 233, 31, 268, - 269, 43, 44, 273, 274, 239, 238, 0, 507, 0, - 43, 44, 275, 31, 498, 276, 31, 277, 0, 234, - 233, 43, 44, 0, 43, 44, 270, 271, 0, 0, - 234, 233, 0, 0, 0, 43, 44, 0, 0, 0, - 497, 0, 0, 0, 0, 239, 238, 529, 239, 238, - 43, 44, 0, 43, 44, 72, 73, 31, 0, 530, - 0, 529, 0, 74, 75, 0, 31, 76, 0, 77, - 72, 73, 0, 530, 0, 0, 273, 274, 74, 75, - 31, 0, 76, 0, 77, 275, 0, 498, 276, 0, - 277, 145, 570, 499, 43, 44, 498, 0, 0, 0, - 0, 146, 0, 531, 533, 147, 532, 0, 0, 0, - 498, 220, 0, 497, 148, 0, 149, 531, 533, 0, - 204, 0, 497, 0, 0, 220, 0, 150, 0, 151, - 56, 0, 0, 0, 204, 0, 497, 152, 0, 0, - 153, 57, 0, 0, 0, 145, 154, 0, 72, 73, - 0, 0, 155, 0, 0, 146, 74, 75, 0, 147, - 76, 0, 77, 0, 0, 0, 0, 156, 148, 0, - 149, 0, 0, 302, 0, 0, 0, 0, 0, 0, - 0, 150, 0, 151, 56, 0, 0, 0, 0, 0, - 0, 152, 0, 0, 153, 57, 0, 0, 0, 0, - 154, 0, 0, 0, 0, 0, 155, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 145, 156, 0, 0, 0, 0, 0, 0, 0, 0, - 146, 0, 0, 0, 147, 0, 0, 0, 0, 0, - 0, 0, 0, 148, 0, 149, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 150, 0, 151, 56, - 0, 26, 27, 28, 0, 0, 152, 0, 0, 153, - 57, 0, 30, 0, 0, 154, 0, 0, 0, 31, - 0, 155, 0, 32, 33, 0, 34, 0, 0, 0, - 35, 0, 36, 37, 38, 0, 156, 40, 0, 0, - 0, 41, 0, 42, 0, 0, 0, 0, 0, 0, - 0, 0, 27, 28, 0, 45, 43, 44, 0, 46, - 0, 47, 30, 49, 0, 50, 0, 0, 0, 31, - 39, 48, 29, 32, 33, 0, 34, 0, 0, 0, - 0, 0, 0, 37, 0, 0, 0, 40, 0, 0, + -114, 398, -93, 326, 252, 411, -89, -103, 343, -122, + 396, 386, 338, 337, -116, 492, 335, 452, -79, 340, + 540, 328, 384, 561, 435, -119, 448, 347, 452, 461, + 419, -92, 441, -122, 435, -103, 419, 415, 566, 554, + 439, 562, 335, 425, 426, 419, 443, 403, -119, 448, + 435, -116, -92, -114, 435, 411, 394, 569, 252, -89, + -93, 545, 287, 343, 165, 178, 136, 307, 174, 185, + 182, 159, 267, 66, 142, 452, 289, 296, 343, 448, + 404, 94, 291, 144, 411, 341, 252, 96, -111, 435, + 231, 247, 409, 159, 136, 287, 66, 320, 307, 313, + 616, 330, 136, 422, 0, 472, 136, 94, 0, 136, + 136, 301, 289, 322, 246, 438, 53, 161, 309, 613, + 184, 162, 310, 136, 299, 408, 407, 54, 136, 439, + 429, 136, 96, 136, 136, 556, 237, 236, 244, 243, + 251, 250, 510, 244, 243, 242, 241, 136, 423, 492, + 515, 514, 53, 473, 483, 136, 136, 53, 413, 53, + 527, 345, 249, 54, 522, 521, 323, 614, 54, 59, + 54, 507, 506, 57, 541, 450, 267, 244, 243, 80, + 332, 81, 172, 547, 58, 454, 80, 541, 81, 557, + 555, 31, 82, 464, 541, 137, 573, 31, 80, 82, + 81, 0, 167, 80, 510, 81, 541, 305, 0, 560, + 559, 82, 59, 136, 60, 31, 82, 31, 0, 543, + 61, 168, 527, 169, 59, 0, 0, 31, 44, 45, + 542, 80, 543, 81, 44, 45, 31, 548, 546, 543, + 504, 503, 31, 542, 82, 31, 465, 463, 31, 0, + 542, 543, 44, 45, 44, 45, 31, 60, 80, 80, + 81, 81, 542, 61, 44, 45, 230, 229, 502, 60, + 136, 82, 82, 44, 45, 61, 98, 31, 0, 44, + 45, 31, 44, 45, 31, 44, 45, 167, 31, 519, + 518, 0, 0, 44, 45, 99, 136, 100, 3, 2, + 1, 0, 0, 80, 0, 81, 168, 80, 401, 81, + 269, 270, 0, 0, 44, 45, 82, 517, 44, 45, + 82, 44, 45, 551, 550, 44, 45, 80, 80, 81, + 81, 80, 80, 81, 81, 136, 510, 271, 272, 31, + 82, 82, 269, 270, 82, 82, -333, 31, 0, 433, + 432, 0, 0, 0, -333, 0, 0, 31, 0, 31, + 527, 0, 0, 31, 0, 0, 31, 0, 511, 271, + 272, 0, 0, 0, 31, 0, 44, 45, 0, 0, + 0, 0, 512, 509, 44, 45, 0, 0, 230, 229, + 0, 240, 239, 499, 44, 45, 44, 45, 240, 239, + 44, 45, 0, 44, 45, 31, 235, 234, 274, 275, + 508, 44, 45, 0, 0, 31, 0, 276, 0, 498, + 277, 0, 278, 68, 69, 274, 275, 31, 0, 0, + 31, 0, 73, 74, 276, 499, 31, 277, 0, 278, + 75, 76, 44, 45, 77, 0, 78, 235, 234, 0, + 70, 71, 44, 45, 0, 0, 0, 0, 0, 240, + 239, 498, 235, 234, 44, 45, 499, 44, 45, 73, + 74, 0, 500, 44, 45, 0, 0, 75, 76, 73, + 74, 77, 0, 78, 0, 530, 0, 75, 76, 0, + 0, 77, 498, 78, 73, 74, 0, 531, 0, 0, + 274, 275, 75, 76, 31, 0, 77, 0, 78, 276, + 530, 0, 277, 0, 278, 0, 0, 0, 0, 0, + 0, 0, 531, 0, 0, 0, 0, 0, 0, 31, + 533, 0, 0, 0, 499, 0, 0, 0, 0, 0, + 0, 532, 534, 0, 0, 0, 0, 0, 0, 221, + 0, 0, 0, 0, 146, 571, 0, 0, 205, 499, + 498, 0, 0, 0, 147, 0, 532, 534, 148, 0, + 0, 0, 73, 74, 221, 0, 0, 149, 0, 150, + 75, 76, 303, 205, 77, 498, 78, 0, 0, 0, + 151, 0, 152, 57, 0, 0, 27, 28, 0, 0, + 153, 0, 0, 154, 58, 0, 30, 0, 0, 155, + 0, 0, 0, 31, 0, 156, 0, 32, 33, 0, + 34, 0, 0, 0, 0, 0, 0, 38, 0, 0, + 157, 41, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 0, 0, 0, 0, 46, + 44, 45, 0, 47, 147, 0, 0, 0, 148, 0, + 0, 0, 0, 0, 40, 49, 29, 149, 0, 150, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 151, 0, 152, 57, 0, 0, 0, 0, 0, 0, + 153, 0, 0, 154, 58, 0, 0, 0, 0, 155, + 0, 0, 0, 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 45, 43, 44, 0, 46, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 39, 48, 29, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 26, 27, 28, 0, 0, + 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, - 34, 0, 0, 0, 35, 0, 36, 37, 38, 0, - 0, 40, 0, 0, 0, 41, 0, 42, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, - 43, 44, 0, 46, 0, 47, 0, 49, 0, 50, - 0, 0, 0, 0, 39, 48, 29, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -116, + 34, 0, 0, 0, 0, 0, 0, 38, 0, 0, + 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 44, 45, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 49, 29, 0, 0, 0, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 26, + 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 32, 33, 0, 34, 0, 0, 0, 35, 0, + 36, 38, 39, 0, 0, 41, 0, 0, 0, 42, + 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 44, 45, 0, 47, 0, 48, + 0, 50, 0, 51, 0, 0, 0, 0, 40, 49, + 29, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, 34, 0, - 0, 0, 35, 0, 36, 37, 38, 0, 0, 40, - 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 45, 43, 44, - 0, 46, 0, 47, 0, 49, 0, 50, 0, 0, - 0, 0, 39, 48, 29, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 26, 27, 28, - 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, - 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, - 33, 0, 34, 0, 0, 0, 35, 0, 36, 37, - 38, 0, 0, 40, 0, 0, 0, 41, 0, 42, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 45, 43, 44, 0, 46, 0, 47, 0, 49, - 265, 50, 0, 0, 0, 0, 39, 48, 29, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 469, 0, 0, 26, 27, 28, 0, 0, 0, - 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 0, 32, 33, 0, 34, - 0, 0, 0, 35, 0, 36, 37, 38, 0, 0, - 40, 0, 0, 0, 41, 0, 42, 0, 0, 470, - 0, 0, 0, 0, 0, 0, 0, 0, 45, 43, - 44, 0, 46, 0, 47, 0, 49, 0, 50, 0, - 0, 0, 0, 39, 48, 29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 477, 0, + 0, 0, 35, 0, 36, 38, 39, 0, 0, 41, + 0, 0, 0, 42, 0, 43, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 44, 45, + 0, 47, 0, 48, 0, 50, 266, 51, 0, 0, + 0, 0, 40, 49, 29, 0, 0, 0, 37, 0, + 0, 0, 0, 0, 0, 0, 0, -112, 0, 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, 34, 0, 0, 0, - 35, 0, 36, 37, 38, 0, 0, 40, 0, 0, - 0, 41, 0, 42, 0, 0, 478, 0, 0, 0, - 0, 0, 0, 0, 0, 45, 43, 44, 0, 46, - 0, 47, 0, 49, 0, 50, 0, 0, 0, 0, - 39, 48, 29, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 477, 0, 0, 26, 27, + 35, 0, 36, 38, 39, 0, 0, 41, 0, 0, + 0, 42, 0, 43, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 46, 44, 45, 0, 47, + 0, 48, 0, 50, 0, 51, 0, 0, 0, 0, + 40, 49, 29, 0, 0, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 470, 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, 34, 0, 0, 0, 35, 0, 36, - 37, 38, 0, 0, 40, 0, 0, 0, 41, 0, - 42, 0, 0, 480, 0, 0, 0, 0, 0, 0, - 0, 0, 45, 43, 44, 0, 46, 0, 47, 0, - 49, 0, 50, 0, 0, 0, 0, 39, 48, 29, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 469, 0, 0, 26, 27, 28, 0, 0, + 38, 39, 0, 0, 41, 0, 0, 0, 42, 0, + 43, 0, 0, 476, 0, 0, 0, 0, 0, 0, + 0, 0, 46, 44, 45, 0, 47, 0, 48, 0, + 50, 0, 51, 0, 0, 0, 0, 40, 49, 29, + 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, + 0, 0, 478, 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, 0, - 34, 0, 0, 0, 35, 0, 36, 37, 38, 0, - 0, 40, 0, 0, 0, 41, 0, 42, 0, 0, - 475, 0, 0, 0, 0, 0, 0, 0, 0, 45, - 43, 44, 0, 46, 0, 47, 0, 49, 0, 50, - 0, 0, 0, 0, 39, 48, 29, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, - 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, - 30, 0, 0, 0, 0, 0, 0, 31, 211, 0, - 0, 579, 580, 0, 34, 0, 0, 0, 35, 0, - 36, 37, 38, 0, 0, 40, 0, 0, 0, 41, - 0, 42, 0, 0, 0, 0, 0, 0, 0, 215, - 0, 0, 0, 45, 43, 44, 0, 46, 0, 47, - 0, 49, 0, 50, 0, 0, 0, 0, 39, 48, - 29, 0, 206, 0, 581, 0, 0, 0, 0, 0, - 0, 0, 0, 469, 0, 0, 26, 27, 28, 0, + 34, 0, 0, 0, 35, 0, 36, 38, 39, 0, + 0, 41, 0, 0, 0, 42, 0, 43, 0, 0, + 481, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 44, 45, 0, 47, 0, 48, 0, 50, 0, 51, + 0, 0, 0, 0, 40, 49, 29, 0, 0, 0, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 478, + 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 31, 0, 0, 0, 32, 33, 0, 34, 0, 0, + 0, 35, 0, 36, 38, 39, 0, 0, 41, 0, + 0, 0, 42, 0, 43, 0, 0, 479, 0, 0, + 0, 0, 0, 0, 0, 0, 46, 44, 45, 0, + 47, 0, 48, 0, 50, 0, 51, 0, 0, 0, + 0, 40, 49, 29, 0, 0, 0, 37, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 32, 33, - 0, 34, 0, 0, 0, 35, 0, 36, 37, 38, - 0, 0, 40, 0, 0, 0, 41, 0, 42, 0, - 0, 470, 0, 0, 498, 0, 0, 0, 0, 0, - 45, 43, 44, 0, 46, 0, 47, 0, 49, 0, - 50, 0, 0, 0, 0, 39, 48, 29, 0, 0, - 497, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 103, 104, 105, 0, 0, 107, 109, 110, 0, 0, - 111, 0, 112, 0, 0, 0, 114, 115, 116, 0, - 0, 0, 0, 0, 0, 31, 117, 118, 119, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, - 0, 0, 43, 44, 124, 125, 126, 0, 128, 129, - 130, 131, 132, 133, 0, 0, 121, 127, 113, 106, - 108, 122, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 103, 104, 105, 0, 0, 107, 109, 110, 0, - 0, 111, 0, 112, 0, 0, 0, 114, 115, 116, - 0, 0, 0, 0, 0, 0, 387, 117, 118, 119, + 0, 0, 0, 0, 31, 212, 0, 0, 579, 580, + 0, 34, 0, 0, 0, 35, 0, 36, 38, 39, + 0, 0, 41, 0, 0, 0, 42, 0, 43, 0, + 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, + 46, 44, 45, 0, 47, 0, 48, 0, 50, 0, + 51, 0, 0, 0, 0, 40, 49, 29, 0, 0, + 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, + 470, 0, 0, 26, 27, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 32, 33, 0, 34, 0, + 0, 0, 35, 0, 36, 38, 39, 0, 0, 41, + 0, 0, 0, 42, 0, 43, 0, 0, 471, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 44, 45, + 0, 47, 0, 48, 0, 50, 0, 51, 0, 0, + 0, 0, 40, 49, 29, 0, 0, 0, 37, 0, + 0, 0, 0, 0, 0, 0, 0, 470, 0, 0, + 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, + 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 32, 33, 0, 34, 0, 0, 0, 35, + 0, 36, 38, 39, 0, 0, 41, 0, 0, 0, + 42, 0, 43, 0, 0, 471, 0, 0, 499, 0, + 0, 0, 0, 0, 46, 44, 45, 0, 47, 0, + 48, 0, 50, 0, 51, 0, 0, 0, 0, 40, + 49, 29, 0, 0, 498, 37, 0, 0, 0, 0, + 0, 0, 0, 0, 104, 105, 106, 0, 0, 108, + 110, 111, 0, 0, 112, 0, 113, 0, 0, 0, + 115, 116, 117, 0, 0, 0, 0, 0, 0, 31, + 118, 119, 120, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, + 0, 0, 0, 0, 0, 0, 44, 45, 125, 126, + 127, 0, 129, 130, 131, 132, 133, 134, 0, 0, + 122, 128, 114, 107, 109, 123, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 104, 105, 106, 0, 0, + 108, 110, 111, 0, 0, 112, 0, 113, 0, 0, + 0, 115, 116, 117, 0, 0, 0, 0, 0, 0, + 388, 118, 119, 120, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 121, 0, 0, 0, 389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 120, 0, 0, 0, 388, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, - 0, 0, 392, 389, 391, 124, 125, 126, 0, 128, - 129, 130, 131, 132, 133, 0, 0, 121, 127, 113, - 106, 108, 122, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 103, 104, 105, 0, 0, 107, 109, 110, - 0, 0, 111, 0, 112, 0, 0, 0, 114, 115, - 116, 0, 0, 0, 0, 0, 0, 387, 117, 118, - 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 120, 0, 0, 0, 388, 0, 0, 0, 0, - 0, 0, 0, 390, 0, 0, 0, 123, 0, 0, - 0, 0, 0, 392, 389, 391, 124, 125, 126, 0, - 128, 129, 130, 131, 132, 133, 0, 0, 121, 127, - 113, 106, 108, 122, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 203, 0, 0, 0, 0, 205, 0, - 26, 27, 28, 207, 0, 0, 0, 0, 0, 0, - 208, 30, 0, 0, 0, 0, 0, 0, 210, 211, - 0, 0, 212, 33, 0, 34, 0, 0, 0, 35, - 0, 36, 37, 38, 0, 0, 40, 0, 0, 0, - 41, 0, 42, 0, 0, 0, 0, 0, 214, 0, - 215, 0, 0, 0, 45, 213, 216, 217, 46, 218, - 47, 219, 49, 220, 50, 221, 222, 0, 0, 39, - 48, 29, 204, 206, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 203, 0, 0, 0, 0, 205, - 0, 26, 27, 28, 207, 0, 0, 0, 0, 0, - 0, 208, 209, 0, 0, 0, 0, 0, 0, 210, - 211, 0, 0, 212, 33, 0, 34, 0, 0, 0, - 35, 0, 36, 37, 38, 0, 0, 40, 0, 0, - 0, 41, 0, 42, 0, 0, 0, 0, 0, 214, - 0, 215, 0, 0, 0, 45, 213, 216, 217, 46, - 218, 47, 219, 49, 220, 50, 221, 222, 0, 0, - 39, 48, 29, 204, 206, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 585, 104, 105, 0, 0, - 587, 109, 589, 27, 28, 590, 0, 112, 0, 0, - 0, 114, 592, 593, 0, 0, 0, 0, 0, 0, - 594, 595, 118, 119, 212, 33, 0, 34, 0, 0, - 0, 35, 0, 36, 596, 38, 0, 0, 598, 0, - 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, - 600, 0, 215, 0, 0, 0, 602, 599, 601, 603, - 604, 605, 47, 607, 608, 609, 610, 611, 612, 0, - 0, 597, 606, 591, 586, 588, 122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 355, 104, 105, 0, - 0, 357, 109, 359, 27, 28, 360, 0, 112, 0, - 0, 0, 114, 362, 363, 0, 0, 0, 0, 0, - 0, 364, 365, 118, 119, 212, 33, 0, 34, 0, - 0, 0, 35, 0, 36, 366, 38, 0, 0, 368, - 0, 0, 0, 41, 0, 42, 0, -262, 0, 0, - 0, 370, 0, 215, 0, 0, 0, 372, 369, 371, - 373, 374, 375, 47, 377, 378, 379, 380, 381, 382, - 0, 0, 367, 376, 361, 356, 358, 122, 0, 0, - 0, 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 0, 0, 393, 390, 392, 125, + 126, 127, 0, 129, 130, 131, 132, 133, 134, 0, + 0, 122, 128, 114, 107, 109, 123, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 104, 105, 106, 0, + 0, 108, 110, 111, 0, 0, 112, 0, 113, 0, + 0, 0, 115, 116, 117, 0, 0, 0, 0, 0, + 0, 388, 118, 119, 120, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 121, 0, 0, 0, 389, + 0, 0, 0, 0, 0, 0, 0, 391, 0, 0, + 0, 124, 0, 0, 0, 0, 0, 393, 390, 392, + 125, 126, 127, 0, 129, 130, 131, 132, 133, 134, + 0, 0, 122, 128, 114, 107, 109, 123, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, + 0, 0, 206, 0, 26, 27, 28, 208, 0, 0, + 0, 0, 0, 0, 209, 30, 0, 0, 0, 0, + 0, 0, 211, 212, 0, 0, 213, 33, 0, 34, + 0, 0, 0, 35, 0, 36, 38, 39, 0, 0, + 41, 0, 0, 0, 42, 0, 43, 0, 0, 0, + 0, 0, 215, 0, 216, 0, 0, 0, 46, 214, + 217, 218, 47, 219, 48, 220, 50, 221, 51, 222, + 223, 0, 0, 40, 49, 29, 205, 207, 0, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, + 0, 0, 0, 206, 0, 26, 27, 28, 208, 0, + 0, 0, 0, 0, 0, 209, 210, 0, 0, 0, + 0, 0, 0, 211, 212, 0, 0, 213, 33, 0, + 34, 0, 0, 0, 35, 0, 36, 38, 39, 0, + 0, 41, 0, 0, 0, 42, 0, 43, 0, 0, + 0, 0, 0, 215, 0, 216, 0, 0, 0, 46, + 214, 217, 218, 47, 219, 48, 220, 50, 221, 51, + 222, 223, 0, 0, 40, 49, 29, 205, 207, 0, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 582, + 105, 106, 0, 0, 584, 110, 586, 27, 28, 587, + 0, 113, 0, 0, 0, 115, 589, 590, 0, 0, + 0, 0, 0, 0, 591, 592, 119, 120, 213, 33, + 0, 34, 0, 0, 0, 35, 0, 36, 593, 39, + 0, 0, 595, 0, 0, 0, 42, 0, 43, 0, + 0, 0, 0, 0, 597, 0, 216, 0, 0, 0, + 599, 596, 598, 600, 601, 602, 48, 604, 605, 606, + 607, 608, 609, 0, 0, 594, 603, 588, 583, 585, + 123, 37, 0, 0, 0, 0, 0, 0, 0, 0, + 356, 105, 106, 0, 0, 358, 110, 360, 27, 28, + 361, 0, 113, 0, 0, 0, 115, 363, 364, 0, + 0, 0, 0, 0, 0, 365, 366, 119, 120, 213, + 33, 0, 34, 0, 0, 0, 35, 0, 36, 367, + 39, 0, 0, 369, 0, 0, 0, 42, 0, 43, + 0, -258, 0, 0, 0, 371, 0, 216, 0, 0, + 0, 373, 370, 372, 374, 375, 376, 48, 378, 379, + 380, 381, 382, 383, 0, 0, 368, 377, 362, 357, + 359, 123, 37, 0, 0, 0, 0, 0, 0, 0, + 0, - 165, 543, 163, 430, 409, 512, 303, 301, 386, 394, - 504, 411, 557, 455, 305, 515, 519, 430, 404, 551, - 569, 144, 176, 296, 13, 489, 314, 384, 182, 244, - 201, 180, 296, 433, 567, 237, 481, 247, 439, 232, - 170, 566, 341, 244, 176, 430, 345, 564, 343, 429, - 433, 584, 333, 423, 328, 176, 330, 296, 332, 237, - 441, 347, 426, 396, 466, 454, 232, 443, 452, 237, - 244, 461, 548, 232, 450, 419, 444, 134, 427, 522, - 479, 476, 54, 0, 0, 433, 84, 0, 142, 100, - 496, 0, 618, 201, 496, 137, 523, 496, 500, 157, - 201, 0, 0, 140, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 398, 102, 54, 399, 0, 54, - 82, 54, 54, 83, 174, 54, 282, 174, 140, 54, - 54, 445, 54, 54, 401, 86, 140, 87, 314, 54, - 54, 66, 172, 54, 281, 89, 180, 54, 54, 446, - 260, 54, 54, 280, 174, 264, 296, 159, 54, 54, - 54, 96, 445, 85, 279, 54, 54, 54, 446, 54, - 278, 54, 88, 54, 448, 71, 474, 90, 54, 91, - 473, 64, 54, 54, 446, 488, 54, 398, 445, 296, - 399, 54, 296, 455, 231, 54, 338, 63, 54, 54, - 62, 61, 54, 54, 54, 55, 484, 162, 54, 92, - 485, 54, 54, 398, 323, 100, 399, 78, 0, 613, - 297, 615, 54, 94, 483, 54, 54, 487, 486, 0, - 292, 54, 0, 292, 335, 264, 264, 0, 264, 0, - 54, 102, 169, 466, 287, 264, 292, 0, 0, 267, - 0, 264, 313, 324, 54, 311, 326, 292, 54, 264, - 54, 285, 264, 264, 0, 264, 54, 465, 294, 289, - 0, 264, 0, 54, 0, 307, 296, 54, 264, 291, - 272, 292, 264, 310, 283, 54, 264, 496, 537, 0, - 264, 571, 284, 576, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 320, 528, 538, 0, 0, 573, 575, - 577, 574, 578, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 233, 513, 304, 238, 183, 523, 164, 431, 145, 434, + 177, 306, 245, 581, 505, 490, 166, 181, 482, 431, + 520, 549, 565, 544, 558, 302, 385, 405, 434, 570, + 171, 387, 430, 177, 567, 456, 467, 395, 552, 568, + 13, 453, 333, 342, 238, 449, 344, 451, 420, 428, + 455, 245, 462, 233, 346, 424, 427, 397, 138, 233, + 238, 143, 440, 444, 348, 442, 158, 297, 412, 445, + 334, 248, 431, 410, 434, 297, 202, 0, 297, 315, + 135, 331, 177, 245, 477, 329, 0, 141, 0, 480, + 0, 0, 0, 497, 516, 615, 202, 101, 0, 0, + 55, 297, 315, 55, 202, 281, 55, 55, 486, 446, + 0, 297, 0, 0, 399, 95, 55, 400, 181, 55, + 103, 282, 55, 497, 283, 524, 55, 280, 487, 55, + 261, 175, 55, 456, 484, 265, 55, 55, 175, 447, + 55, 55, 485, 55, 55, 447, 279, 55, 84, 175, + 55, 55, 55, 55, 85, 83, 55, 87, 90, 55, + 55, 88, 325, 475, 89, 55, 55, 474, 55, 297, + 97, 86, 327, 79, 55, 55, 324, 56, 65, 0, + 55, 163, 447, 55, 55, 488, 446, 55, 399, 446, + 141, 400, 55, 55, 489, 232, 173, 55, 339, 91, + 297, 55, 55, 62, 336, 466, 0, 55, 92, 55, + 55, 160, 63, 93, 55, 72, 55, 141, 64, 101, + 55, 55, 67, 402, 293, 265, 265, 0, 0, 265, + 298, 610, 293, 612, 55, 308, 0, 265, 311, 265, + 0, 0, 103, 170, 293, 290, 321, 0, 55, 265, + 0, 55, 467, 265, 292, 273, 265, 497, 501, 0, + 55, 300, 0, 293, 288, 265, 295, 293, 265, 268, + 55, 55, 265, 0, 55, 265, 265, 285, 284, 265, + 0, 286, 497, 538, 0, 312, 572, 576, 0, 314, + 0, 0, 0, 0, 0, 0, 529, 539, 0, 0, + 574, 575, 577, 578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 299, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 496, 537, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 528, 538, 0, 0, 0, + 0, 497, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 529, 539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -609,135 +600,116 @@ const int QmlJSGrammar::action_info [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0}; + 0, 0, 0, 0, 0}; const int QmlJSGrammar::action_check [] = { - 7, 36, 36, 7, 55, 7, 33, 7, 36, 7, - 55, 8, 36, 7, 36, 16, 36, 7, 60, 7, - 33, 7, 33, 55, 36, 7, 36, 60, 7, 20, - 55, 5, 7, 5, 29, 8, 29, 36, 7, 17, - 36, 33, 29, 60, 33, 60, 7, 5, 7, 88, - 7, 36, 36, 33, 7, 7, 33, 66, 7, 7, - 36, 1, 8, 2, 78, 36, 7, 1, 36, 7, - 78, 8, 2, 78, 1, 8, 36, 60, 33, 8, - 61, 7, 48, 7, 48, 88, 48, 31, 7, 36, - 33, 61, 17, 60, 36, 60, 2, 60, 8, 55, - 36, 36, 2, 1, 36, 8, 60, 8, 7, 8, - -1, 8, 8, 8, 8, 6, 61, 48, 8, 8, - 40, 8, 10, 8, 40, 8, 76, 78, 50, 20, - 8, 51, 54, 61, 62, 51, 15, -1, 61, 62, - 61, 62, 50, 61, 62, 8, 54, 61, 62, 61, - 62, 7, 61, 62, 33, 29, 29, 60, 12, 60, - 56, 56, 29, 60, 40, 7, 60, 55, 61, 62, - 60, 56, 61, 60, 40, 51, 0, 60, 42, 61, - 62, 25, 60, 27, 29, 51, 61, 62, 8, 53, - 61, 62, 29, 56, 38, 12, 8, 29, 8, 29, - 74, 74, 25, 57, 27, 61, 62, 74, -1, 63, - 29, 85, 85, 8, -1, 38, -1, -1, 85, 61, - 62, 66, 67, 29, -1, 61, 62, 29, -1, 66, - 67, 29, 12, -1, 66, 67, 29, -1, 29, -1, - 57, 61, 62, 25, 74, 27, 63, 66, 67, 61, - 62, 61, 62, 89, 29, 85, 38, 25, 29, 27, - 66, 67, 61, 62, 66, 67, 61, 62, 66, 67, - 38, 7, 29, 66, 67, 66, 67, 57, 29, 15, - 25, 15, 27, 63, 15, 25, 25, 27, 27, 8, - 89, 66, 67, 38, -1, 66, 67, 33, 38, 38, - 34, 29, 36, 34, 25, 36, 27, 29, -1, 66, - 67, 25, 25, 27, 27, 66, 67, 38, 25, 25, - 27, 27, 18, 19, 38, 38, 90, 91, 92, 29, - -1, 38, 38, 25, 29, 27, -1, 8, 66, 67, - -1, -1, 61, 62, 66, 67, 38, 29, -1, 45, - 46, -1, -1, -1, 36, 18, 19, 29, -1, 15, - 18, 19, 33, 29, 36, -1, 66, 67, -1, -1, - -1, 66, 67, -1, 15, -1, -1, -1, 34, -1, - 36, -1, 45, 46, 66, 67, -1, 45, 46, -1, - 61, 62, -1, 59, 66, 67, 23, 24, -1, -1, - 66, 67, 23, 24, 29, 32, 47, -1, 35, -1, - 37, 32, -1, 29, 35, -1, 37, 23, 24, 85, - 61, 62, -1, -1, 29, -1, 32, 29, -1, 35, - -1, 37, -1, -1, -1, -1, 61, 62, 29, 18, - 19, 66, 67, 23, 24, 61, 62, -1, 89, -1, - 66, 67, 32, 29, 59, 35, 29, 37, -1, 61, - 62, 66, 67, -1, 66, 67, 45, 46, -1, -1, - 61, 62, -1, -1, -1, 66, 67, -1, -1, -1, - 85, -1, -1, -1, -1, 61, 62, 10, 61, 62, - 66, 67, -1, 66, 67, 23, 24, 29, -1, 22, - -1, 10, -1, 31, 32, -1, 29, 35, -1, 37, - 23, 24, -1, 22, -1, -1, 23, 24, 31, 32, - 29, -1, 35, -1, 37, 32, -1, 59, 35, -1, - 37, 3, 55, 65, 66, 67, 59, -1, -1, -1, - -1, 13, -1, 66, 67, 17, 55, -1, -1, -1, - 59, 74, -1, 85, 26, -1, 28, 66, 67, -1, - 83, -1, 85, -1, -1, 74, -1, 39, -1, 41, - 42, -1, -1, -1, 83, -1, 85, 49, -1, -1, - 52, 53, -1, -1, -1, 3, 58, -1, 23, 24, - -1, -1, 64, -1, -1, 13, 31, 32, -1, 17, - 35, -1, 37, -1, -1, -1, -1, 79, 26, -1, - 28, -1, -1, 31, -1, -1, -1, -1, -1, -1, - -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, - -1, 49, -1, -1, 52, 53, -1, -1, -1, -1, - 58, -1, -1, -1, -1, -1, 64, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 79, -1, -1, -1, -1, -1, -1, -1, -1, - 13, -1, -1, -1, 17, -1, -1, -1, -1, -1, - -1, -1, -1, 26, -1, 28, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 39, -1, 41, 42, - -1, 11, 12, 13, -1, -1, 49, -1, -1, 52, - 53, -1, 22, -1, -1, 58, -1, -1, -1, 29, - -1, 64, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, 79, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, - -1, -1, 12, 13, -1, 65, 66, 67, -1, 69, - -1, 71, 22, 73, -1, 75, -1, -1, -1, 29, - 80, 81, 82, 33, 34, -1, 36, -1, -1, -1, - -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, + 7, 55, 7, 61, 36, 36, 7, 7, 36, 7, + 55, 8, 33, 60, 7, 88, 36, 36, 33, 55, + 66, 60, 7, 29, 33, 7, 36, 16, 36, 17, + 5, 7, 36, 7, 33, 7, 5, 33, 8, 29, + 20, 36, 36, 55, 7, 5, 60, 60, 7, 36, + 33, 7, 7, 7, 33, 36, 7, 60, 36, 7, + 7, 29, 48, 36, 7, 36, 8, 2, 60, 33, + 8, 2, 1, 1, 8, 36, 78, 61, 36, 36, + 7, 48, 8, 60, 36, 7, 36, 78, 7, 33, + 55, 36, 7, 2, 8, 48, 1, 17, 2, 7, + 0, 31, 8, 10, -1, 8, 8, 48, -1, 8, + 8, 60, 78, 8, 76, 6, 40, 50, 50, 8, + 60, 54, 54, 8, 61, 61, 62, 51, 8, 20, + 7, 8, 78, 8, 8, 7, 61, 62, 61, 62, + 61, 62, 15, 61, 62, 61, 62, 8, 55, 88, + 61, 62, 40, 56, 60, 8, 8, 40, 60, 40, + 33, 60, 60, 51, 61, 62, 61, 56, 51, 12, + 51, 61, 62, 42, 29, 60, 1, 61, 62, 25, + 60, 27, 56, 7, 53, 60, 25, 29, 27, 61, + 62, 29, 38, 8, 29, 56, 7, 29, 25, 38, + 27, -1, 15, 25, 15, 27, 29, 60, -1, 61, + 62, 38, 12, 8, 57, 29, 38, 29, -1, 74, + 63, 34, 33, 36, 12, -1, -1, 29, 66, 67, + 85, 25, 74, 27, 66, 67, 29, 61, 62, 74, + 61, 62, 29, 85, 38, 29, 61, 62, 29, -1, + 85, 74, 66, 67, 66, 67, 29, 57, 25, 25, + 27, 27, 85, 63, 66, 67, 61, 62, 89, 57, + 8, 38, 38, 66, 67, 63, 15, 29, -1, 66, + 67, 29, 66, 67, 29, 66, 67, 15, 29, 61, + 62, -1, -1, 66, 67, 34, 8, 36, 90, 91, + 92, -1, -1, 25, -1, 27, 34, 25, 36, 27, + 18, 19, -1, -1, 66, 67, 38, 89, 66, 67, + 38, 66, 67, 61, 62, 66, 67, 25, 25, 27, + 27, 25, 25, 27, 27, 8, 15, 45, 46, 29, + 38, 38, 18, 19, 38, 38, 36, 29, -1, 61, + 62, -1, -1, -1, 36, -1, -1, 29, -1, 29, + 33, -1, -1, 29, -1, -1, 29, -1, 47, 45, + 46, -1, -1, -1, 29, -1, 66, 67, -1, -1, + -1, -1, 61, 62, 66, 67, -1, -1, 61, 62, + -1, 61, 62, 59, 66, 67, 66, 67, 61, 62, + 66, 67, -1, 66, 67, 29, 61, 62, 23, 24, + 89, 66, 67, -1, -1, 29, -1, 32, -1, 85, + 35, -1, 37, 18, 19, 23, 24, 29, -1, -1, + 29, -1, 23, 24, 32, 59, 29, 35, -1, 37, + 31, 32, 66, 67, 35, -1, 37, 61, 62, -1, + 45, 46, 66, 67, -1, -1, -1, -1, -1, 61, + 62, 85, 61, 62, 66, 67, 59, 66, 67, 23, + 24, -1, 65, 66, 67, -1, -1, 31, 32, 23, + 24, 35, -1, 37, -1, 10, -1, 31, 32, -1, + -1, 35, 85, 37, 23, 24, -1, 22, -1, -1, + 23, 24, 31, 32, 29, -1, 35, -1, 37, 32, + 10, -1, 35, -1, 37, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + 55, -1, -1, -1, 59, -1, -1, -1, -1, -1, + -1, 66, 67, -1, -1, -1, -1, -1, -1, 74, + -1, -1, -1, -1, 3, 55, -1, -1, 83, 59, + 85, -1, -1, -1, 13, -1, 66, 67, 17, -1, + -1, -1, 23, 24, 74, -1, -1, 26, -1, 28, + 31, 32, 31, 83, 35, 85, 37, -1, -1, -1, + 39, -1, 41, 42, -1, -1, 12, 13, -1, -1, + 49, -1, -1, 52, 53, -1, 22, -1, -1, 58, + -1, -1, -1, 29, -1, 64, -1, 33, 34, -1, + 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, + 79, 47, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3, -1, -1, -1, -1, 65, + 66, 67, -1, 69, 13, -1, -1, -1, 17, -1, + -1, -1, -1, -1, 80, 81, 82, 26, -1, 28, + 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, + 49, -1, -1, 52, 53, -1, -1, -1, -1, 58, + -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, + 79, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, - 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, + 66, 67, -1, 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, + 86, -1, -1, -1, -1, -1, -1, -1, -1, 11, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, + -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, + 82, -1, -1, -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, - -1, -1, 80, 81, 82, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, - 74, 75, -1, -1, -1, -1, 80, 81, 82, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, + -1, 69, -1, 71, -1, 73, 74, 75, -1, -1, + -1, -1, 80, 81, 82, -1, -1, -1, 86, -1, + -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, - 80, 81, 82, -1, -1, -1, -1, -1, -1, -1, + 80, 81, 82, -1, -1, -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, @@ -746,7 +718,7 @@ const int QmlJSGrammar::action_check [] = { 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, @@ -755,129 +727,144 @@ const int QmlJSGrammar::action_check [] = { 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, - -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, - -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, - 82, -1, 84, -1, 86, -1, -1, -1, -1, -1, - -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + 86, -1, -1, -1, -1, -1, -1, -1, -1, 8, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, -1, + 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, + -1, 80, 81, 82, -1, -1, -1, 86, -1, -1, + -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, 56, -1, -1, 59, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, 81, 82, -1, -1, - 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, -1, 66, 67, 68, 69, 70, -1, 72, 73, - 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, - 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, - -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, - -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, - -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, - 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, - 83, 84, 85, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, - -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, - 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, - 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, - -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, - -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, - 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, - 82, 83, 84, 85, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, - 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, + -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + -1, 69, -1, 71, -1, 73, -1, 75, -1, -1, + -1, -1, 80, 81, 82, -1, -1, -1, 86, -1, + -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, - 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, -1, -1, 80, - 81, 82, 83, 84, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, - -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, - -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, - 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, - -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, -1, -1, - 80, 81, 82, 83, 84, -1, -1, -1, -1, -1, + 51, -1, 53, -1, -1, 56, -1, -1, 59, -1, + -1, -1, -1, -1, 65, 66, 67, -1, 69, -1, + 71, -1, 73, -1, 75, -1, -1, -1, -1, 80, + 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, + -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, + 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, + 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + -1, -1, -1, -1, -1, -1, 66, 67, 68, 69, + 70, -1, 72, 73, 74, 75, 76, 77, -1, -1, + 80, 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, - 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, + 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, - 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, - -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, - 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, -1, + 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 59, -1, -1, -1, -1, -1, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, - -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, + -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, - -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, - -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, + -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, + 68, 69, 70, -1, 72, 73, 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, 84, 85, -1, -1, - -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, + -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, + -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, + -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, + -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, -1, -1, 80, 81, 82, 83, 84, -1, 86, + -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, + -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, + -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, -1, -1, 80, 81, 82, 83, 84, -1, + 86, -1, -1, -1, -1, -1, -1, -1, -1, 4, + 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, + -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, + -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, -1, -1, 80, 81, 82, 83, 84, + 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, 55, -1, -1, -1, 59, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, -1, -1, 80, 81, 82, 83, + 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, - 33, 23, 33, 3, 2, 9, 3, 2, 34, 33, - 9, 3, 3, 9, 2, 9, 9, 3, 2, 9, - 9, 66, 9, 3, 3, 2, 9, 33, 9, 2, - 2, 9, 3, 18, 9, 9, 3, 3, 96, 9, - 3, 23, 2, 2, 9, 3, 2, 23, 3, 79, - 18, 15, 9, 91, 2, 9, 3, 3, 2, 9, - 9, 2, 79, 2, 33, 2, 9, 18, 3, 9, - 2, 33, 3, 9, 2, 94, 18, 3, 3, 8, - 33, 33, 43, -1, -1, 18, 47, -1, 33, 9, - 9, -1, 11, 2, 9, 33, 11, 9, 10, 33, - 2, -1, -1, 33, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 37, 35, 43, 40, -1, 43, - 47, 43, 43, 47, 45, 43, 48, 45, 33, 43, - 43, 45, 43, 43, 39, 48, 33, 48, 9, 43, - 43, 51, 39, 43, 48, 48, 9, 43, 43, 45, - 43, 43, 43, 48, 45, 48, 3, 57, 43, 43, - 43, 53, 45, 48, 48, 43, 43, 43, 45, 43, - 48, 43, 48, 43, 3, 49, 29, 49, 43, 49, - 33, 46, 43, 43, 45, 45, 43, 37, 45, 3, - 40, 43, 3, 9, 103, 43, 98, 45, 43, 43, - 45, 45, 43, 43, 43, 46, 45, 59, 43, 49, - 45, 43, 43, 37, 85, 9, 40, 48, -1, 9, - 67, 11, 43, 55, 45, 43, 43, 45, 45, -1, - 43, 43, -1, 43, 97, 48, 48, -1, 48, -1, - 43, 35, 36, 33, 56, 48, 43, -1, -1, 52, - -1, 48, 65, 67, 43, 65, 67, 43, 43, 48, - 43, 50, 48, 48, -1, 48, 43, 83, 65, 54, - -1, 48, -1, 43, -1, 58, 3, 43, 48, 65, - 50, 43, 48, 60, 50, 43, 48, 9, 10, -1, - 48, 13, 50, 3, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 26, 27, -1, -1, 18, 19, - 20, 21, 22, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 9, 9, 3, 9, 9, 8, 30, 3, 63, 16, + 9, 2, 2, 15, 9, 2, 30, 9, 3, 3, + 9, 3, 20, 20, 3, 2, 30, 2, 16, 9, + 3, 31, 77, 9, 20, 9, 30, 30, 9, 9, + 3, 3, 2, 2, 9, 3, 3, 2, 92, 3, + 2, 2, 30, 9, 2, 89, 77, 2, 30, 9, + 9, 30, 94, 16, 2, 9, 30, 3, 3, 16, + 9, 3, 3, 2, 16, 3, 2, -1, 3, 9, + 3, 3, 9, 2, 30, 2, -1, 30, -1, 30, + -1, -1, -1, 9, 9, 11, 2, 9, -1, -1, + 40, 3, 9, 40, 2, 45, 40, 40, 42, 42, + -1, 3, -1, -1, 34, 52, 40, 37, 9, 40, + 32, 45, 40, 9, 45, 11, 40, 45, 42, 40, + 40, 42, 40, 9, 42, 45, 40, 40, 42, 42, + 40, 40, 42, 40, 40, 42, 45, 40, 44, 42, + 40, 40, 40, 40, 44, 44, 40, 45, 45, 40, + 40, 45, 64, 26, 45, 40, 40, 30, 40, 3, + 50, 45, 64, 45, 40, 40, 83, 43, 43, -1, + 40, 56, 42, 40, 40, 42, 42, 40, 34, 42, + 30, 37, 40, 40, 42, 101, 36, 40, 96, 46, + 3, 40, 40, 42, 95, 81, -1, 40, 46, 40, + 40, 54, 42, 46, 40, 46, 40, 30, 42, 9, + 40, 40, 48, 36, 40, 45, 45, -1, -1, 45, + 64, 9, 40, 11, 40, 55, -1, 45, 57, 45, + -1, -1, 32, 33, 40, 51, 62, -1, 40, 45, + -1, 40, 30, 45, 62, 47, 45, 9, 10, -1, + 40, 64, -1, 40, 53, 45, 62, 40, 45, 49, + 40, 40, 45, -1, 40, 45, 45, 47, 47, 45, + -1, 47, 9, 10, -1, 62, 13, 3, -1, 62, + -1, -1, -1, -1, -1, -1, 23, 24, -1, -1, + 16, 17, 18, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 26, 27, -1, -1, -1, + -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -885,5 +872,5 @@ const int QmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1}; + -1, -1, -1, -1, -1}; diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h index da42f8c..c760564 100644 --- a/src/declarative/qml/parser/qmljsgrammar_p.h +++ b/src/declarative/qml/parser/qmljsgrammar_p.h @@ -2,7 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,7 +35,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -154,15 +154,15 @@ public: T_XOR = 78, T_XOR_EQ = 79, - ACCEPT_STATE = 621, - RULE_COUNT = 341, - STATE_COUNT = 622, + ACCEPT_STATE = 616, + RULE_COUNT = 337, + STATE_COUNT = 617, TERMINAL_COUNT = 95, - NON_TERMINAL_COUNT = 105, + NON_TERMINAL_COUNT = 103, - GOTO_INDEX_OFFSET = 622, - GOTO_INFO_OFFSET = 2247, - GOTO_CHECK_OFFSET = 2247 + GOTO_INDEX_OFFSET = 617, + GOTO_INFO_OFFSET = 2231, + GOTO_CHECK_OFFSET = 2231 }; static const char *const spell []; diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp index 08a424e..a1236d5 100644 --- a/src/declarative/qml/parser/qmljsparser.cpp +++ b/src/declarative/qml/parser/qmljsparser.cpp @@ -346,18 +346,6 @@ case 30: { } break; case 31: { - AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 33: { - AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 34: { if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { AST::UiObjectBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); @@ -372,7 +360,7 @@ case 34: { return false; // ### recover } } break; -case 35:case 36:case 37:case 38:case 39:case 40: +case 32:case 33:case 34:case 35: { AST::UiScriptBinding *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(3).Statement); @@ -380,35 +368,35 @@ case 35:case 36:case 37:case 38:case 39:case 40: sym(1).Node = node; } break; -case 41: +case 36: -case 42: { +case 37: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); break; } -case 44: { +case 39: { sym(1).Node = 0; } break; -case 45: { +case 40: { sym(1).Node = sym(1).UiParameterList->finish (); } break; -case 46: { +case 41: { AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).sval); node->identifierToken = loc(2); sym(1).Node = node; } break; -case 47: { +case 42: { AST::UiParameterList *node = makeAstNode (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; -case 48: { +case 43: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -418,7 +406,7 @@ case 48: { sym(1).Node = node; } break; -case 49: { +case 44: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); @@ -427,7 +415,7 @@ case 49: { sym(1).Node = node; } break; -case 51: { +case 46: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -436,7 +424,7 @@ case 51: { sym(1).Node = node; } break; -case 53: { +case 48: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -447,7 +435,7 @@ case 53: { sym(1).Node = node; } break; -case 55: { +case 50: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(3).sval, sym(5).Expression); node->propertyToken = loc(1); @@ -458,7 +446,7 @@ case 55: { sym(1).Node = node; } break; -case 57: { +case 52: { AST::UiPublicMember *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(4).sval, sym(6).Expression); node->isDefaultMember = true; @@ -471,76 +459,76 @@ case 57: { sym(1).Node = node; } break; -case 58: { +case 53: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 59: { +case 54: { sym(1).Node = makeAstNode(driver->nodePool(), sym(1).Node); } break; -case 60: -case 61: +case 55: +case 56: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 63: { +case 58: { QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 64: { +case 59: { QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 65: { +case 60: { AST::ThisExpression *node = makeAstNode (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 66: { +case 61: { AST::IdentifierExpression *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 67: { +case 62: { AST::NullExpression *node = makeAstNode (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 68: { +case 63: { AST::TrueLiteral *node = makeAstNode (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 69: { +case 64: { AST::FalseLiteral *node = makeAstNode (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 70: { +case 65: { AST::NumericLiteral *node = makeAstNode (driver->nodePool(), sym(1).dval, lexer->flags); node->literalToken = loc(1); sym(1).Node = node; } break; - -case 71: { +case 66: +case 67: { AST::StringLiteral *node = makeAstNode (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 72: { +case 68: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -551,7 +539,7 @@ case 72: { sym(1).Node = node; } break; -case 73: { +case 69: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -562,28 +550,28 @@ case 73: { sym(1).Node = node; } break; -case 74: { +case 70: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), (AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 75: { +case 71: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 76: { +case 72: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 77: { +case 73: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -592,7 +580,7 @@ case 77: { sym(1).Node = node; } break; -case 78: { +case 74: { AST::ArrayLiteral *node = makeAstNode (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -601,7 +589,7 @@ case 78: { sym(1).Node = node; } break; -case 79: { +case 75: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = makeAstNode (driver->nodePool(), @@ -613,7 +601,7 @@ case 79: { sym(1).Node = node; } break; -case 80: { +case 76: { AST::ObjectLiteral *node = makeAstNode (driver->nodePool(), sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); @@ -621,67 +609,67 @@ case 80: { sym(1).Node = node; } break; -case 81: { +case 77: { AST::NestedExpression *node = makeAstNode(driver->nodePool(), sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 82: { +case 78: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 83: { +case 79: { AST::UiQualifiedId *node = makeAstNode (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 84: { +case 80: { sym(1).Node = makeAstNode (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 85: { +case 81: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; -case 86: { +case 82: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 87: { +case 83: { AST::ElementList *node = makeAstNode (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 88: { +case 84: { AST::Elision *node = makeAstNode (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 89: { +case 85: { AST::Elision *node = makeAstNode (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 90: { +case 86: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 91: { +case 87: { AST::PropertyNameAndValueList *node = makeAstNode (driver->nodePool(), sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); @@ -689,36 +677,44 @@ case 91: { sym(1).Node = node; } break; -case 92: { +case 88: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 93: -case 94: { +case 89: +case 90: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 95: { +case 91: { AST::StringLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 96: { +case 92: { AST::NumericLiteralPropertyName *node = makeAstNode (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 97: { +case 93: { AST::IdentifierPropertyName *node = makeAstNode (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; +case 94: + +case 95: + +case 96: + +case 97: + case 98: case 99: @@ -772,33 +768,25 @@ case 122: case 123: case 124: - -case 125: - -case 126: - -case 127: - -case 128: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); } break; -case 133: { +case 129: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 134: { +case 130: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 135: { +case 131: { AST::NewMemberExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -806,384 +794,384 @@ case 135: { sym(1).Node = node; } break; -case 137: { +case 133: { AST::NewExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 138: { +case 134: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 139: { +case 135: { AST::CallExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 140: { +case 136: { AST::ArrayMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 141: { +case 137: { AST::FieldMemberExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).sval); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 142: { +case 138: { sym(1).Node = 0; } break; -case 143: { +case 139: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 144: { +case 140: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Expression); } break; -case 145: { +case 141: { AST::ArgumentList *node = makeAstNode (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 149: { +case 145: { AST::PostIncrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 150: { +case 146: { AST::PostDecrementExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 152: { +case 148: { AST::DeleteExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 153: { +case 149: { AST::VoidExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 154: { +case 150: { AST::TypeOfExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 155: { +case 151: { AST::PreIncrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 156: { +case 152: { AST::PreDecrementExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 157: { +case 153: { AST::UnaryPlusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 158: { +case 154: { AST::UnaryMinusExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 159: { +case 155: { AST::TildeExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 160: { +case 156: { AST::NotExpression *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 162: { +case 158: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 163: { +case 159: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 164: { +case 160: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 166: { +case 162: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 167: { +case 163: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 169: { +case 165: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 170: { +case 166: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 171: { +case 167: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 173: { +case 169: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 174: { +case 170: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 175: { +case 171: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 176: { +case 172: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 177: { +case 173: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 178: { +case 174: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 180: { +case 176: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 181: { +case 177: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 182: { +case 178: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 183: { +case 179: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 184: { +case 180: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 186: { +case 182: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 187: { +case 183: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 188: { +case 184: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 189: { +case 185: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 191: { +case 187: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 192: { +case 188: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 193: { +case 189: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 194: { +case 190: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 196: { +case 192: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 198: { +case 194: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 200: { +case 196: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 202: { +case 198: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 204: { +case 200: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 206: { +case 202: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 208: { +case 204: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 210: { +case 206: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 212: { +case 208: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 214: { +case 210: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 216: { +case 212: { AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1191,7 +1179,7 @@ case 216: { sym(1).Node = node; } break; -case 218: { +case 214: { AST::ConditionalExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1199,112 +1187,112 @@ case 218: { sym(1).Node = node; } break; -case 220: { +case 216: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 222: { +case 218: { AST::BinaryExpression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 223: { +case 219: { sym(1).ival = QSOperator::Assign; } break; -case 224: { +case 220: { sym(1).ival = QSOperator::InplaceMul; } break; -case 225: { +case 221: { sym(1).ival = QSOperator::InplaceDiv; } break; -case 226: { +case 222: { sym(1).ival = QSOperator::InplaceMod; } break; -case 227: { +case 223: { sym(1).ival = QSOperator::InplaceAdd; } break; -case 228: { +case 224: { sym(1).ival = QSOperator::InplaceSub; } break; -case 229: { +case 225: { sym(1).ival = QSOperator::InplaceLeftShift; } break; -case 230: { +case 226: { sym(1).ival = QSOperator::InplaceRightShift; } break; -case 231: { +case 227: { sym(1).ival = QSOperator::InplaceURightShift; } break; -case 232: { +case 228: { sym(1).ival = QSOperator::InplaceAnd; } break; -case 233: { +case 229: { sym(1).ival = QSOperator::InplaceXor; } break; -case 234: { +case 230: { sym(1).ival = QSOperator::InplaceOr; } break; -case 236: { +case 232: { AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 237: { +case 233: { sym(1).Node = 0; } break; -case 240: { +case 236: { AST::Expression *node = makeAstNode (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 241: { +case 237: { sym(1).Node = 0; } break; -case 258: { +case 254: { AST::Block *node = makeAstNode (driver->nodePool(), sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 259: { +case 255: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 260: { +case 256: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).StatementList, sym(2).Statement); } break; -case 261: { +case 257: { sym(1).Node = 0; } break; -case 262: { +case 258: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 264: { +case 260: { AST::VariableStatement *node = makeAstNode (driver->nodePool(), sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1312,76 +1300,76 @@ case 264: { sym(1).Node = node; } break; -case 265: { +case 261: { sym(1).ival = T_CONST; } break; -case 266: { +case 262: { sym(1).ival = T_VAR; } break; -case 267: { +case 263: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 268: { +case 264: { AST::VariableDeclarationList *node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 269: { +case 265: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 270: { +case 266: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 271: { +case 267: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 272: { +case 268: { AST::VariableDeclaration *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 273: { +case 269: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 274: { +case 270: { sym(1).Node = 0; } break; -case 276: { +case 272: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 277: { +case 273: { sym(1).Node = 0; } break; -case 279: { +case 275: { AST::EmptyStatement *node = makeAstNode (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 281: { +case 277: { AST::ExpressionStatement *node = makeAstNode (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 282: { +case 278: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1390,7 +1378,7 @@ case 282: { sym(1).Node = node; } break; -case 283: { +case 279: { AST::IfStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1398,7 +1386,7 @@ case 283: { sym(1).Node = node; } break; -case 285: { +case 281: { AST::DoWhileStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1408,7 +1396,7 @@ case 285: { sym(1).Node = node; } break; -case 286: { +case 282: { AST::WhileStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1416,7 +1404,7 @@ case 286: { sym(1).Node = node; } break; -case 287: { +case 283: { AST::ForStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1427,7 +1415,7 @@ case 287: { sym(1).Node = node; } break; -case 288: { +case 284: { AST::LocalForStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1440,7 +1428,7 @@ case 288: { sym(1).Node = node; } break; -case 289: { +case 285: { AST:: ForEachStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1450,7 +1438,7 @@ case 289: { sym(1).Node = node; } break; -case 290: { +case 286: { AST::LocalForEachStatement *node = makeAstNode (driver->nodePool(), sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1461,14 +1449,14 @@ case 290: { sym(1).Node = node; } break; -case 292: { +case 288: { AST::ContinueStatement *node = makeAstNode (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 294: { +case 290: { AST::ContinueStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1476,14 +1464,14 @@ case 294: { sym(1).Node = node; } break; -case 296: { +case 292: { AST::BreakStatement *node = makeAstNode (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 298: { +case 294: { AST::BreakStatement *node = makeAstNode (driver->nodePool(), sym(2).sval); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1491,14 +1479,14 @@ case 298: { sym(1).Node = node; } break; -case 300: { +case 296: { AST::ReturnStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 301: { +case 297: { AST::WithStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1506,7 +1494,7 @@ case 301: { sym(1).Node = node; } break; -case 302: { +case 298: { AST::SwitchStatement *node = makeAstNode (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1514,90 +1502,90 @@ case 302: { sym(1).Node = node; } break; -case 303: { +case 299: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 304: { +case 300: { AST::CaseBlock *node = makeAstNode (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 305: { +case 301: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClause); } break; -case 306: { +case 302: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); } break; -case 307: { +case 303: { sym(1).Node = 0; } break; -case 308: { +case 304: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 309: { +case 305: { AST::CaseClause *node = makeAstNode (driver->nodePool(), sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 310: { +case 306: { AST::DefaultClause *node = makeAstNode (driver->nodePool(), sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 311: -case 312: { +case 307: +case 308: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 313: { +case 309: { AST::LabelledStatement *node = makeAstNode (driver->nodePool(), sym(1).sval, sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 315: { +case 311: { AST::ThrowStatement *node = makeAstNode (driver->nodePool(), sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 316: { +case 312: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 317: { +case 313: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 318: { +case 314: { AST::TryStatement *node = makeAstNode (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 319: { +case 315: { AST::Catch *node = makeAstNode (driver->nodePool(), sym(3).sval, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1606,20 +1594,20 @@ case 319: { sym(1).Node = node; } break; -case 320: { +case 316: { AST::Finally *node = makeAstNode (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 322: { +case 318: { AST::DebuggerStatement *node = makeAstNode (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 323: { +case 319: { AST::FunctionDeclaration *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1630,7 +1618,7 @@ case 323: { sym(1).Node = node; } break; -case 324: { +case 320: { AST::FunctionExpression *node = makeAstNode (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (sym(2).sval) @@ -1642,56 +1630,56 @@ case 324: { sym(1).Node = node; } break; -case 325: { +case 321: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 326: { +case 322: { AST::FormalParameterList *node = makeAstNode (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 327: { +case 323: { sym(1).Node = 0; } break; -case 328: { +case 324: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 329: { +case 325: { sym(1).Node = 0; } break; -case 331: { +case 327: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 332: { +case 328: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElement); } break; -case 333: { +case 329: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 334: { +case 330: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).Statement); } break; -case 335: { +case 331: { sym(1).Node = makeAstNode (driver->nodePool(), sym(1).FunctionDeclaration); } break; -case 336: { +case 332: { sym(1).sval = 0; } break; -case 338: { +case 334: { sym(1).Node = 0; } break; diff --git a/src/declarative/qml/parser/qmljsparser_p.h b/src/declarative/qml/parser/qmljsparser_p.h index 9273039..6f36484 100644 --- a/src/declarative/qml/parser/qmljsparser_p.h +++ b/src/declarative/qml/parser/qmljsparser_p.h @@ -219,9 +219,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 72 +#define J_SCRIPT_REGEXPLITERAL_RULE1 68 -#define J_SCRIPT_REGEXPLITERAL_RULE2 73 +#define J_SCRIPT_REGEXPLITERAL_RULE2 69 QT_END_NAMESPACE -- cgit v0.12