diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-07-16 21:36:34 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-07-16 21:36:34 (GMT) |
commit | 6470f646d0815f67bab507c1362cdda775c42a6e (patch) | |
tree | 6389ca2728ec8b78294af60e20b918fdccdf88f1 /src | |
parent | 50f400ac20e918db1d0a6496003d953dedaba42a (diff) | |
parent | 3bd0062535aaa991fadf739f9362851afacb19eb (diff) | |
download | Qt-6470f646d0815f67bab507c1362cdda775c42a6e.zip Qt-6470f646d0815f67bab507c1362cdda775c42a6e.tar.gz Qt-6470f646d0815f67bab507c1362cdda775c42a6e.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src')
58 files changed, 5523 insertions, 3581 deletions
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/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(); } } 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<QmlAbstractAnimation *> { 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(); }; 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() 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/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<QFxItem *>* children READ children DESIGNABLE false) Q_PROPERTY(QmlList<QObject *>* 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<QObject *> *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<QmlState *>* states READ states DESIGNABLE false) Q_PROPERTY(QmlList<QmlTransition *>* 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<QFxTransform *>* 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<QString, QFxItem *> QmlChildren; 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 <QValidator> +#include <QApplication> +#include <QFontMetrics> + +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 <QTimer> //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<QValidator*>(d->control->validator()); +} + +void QFxLineEdit::setValidator(QObject* v) +{ + Q_D(QFxLineEdit); + QValidator* valid = qobject_cast<QValidator*>(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<QFxItem*>(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 <QGraphicsSceneMouseEvent> +#include <QIntValidator> + +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 <QPointer> +// +// 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<QmlComponent> cursorComponent; + QPointer<QFxItem> cursorItem; + + int oldSelectLength; + int oldHeight; + int oldWidth; + bool oldValidity; + int hscroll; + int oldScroll; + bool focused; + bool awesome; + +}; + +QT_END_NAMESPACE + +#endif + 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<AST::StringLiteral> (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<AST::ExpressionStatement> (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<AST::StringLiteral> (driver->nodePool(), sym(1).sval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 33: { - AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (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<AST::UiObjectBinding> (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<AST::UiScriptBinding> (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<AST::UiParameterList> (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<AST::UiParameterList> (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<AST::UiPublicMember> (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<AST::UiPublicMember> (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<AST::UiPublicMember> (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<AST::UiPublicMember> (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<AST::UiPublicMember> (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<AST::UiPublicMember> (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<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 59: { +case 54: { sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 60: -case 61: +case 55: +case 56: { AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (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<AST::ThisExpression> (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 66: { +case 61: { AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 67: { +case 62: { AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 68: { +case 63: { AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 69: { +case 64: { AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 70: { +case 65: { AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (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<AST::StringLiteral> (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<AST::ArrayLiteral> (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<AST::ArrayLiteral> (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<AST::ArrayLiteral> (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<AST::ArrayLiteral> (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<AST::ArrayLiteral> (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<AST::ObjectLiteral> (driver->nodePool(), @@ -613,7 +601,7 @@ case 79: { sym(1).Node = node; } break; -case 80: { +case 76: { AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (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<AST::NestedExpression>(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<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 83: { +case 79: { AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (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<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 85: { +case 81: { sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; -case 86: { +case 82: { AST::ElementList *node = makeAstNode<AST::ElementList> (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<AST::ElementList> (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<AST::Elision> (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 89: { +case 85: { AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 90: { +case 86: { AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (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<AST::PropertyNameAndValueList> (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<AST::IdentifierPropertyName> (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<AST::IdentifierPropertyName> (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<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 96: { +case 92: { AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 97: { +case 93: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (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<AST::ArrayMemberExpression> (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<AST::FieldMemberExpression> (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<AST::NewMemberExpression> (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<AST::NewExpression> (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 138: { +case 134: { AST::CallExpression *node = makeAstNode<AST::CallExpression> (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<AST::CallExpression> (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<AST::ArrayMemberExpression> (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<AST::FieldMemberExpression> (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<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); } break; -case 145: { +case 141: { AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (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<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 150: { +case 146: { AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 152: { +case 148: { AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 153: { +case 149: { AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 154: { +case 150: { AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 155: { +case 151: { AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 156: { +case 152: { AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 157: { +case 153: { AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 158: { +case 154: { AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 159: { +case 155: { AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 160: { +case 156: { AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 162: { +case 158: { AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::ConditionalExpression> (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<AST::ConditionalExpression> (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<AST::BinaryExpression> (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<AST::BinaryExpression> (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<AST::Expression> (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<AST::Expression> (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<AST::Block> (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<AST::StatementList> (driver->nodePool(), sym(1).Statement); } break; -case 260: { +case 256: { sym(1).Node = makeAstNode<AST::StatementList> (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<AST::VariableStatement> (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<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 268: { +case 264: { AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (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<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 270: { +case 266: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 271: { +case 267: { AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (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<AST::VariableDeclaration> (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<AST::EmptyStatement> (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 281: { +case 277: { AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 282: { +case 278: { AST::IfStatement *node = makeAstNode<AST::IfStatement> (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<AST::IfStatement> (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<AST::DoWhileStatement> (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<AST::WhileStatement> (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<AST::ForStatement> (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<AST::LocalForStatement> (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<AST::ForEachStatement> (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<AST::LocalForEachStatement> (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<AST::ContinueStatement> (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 294: { +case 290: { AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (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<AST::BreakStatement> (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 298: { +case 294: { AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (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<AST::ReturnStatement> (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<AST::WithStatement> (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<AST::SwitchStatement> (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<AST::CaseBlock> (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<AST::CaseBlock> (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<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); } break; -case 306: { +case 302: { sym(1).Node = makeAstNode<AST::CaseClauses> (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<AST::CaseClause> (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<AST::DefaultClause> (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<AST::LabelledStatement> (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<AST::LabelledStatement> (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<AST::ThrowStatement> (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<AST::TryStatement> (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<AST::TryStatement> (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<AST::TryStatement> (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<AST::Catch> (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<AST::Finally> (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 322: { +case 318: { AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 323: { +case 319: { AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (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<AST::FunctionExpression> (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<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 326: { +case 322: { AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (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<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 332: { +case 328: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); } break; -case 333: { +case 329: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 334: { +case 330: { sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); } break; -case 335: { +case 331: { sym(1).Node = makeAstNode<AST::FunctionSourceElement> (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 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<INTERFACE *>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE)); #define QML_DEFINE_EXTENDED_TYPE(TYPE, NAME, EXTENSION) \ - template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#NAME, #TYPE)); + template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(QML_FORCE_NAMESPACE #NAME, #TYPE)); #define QML_DEFINE_TYPE(TYPE, NAME) \ - template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#NAME, #TYPE)); + template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(QML_FORCE_NAMESPACE #NAME, #TYPE)); #define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE)); diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 857b07e..eecf8cd 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/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 478491f..40ffffe 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 @@ -181,6 +176,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: { @@ -291,7 +289,7 @@ struct QmlBasicScriptCompiler QmlParser::Object *context; QmlParser::Object *component; - QHash<QString, QPair<QmlParser::Object *, int> > ids; + QHash<QString, QmlParser::Object *> ids; bool compile(QmlJS::AST::Node *); @@ -445,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; @@ -588,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()); @@ -679,11 +668,7 @@ bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node) AST::BinaryExpression *expr = static_cast<AST::BinaryExpression *>(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; @@ -700,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; } @@ -823,7 +796,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 +808,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 +821,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c QObject *obj = qvariant_cast<QObject *>(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; @@ -913,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(); @@ -945,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; } 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<QString, QPair<QmlParser::Object *, int> > ids; + QHash<QString, QmlParser::Object *> 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..b0bc6e8 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<QmlError> 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,27 +142,26 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) 'A' <= name.at(2) && 'Z' >= name.at(2); } -#define COMPILE_EXCEPTION2(token, desc) \ - { \ - QString exceptionDescription; \ - QmlError error; \ - error.setUrl(output->url); \ - error.setLine(token->location.start.line); \ - error.setColumn(token->location.start.column); \ - QDebug d(&exceptionDescription); \ - d << desc; \ - error.setDescription(exceptionDescription.trimmed()); \ - exceptions << error; \ - return false; \ - } +/*! + Inserts an error into the QmlCompiler error list, and returns false + (failure). -#define COMPILE_EXCEPTION(desc) \ + \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; \ error.setUrl(output->url); \ - error.setLine(obj->location.start.line); \ - error.setColumn(obj->location.start.column); \ + error.setLine((token)->location.start.line); \ + error.setColumn((token)->location.start.column); \ QDebug d(&exceptionDescription); \ d << desc; \ error.setDescription(exceptionDescription.trimmed()); \ @@ -150,19 +169,28 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) 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); @@ -1687,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)) @@ -1797,14 +1856,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 +1889,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 +1934,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 +1950,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 +1978,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<QmlParser::Value*,BindingReference>::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<QString, IdReference> ids; + QHash<QString, QmlParser::Object *> ids; int parserStatusCount; int savedObjects; int pushedProperties; - QList<BindingReference> bindings; - QHash<QmlParser::Value *, int> bindingMap; - QList<AliasReference> aliases; + + QHash<QmlParser::Value *, BindingReference> bindings; + QList<QmlParser::Object *> aliasingObjects; QmlParser::Object *root; }; ComponentCompileState compileState; 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<QmlContextPrivate*>(ctxt->d_ptr)->startLine = d->cc->bytecode.at(d->start - 1).line; static_cast<QmlContextPrivate*>(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 b605869..5bc70bc 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); + } } } @@ -398,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/qmldom.cpp b/src/declarative/qml/qmldom.cpp index e3cb563..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; } @@ -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/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index acbeb26..a6f5b28 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 <QMetaProperty> #include <private/qmlengine_p.h> #include <private/qmlcontext_p.h> @@ -90,49 +92,6 @@ struct StaticQtMetaObject : public QObject { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; } }; - -struct QmlEngineStack { - QmlEngineStack(); - - QStack<QmlEngine *> mainThreadEngines; - QThread *mainThread; - - QThreadStorage<QStack<QmlEngine *> *> storage; - - QStack<QmlEngine *> *engines(); -}; - -Q_GLOBAL_STATIC(QmlEngineStack, engineStack); - -QmlEngineStack::QmlEngineStack() -: mainThread(0) -{ -} - -QStack<QmlEngine *> *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<QmlEngine *> *engines = 0; - if (QThread::currentThread() == mainThread) { - engines = &mainThreadEngines; - } else { - engines = storage.localData(); - if (!engines) { - engines = new QStack<QmlEngine *>; - 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 +254,6 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, return QScriptValue(); } -void QmlEnginePrivate::contextActivated(QmlContext *) -{ - Q_Q(QmlEngine); - QmlEngineStack *stack = engineStack(); - if (!stack) - return; - QStack<QmlEngine *> *engines = stack->engines(); - if (engines) - engines->push(q); -} - -void QmlEnginePrivate::contextDeactivated(QmlContext *) -{ - QmlEngineStack *stack = engineStack(); - if (!stack) - return; - QStack<QmlEngine *> *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 +404,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 +576,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<QmlEngine *> *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 +660,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); @@ -1113,11 +995,73 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object, } +struct QmlEngine::ImportedNamespace { + QStringList urls; + QStringList versions; + QList<bool> isLibrary; + + QUrl find(const QString& type) const + { + for (int i=0; i<urls.count(); ++i) { + QUrl url = QUrl(urls.at(i) + QLatin1String("/") + type + QLatin1String(".qml")); + QString version = 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(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==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; i<urls.count(); ++i) { + QByteArray version = versions.at(i).toLatin1(); + QByteArray qt = urls.at(i).toLatin1(); + if (version.isEmpty()) + qt += "/"; + else + qt += "/" + version + "/"; + qt += type; + QmlType *t = QmlMetaType::qmlType(qt); + if (found) *found = qt; + if (t) return t; + } + return 0; + } +}; + class QmlImportsPrivate { public: - bool add(const QString& uri, const QString& prefix, const QString& version, QmlEngine::ImportType importType, const QStringList& importPath) + bool add(const QUrl& base, const QString& uri, const QString& prefix, const QString& version, QmlEngine::ImportType importType, const QStringList& importPath) { - TypeSet *s; + QmlEngine::ImportedNamespace *s; if (prefix.isEmpty()) { if (importType == QmlEngine::LibraryImport && version.isEmpty()) { // unversioned library imports are always qualified - if only by final URI component @@ -1125,14 +1069,14 @@ public: QString defaultprefix = uri.mid(lastdot+1); s = set.value(defaultprefix); if (!s) - set.insert(defaultprefix,(s=new TypeSet)); + set.insert(defaultprefix,(s=new QmlEngine::ImportedNamespace)); } else { s = &unqualifiedset; } } else { s = set.value(prefix); if (!s) - set.insert(prefix,(s=new TypeSet)); + set.insert(prefix,(s=new QmlEngine::ImportedNamespace)); } QString url = uri; if (importType == QmlEngine::LibraryImport) { @@ -1146,8 +1090,11 @@ public: break; } } - if (!found) - return false; + if (!found) { + // XXX assume it is a built-in type qualifier + } + } else { + url = base.resolved(QUrl(url)).toString(); } s->urls.append(url); s->versions.append(version); @@ -1155,9 +1102,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 +1119,16 @@ public: s = &unqualifiedset; } QString unqualifiedtype = type.mid(slash+1); - if (s) { - for (int i=0; i<s->urls.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 +1143,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; i<s->urls.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<bool> isLibrary; - }; - TypeSet unqualifiedset; - QHash<QString,TypeSet* > set; + QmlEngine::ImportedNamespace unqualifiedset; + QHash<QString,QmlEngine::ImportedNamespace* > set; }; QmlEngine::Imports::Imports() : @@ -1256,11 +1168,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 +1194,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..98deba7 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(); @@ -87,10 +84,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/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/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; }; 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<QObject *>); @@ -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/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/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; } diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8ee3b4e..8eb58c8 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; @@ -147,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 d96a43e..d23b4ea 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 @@ -168,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/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..c1c11c7 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 <QStack> #include <QCoreApplication> @@ -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) { @@ -572,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/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<QObject *> &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<QmlCompiledData::TypeReference> &types = comp->types; @@ -169,7 +161,7 @@ QObject *QmlVME::run(QStack<QObject *> &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<QObject *> &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<QObject *> &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<QObject *> &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<QObject *> &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<QmlBindableValuePrivate *>(QObjectPrivate::get(bind)); @@ -570,7 +560,7 @@ QObject *QmlVME::run(QStack<QObject *> &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<QmlBindableValuePrivate *>(QObjectPrivate::get(bind)); 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<QmlError> errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList<QmlError> 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<QmlError> errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList<QmlError> 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<QmlError> &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<QmlError> errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList<QmlError> 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<QmlError> errors = d->component->errors(); - foreach (const QmlError &error, errors) { + QList<QmlError> 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<QmlError> &error); private Q_SLOTS: void continueExecute(); 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(); }; diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 433406c..7fa26ae 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -976,7 +976,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.cpp b/src/gui/widgets/qlinecontrol.cpp new file mode 100644 index 0000000..97f4a45 --- /dev/null +++ b/src/gui/widgets/qlinecontrol.cpp @@ -0,0 +1,1745 @@ +/**************************************************************************** +** +** 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 + +/*! + \internal + + Updates the display text based of the current edit text + If the text has changed will emit displayTextChanged() +*/ +void QLineControl::updateDisplayText() +{ + QString orig = m_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); + } + + m_textLayout.setText(str); + + QTextOption option; + option.setTextDirection(m_layoutDirection); + option.setFlags(QTextOption::IncludeTrailingSpaces); + m_textLayout.setTextOption(option); + + m_textLayout.beginLayout(); + QTextLine l = m_textLayout.createLine(); + m_textLayout.endLayout(); + m_ascent = qRound(l.ascent()); + + if (str != orig) + emit displayTextChanged(str); +} + +#ifndef QT_NO_CLIPBOARD +/*! + \internal + + 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())); + } +} + +/*! + \internal + + 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 + +/*! + \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. + + \sa del() +*/ +void QLineControl::backspace() +{ + int priorState = m_undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else if (m_cursor) { + --m_cursor; + 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) { + // 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) { + internalDelete(true); + --m_cursor; + } + } + internalDelete(true); + } + 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. + + \sa del() +*/ +void QLineControl::del() +{ + int priorState = m_undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else { + int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; + while (n--) + internalDelete(); + } + 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. +*/ +void QLineControl::insert(const QString &newText) +{ + int priorState = m_undoState; + removeSelectedText(); + internalInsert(newText); + finishChange(priorState); +} + +/*! + \internal + + Clears the line control text. +*/ +void QLineControl::clear() +{ + int priorState = m_undoState; + m_selstart = 0; + m_selend = m_text.length(); + removeSelectedText(); + separate(); + 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 + the selection will extend to the end of the current text. +*/ +void QLineControl::setSelection(int start, int length) +{ + if(start < 0 || start > (int)m_text.length()){ + qWarning("QLineControl::setSelection: Invalid start position"); + return; + } + + if (length > 0) { + m_selstart = start; + m_selend = qMin(start + length, (int)m_text.length()); + m_cursor = m_selend; + } else { + m_selstart = qMax(start + length, 0); + m_selend = start; + m_cursor = m_selstart; + } +} + +void QLineControl::_q_clipboardChanged() +{ +} + +void QLineControl::_q_deleteSelected() +{ + if (!hasSelectedText()) + return; + + int priorState = m_undoState; + emit resetInputContext(); + removeSelectedText(); + separate(); + finishChange(priorState); +} + +/*! + \internal + + 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(); +} + +/*! + \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 + does not affect other echo modes. +*/ +void QLineControl::updatePasswordEchoEditing(bool editing) +{ + m_passwordEchoEditing = 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. +*/ +int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn); +} + +/*! + \internal + + Returns the bounds of the current cursor, as defined as a + between characters cursor. +*/ +QRect QLineControl::cursorRect() const +{ + QTextLine l = m_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); +} + +/*! + \internal + + 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) + internalSetText(textCopy, cursorCopy); + return true; + } + } +#endif + return false; +} + +/*! + \internal + + 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 (m_maskData) + pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); + } + if (mark) { + int anchor; + 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; + m_selstart = qMin(anchor, pos); + m_selend = qMax(anchor, pos); + updateDisplayText(); + } else { + internalDeselect(); + } + m_cursor = pos; + if (mark || m_selDirty) { + m_selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); +} + +/*! + \internal + + Applies the given input method event \a event to the text of the line + control +*/ +void QLineControl::processInputMethodEvent(QInputMethodEvent *event) +{ + int priorState = m_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()) { + m_selstart = m_cursor; + m_selend = m_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(); + m_hideCursor = false; + QList<QTextLayout::FormatRange> 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; + m_hideCursor = !a.length; + } else if (a.type == QInputMethodEvent::TextFormat) { + QTextCharFormat f = qvariant_cast<QTextFormat>(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); + } + } + } + m_textLayout.setAdditionalFormats(formats); + updateDisplayText(); + if (!event->commitString().isEmpty()) + emitCursorPositionChanged(); + 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. + + 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<QTextLayout::FormatRange> selections; + if (flags & DrawSelections) { + QTextLayout::FormatRange o; + 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 { + // 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) + m_textLayout.draw(painter, offset, selections, clip); + + if (flags & DrawCursor){ + if(!m_blinkPeriod || m_blinkStatus) + m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + } +} + +/*! + \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. +*/ +void QLineControl::selectWordAtPos(int cursor) +{ + int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + moveCursor(c, false); + // ## text layout should support end of words. + int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + while (end > cursor && m_text[end-1].isSpace()) + --end; + 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. + + 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 = m_selDirty; + if (m_textDirty) { + // do validation + bool wasValidInput = m_validInput; + m_validInput = true; +#ifndef QT_NO_VALIDATOR + if (m_validator) { + m_validInput = false; + QString textCopy = m_text; + int cursorCopy = m_cursor; + m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (m_validInput) { + if (m_text != textCopy) { + internalSetText(textCopy, cursorCopy); + return true; + } + m_cursor = cursorCopy; + } + } +#endif + if (validateFromState >= 0 && wasValidInput && !m_validInput) { + if (m_transactions.count()) + return false; + internalUndo(validateFromState); + m_history.resize(m_undoState); + if (m_modifiedState > m_undoState) + m_modifiedState = -1; + m_validInput = true; + m_textDirty = false; + } + updateDisplayText(); + lineDirty |= m_textDirty; + if (m_textDirty) { + m_textDirty = false; + QString actualText = text(); + if (edited) + emit textEdited(actualText); + emit textChanged(actualText); + } + } + if (m_selDirty) { + m_selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); + return true; +} + +/*! + \internal + + An internal function for setting the text of the line control. +*/ +void QLineControl::internalSetText(const QString &txt, int pos, bool edited) +{ + internalDeselect(); + emit resetInputContext(); + QString oldText = m_text; + 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); + } + m_history.clear(); + m_modifiedState = m_undoState = 0; + m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; + m_textDirty = (oldText != m_text); + finishChange(-1, true, edited); +} + + +/*! + \internal + + 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 (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 { + m_history.resize(m_undoState + 1); + } + m_separator = false; + m_history[m_undoState++] = cmd; +} + +/*! + \internal + + 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::internalInsert(const QString &s) +{ + if (hasSelectedText()) + 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)); + 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); + 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)); + m_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::internalDelete(bool wasBackspace) +{ + if (m_cursor < (int) m_text.length()) { + if (hasSelectedText()) + 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 (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); + } + m_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 (m_selstart < m_selend && m_selend <= (int) m_text.length()) { + separate(); + int i ; + 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 >= m_selstart; --i) + addCommand (Command(DeleteSelection, i, 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 = m_selend-1; i >= m_selstart; --i) + addCommand (Command(RemoveSelection, i, m_text.at(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(m_selstart, m_selend - m_selstart); + } + if (m_cursor > m_selstart) + m_cursor -= qMin(m_cursor, m_selend) - m_selstart; + internalDeselect(); + m_textDirty = true; + } +} + +/*! + \internal + + 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 (m_maskData) { + delete [] m_maskData; + m_maskData = 0; + m_maxLength = 32767; + internalSetText(QString()); + } + return; + } + + if (delimiter == -1) { + m_blank = QLatin1Char(' '); + m_inputMask = maskFields; + } else { + m_inputMask = maskFields.left(delimiter); + m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + } + + // calculate m_maxLength / m_maskData length + m_maxLength = 0; + QChar c = 0; + for (int i=0; i<m_inputMask.length(); i++) { + c = m_inputMask.at(i); + if (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 [] m_maskData; + m_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; + m_maskData[index].maskChar = c; + m_maskData[index].separator = s; + m_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) { + m_maskData[index].maskChar = c; + m_maskData[index].separator = s; + m_maskData[index].caseMode = m; + index++; + } + } + } + internalSetText(m_text); +} + + +/*! + \internal + + 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 == m_blank) + return true; + break; + case 'N': + if (key.isLetterOrNumber()) + return true; + break; + case 'n': + if (key.isLetterOrNumber() || key == m_blank) + return true; + break; + case 'X': + if (key.isPrint()) + return true; + break; + case 'x': + if (key.isPrint() || key == m_blank) + return true; + break; + case '9': + if (key.isNumber()) + return true; + break; + case '0': + if (key.isNumber() || key == m_blank) + return true; + break; + case 'D': + if (key.isNumber() && key.digitValue() > 0) + return true; + break; + case 'd': + if ((key.isNumber() && key.digitValue() > 0) || key == m_blank) + return true; + break; + case '#': + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_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 == m_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 == m_blank) + return true; + break; + default: + break; + } + return false; +} + +/*! + \internal + + 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 (!m_maskData) + return true; + + if (str.length() != m_maxLength) + return false; + + for (int i=0; i < m_maxLength; ++i) { + if (m_maskData[i].separator) { + if (str.at(i) != m_maskData[i].maskChar) + return false; + } else { + if (!isValidInput(str.at(i), m_maskData[i].maskChar)) + return false; + } + } + return true; +} + +/*! + \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 +{ + 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 (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], m_maskData[i].maskChar)) { + switch (m_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 && (!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 m_blank if not + n = findInMask(i, true, false, str[(int)strIndex]); + if (n != -1) { + s += fill.mid(i, n-i); + switch (m_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; +} + + + +/*! + \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 +{ + if (pos >= (uint)m_maxLength) + return QString(); + + QString s; + int end = qMin((uint)m_maxLength, pos + len); + for (int i = pos; i < end; ++i) + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; + else + s += m_blank; + + return s; +} + +/*! + \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 +{ + if (!m_maskData) + return str; + + QString s; + int end = qMin(m_maxLength, (int)str.length()); + for (int i = 0; i < end; ++i) + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; + else + if (str[i] != m_blank) + s += str[i]; + + return s; +} + +/*! + \internal + 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 +{ + if (pos >= 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 (m_maskData[i].separator && m_maskData[i].maskChar == searchChar) + return i; + } else { + if (!m_maskData[i].separator) { + if (searchChar.isNull()) + return i; + else if (isValidInput(searchChar, m_maskData[i].maskChar)) + return i; + } + } + i += step; + } + return -1; +} + +void QLineControl::internalUndo(int until) +{ + if (!isUndoAvailable()) + return; + internalDeselect(); + 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: + m_selstart = cmd.selStart; + m_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 && m_undoState) { + Command& next = m_history[m_undoState-1]; + if (next.type != cmd.type && next.type < RemoveSelection + && (cmd.type < RemoveSelection || next.type == Separator)) + break; + } + } + m_textDirty = true; + emitCursorPositionChanged(); +} + +void QLineControl::internalRedo() +{ + if (!isRedoAvailable()) + return; + internalDeselect(); + 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: + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case Delete: + case RemoveSelection: + case DeleteSelection: + m_text.remove(cmd.pos, 1); + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Separator: + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + } + 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; + } + } + m_textDirty = true; + emitCursorPositionChanged(); +} + +/*! + \internal + + If the current cursor position differs from the last emited cursor + position, emits cursorPositionChanged(). +*/ +void QLineControl::emitCursorPositionChanged() +{ + if (m_cursor != m_lastCursorPos) { + const int oldLast = m_lastCursorPos; + m_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; + } + } + } + } +#endif + switch(ev->type()){ +#ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMousePress:{ + QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(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<QMouseEvent*>(ev)); break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + processKeyEvent(static_cast<QKeyEvent*>(ev)); break; + case QEvent::InputMethod: + processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break; +#ifndef QT_NO_SHORTCUT + case QEvent::ShortcutOverride:{ + QKeyEvent* ke = static_cast<QKeyEvent*>(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; + + 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); + clear(); + } + + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + if (hasAcceptableInput() || fixup()) { + emit accepted(); + emit editingFinished(); + } + 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 + case Qt::Key_Back: + if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat() + && !isReadOnly()) { + if (text().length() == 0) { + setText(m_cancelText); + + if (passwordEchoEditing) + updatePasswordEchoEditing(false); + + setEditFocus(false); + } else if (!deleteAllTimer) { + deleteAllTimer = startTimer(750); + } + } 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() && + ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { + 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..1e5c144 --- /dev/null +++ b/src/gui/widgets/qlinecontrol_p.h @@ -0,0 +1,741 @@ +/**************************************************************************** +** +** 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()) + : 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), + 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 [] m_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 &txt); + + 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); + + QString cancelText() const; + void setCancelText(const QString &text); + + 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); + +private: + void init(const QString &txt); + void removeSelectedText(); + void internalSetText(const QString &txt, int pos = -1, bool edited = true); + void updateDisplayText(); + + void internalInsert(const QString &s); + void internalDelete(bool wasBackspace = false); + void internalRemove(int pos); + + inline void internalDeselect() + { + m_selDirty |= (m_selend > m_selstart); + m_selstart = m_selend = 0; + } + + void internalUndo(int until = -1); + void internalRedo(); + + QString m_text; + QPalette m_palette; + int m_cursor; + int m_preeditCursor; + int m_cursorWidth; + Qt::LayoutDirection m_layoutDirection; + 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 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 m_lastCursorPos; + QList<int> m_transactions; + QPoint m_tripleClick; + int m_tripleClickTimer; + QString m_cancelText; + + void emitCursorPositionChanged(); + + bool finishChange(int validateFromState = -1, bool update = false, bool edited = true); + + QPointer<QValidator> m_validator; + QPointer<QCompleter> 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 m_blank; + MaskInputData *m_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 m_modifiedState; + int m_undoState; + QVector<Command> m_history; + void addCommand(const Command& cmd); + + inline void separate() { m_separator = true; } + + // selection + int m_selstart; + int m_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 m_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); + m_separator |= (c != pos); + return (c != -1 ? c : m_maxLength); +} + +inline int QLineControl::prevMaskBlank(int pos) +{ + int c = findInMask(pos, false, false); + m_separator |= (c != pos); + return (c != -1 ? c : 0); +} + +inline bool QLineControl::isUndoAvailable() const +{ + return !m_readOnly && m_undoState; +} + +inline bool QLineControl::isRedoAvailable() const +{ + return !m_readOnly && m_undoState < (int)m_history.size(); +} + +inline void QLineControl::clearUndo() +{ + m_history.clear(); + m_modifiedState = m_undoState = 0; +} + +inline bool QLineControl::isModified() const +{ + return m_modifiedState != m_undoState; +} + +inline void QLineControl::setModified(bool modified) +{ + m_modifiedState = modified ? -1 : m_undoState; +} + +inline bool QLineControl::allSelected() const +{ + return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); +} + +inline bool QLineControl::hasSelectedText() const +{ + return !m_text.isEmpty() && m_selend > m_selstart; +} + +inline int QLineControl::width() const +{ + return qRound(m_textLayout.lineAt(0).width()) + 1; +} + +inline int QLineControl::height() const +{ + return qRound(m_textLayout.lineAt(0).height()) + 1; +} + +inline int QLineControl::ascent() const +{ + return m_ascent; +} + +inline QString QLineControl::selectedText() const +{ + if (hasSelectedText()) + return m_text.mid(m_selstart, m_selend - m_selstart); + return QString(); +} + +inline QString QLineControl::textBeforeSelection() const +{ + if (hasSelectedText()) + return m_text.left(m_selstart); + return QString(); +} + +inline QString QLineControl::textAfterSelection() const +{ + if (hasSelectedText()) + return m_text.mid(m_selend); + return QString(); +} + +inline int QLineControl::selectionStart() const +{ + return hasSelectedText() ? m_selstart : -1; +} + +inline int QLineControl::selectionEnd() const +{ + return hasSelectedText() ? m_selend : -1; +} + +inline int QLineControl::start() const +{ + return 0; +} + +inline int QLineControl::end() const +{ + return m_text.length(); +} + +inline void QLineControl::removeSelection() +{ + int priorState = m_undoState; + removeSelectedText(); + finishChange(priorState); +} + +inline bool QLineControl::inSelection(int x) const +{ + if (m_selstart >= m_selend) + return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); + return pos >= m_selstart && pos < m_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 = m_textLayout.nextCursorPosition(c); + } else if (steps < 0) { + while (steps++) + c = m_textLayout.previousCursorPosition(c); + } + moveCursor(c, mark); +} + +inline void QLineControl::cursorWordForward(bool mark) +{ + moveCursor(m_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(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); +} + +inline qreal QLineControl::cursorToX(int cursor) const +{ + return m_textLayout.lineAt(0).cursorToX(cursor); +} + +inline qreal QLineControl::cursorToX() const +{ + return cursorToX(m_cursor); +} + +inline bool QLineControl::isReadOnly() const +{ + return m_readOnly; +} + +inline void QLineControl::setReadOnly(bool enable) +{ + m_readOnly = enable; +} + +inline QString QLineControl::text() const +{ + QString res = m_maskData ? stripString(m_text) : m_text; + return (res.isNull() ? QString::fromLatin1("") : res); +} + +inline void QLineControl::setText(const QString &txt) +{ + internalSetText(txt, -1, false); +} + +inline QString QLineControl::displayText() const +{ + return m_textLayout.text(); +} + +inline void QLineControl::deselect() +{ + internalDeselect(); + finishChange(); +} + +inline void QLineControl::selectAll() +{ + m_selstart = m_selend = m_cursor = 0; + moveCursor(m_text.length(), true); +} + +inline void QLineControl::undo() +{ + internalUndo(); + finishChange(-1, true); +} + +inline void QLineControl::redo() +{ + internalRedo(); + 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 (m_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<QValidator*>(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<QCompleter*>(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 m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); +} + +inline void QLineControl::setInputMask(const QString &mask) +{ + parseInputMask(mask); + if (m_maskData) + moveCursor(nextMaskBlank(0)); +} + +// input methods +#ifndef QT_NO_IM +inline bool QLineControl::composeMode() const +{ + return !m_textLayout.preeditAreaText().isEmpty(); +} + +inline void QLineControl::setPreeditArea(int cursor, const QString &text) +{ + m_textLayout.setPreeditArea(cursor, text); +} +#endif + +inline QString QLineControl::preeditAreaText() const +{ + return m_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) +{ + m_textLayout.setFont(font); + updateDisplayText(); +} + +inline int QLineControl::cursorBlinkPeriod() const +{ + return m_blinkPeriod; +} + +inline QString QLineControl::cancelText() const +{ + return m_cancelText; +} + +inline void QLineControl::setCancelText(const QString &text) +{ + m_cancelText = text; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QT_NO_LINEEDIT + +#endif // QLINECONTROL_P_H diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index d1067a8..e0f5bc9 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -86,21 +86,12 @@ #include <limits.h> -#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,9 @@ 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->init(contents); - } + d->init(contents); + d->control->setInputMask(inputMask); + d->control->moveCursor(d->control->nextMaskBlank(contents.length())); } #endif @@ -388,19 +374,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 +401,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 +426,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 +501,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 +530,7 @@ void QLineEdit::setEchoMode(EchoMode mode) const QValidator * QLineEdit::validator() const { Q_D(const QLineEdit); - return d->validator; + return d->control->validator(); } /*! @@ -585,7 +548,7 @@ const QValidator * QLineEdit::validator() const void QLineEdit::setValidator(const QValidator *v) { Q_D(QLineEdit); - d->validator = const_cast<QValidator*>(v); + d->control->setValidator(v); } #endif // QT_NO_VALIDATOR @@ -609,23 +572,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 +601,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 +618,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 +642,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 +664,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 +692,17 @@ 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; + // 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; } - return false; + 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) { + 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,60 +1372,31 @@ 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); } + #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) { + if (e->type() == QEvent::EnterEditFocus) { end(false); - if (!d->cursorTimer) { - int cft = QApplication::cursorFlashTime(); - d->cursorTimer = cft ? startTimer(cft/2) : -1; - } + int cft = QApplication::cursorFlashTime(); + d->control->setCursorBlinkPeriod(cft/2); } 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; - } - } + d->control->setCursorBlinkPeriod(0); + if (d->control->hasAcceptableInput() || d->control->fixup()) + emit editingFinished(); } + return true; } #endif return QWidget::event(e); @@ -1684,15 +1408,15 @@ 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() < @@ -1703,18 +1427,16 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) 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 +1446,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 +1456,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,7 +1467,7 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) { Q_D(QLineEdit); if (d->sendMouseEventToInputContext(e)) - return; + return; #ifndef QT_NO_DRAGANDDROP if (e->button() == Qt::LeftButton) { if (d->dndTimer.isActive()) { @@ -1758,9 +1480,9 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) #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(); + d->control->copy(QClipboard::Selection); + } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) { + deselect(); insert(QApplication::clipboard()->text(QClipboard::Selection)); } } @@ -1773,16 +1495,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 +1537,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 +1581,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 +1595,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. @@ -2260,55 +1625,11 @@ 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(); + d->control->processInputMethodEvent(e); - // 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<QTextLayout::FormatRange> 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<QTextFormat>(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 +1644,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 +1663,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; + d->control->setCancelText(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 +1703,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,37 +1715,29 @@ 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 (hasAcceptableInput() || d->control->fixup()) emit editingFinished(); - d->emitingEditingFinished = false; - } - } #ifdef QT3_SUPPORT emit lostFocus(); #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(); + d->control->setCancelText(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 +1767,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 +1789,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 +1817,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 +1827,23 @@ void QLineEdit::paintEvent(QPaintEvent *) #endif p.setPen(pal.text().color()); - QVector<QTextLayout::FormatRange> 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 +1853,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 +1883,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 +1912,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 +1956,39 @@ 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() + && d->control->echoMode() == QLineEdit::Normal); 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() + && d->control->echoMode() == QLineEdit::Normal); 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 +2002,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 +2018,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<inputMask.length(); i++) { - c = inputMask.at(i); - if (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; + case QEvent::FontChange: + d->control->setFont(font()); 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; + 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')) || 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<end; i++) - if (maskData[i].separator) - s += maskData[i].maskChar; - else - s += blank; - - return s; -} - -/* - Strips blank parts of the input in a QLineEdit when an inputMask is set, - separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". -*/ -QString QLineEditPrivate::stripString(const QString &str) const -{ - if (!maskData) - return str; - - QString s; - int end = qMin(maxLength, (int)str.length()); - for (int i=0; i < end; i++) - if (maskData[i].separator) - s += maskData[i].maskChar; - else - if (str[i] != blank) - s += str[i]; - - return s; -} - -/* searches forward/backward in maskData for either a separator or a blank */ -int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const -{ - if (pos >= 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..230023d 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,167 +75,64 @@ 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<QAction> 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<QAction> 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<QValidator> 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); - - - // 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<Command> 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; -#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_clipboardChanged(); 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); + void _q_textEdited(const QString &); + void _q_cursorPositionChanged(int, int); #ifndef QT_NO_COMPLETER - QPointer<QCompleter> completer; - void complete(int key = -1); void _q_completionHighlighted(QString); - bool advanceToEnabledItem(int n); +#endif +#ifndef QT_NO_DRAGANDDROP + QPoint dndPos; + QBasicTimer dndTimer; + void drag(); #endif int leftTextMargin; diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h index ce78959..5c27d1d 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(); 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 \ 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 { |