diff options
Diffstat (limited to 'src')
270 files changed, 6563 insertions, 4731 deletions
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index 8c9f358..0745d39 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -41,23 +41,51 @@ /*! \class QAnimationGroup - \brief The QAnimationGroup class is an abstract base class for group of animations. + \brief The QAnimationGroup class is an abstract base class for groups of animations. \since 4.5 \ingroup group_animation \preliminary - QAnimationGroup represents a group of animations, such as parallel or sequential, - and lets you combine different animations into one. The group manages any animation - that inherits QAbstractAnimation. By combining groups, you can easily construct - complex animation graphs. - - The QAnimationGroup base class provides methods for adding and retrieving animations. - Besides that, you can remove animations by calling remove(), and clear the animation - group by calling clearAnimations(). You may keep track of changes in the group's animations by - listening to QEvent::ChildAdded and QEvent::ChildRemoved events. - - QAnimationGroup takes ownership of the animations it manages, and ensures that they are - deleted when the animation group is deleted. + An animation group is a container for animations (subclasses of + QAbstractAnimation). A group is usually responsible for managing + the \l{QAbstractAnimation::State}{state} of its animations, i.e., + it decides when to start, stop, resume, and pause them. Currently, + Qt provides two such groups: QParallelAnimationGroup and + QSequentialAnimationGroup. Look up their class descriptions for + details. + + Since QAnimationGroup inherits from QAbstractAnimation, you can + combine groups, and easily construct complex animation graphs. + You can query QAbstractAnimation for the group it belongs to + (using the \l{QAbstractAnimation::}{group()} function). + + To start a top-level animation group, you simply use the + \l{QAbstractAnimation::}{start()} function from + QAbstractAnimation. By a top-level animation group, we think of a + group that itself is not contained within another group. Starting + sub groups directly is not supported, and may lead to unexpected + behavior. + + \omit OK, we'll put in a snippet on this here \endomit + + QAnimationGroup provides methods for adding and retrieving + animations. Besides that, you can remove animations by calling + remove(), and clear the animation group by calling + clearAnimations(). You may keep track of changes in the group's + animations by listening to QEvent::ChildAdded and + QEvent::ChildRemoved events. + + \omit OK, let's find a snippet here as well. \endomit + + QAnimationGroup takes ownership of the animations it manages, and + ensures that they are deleted when the animation group is deleted. + + You can also use a \l{The State Machine Framework}{state machine} + to create complex animations. The framework provides a special + state, QAnimationState, that plays an animation upon entry and + transitions to a new state when the animation has finished + playing. This technique can also be combined with using animation + groups. \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework} */ diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index a75f85c..68dbb9e 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -46,8 +46,27 @@ \ingroup group_animation \preliminary - The animations are all started at the same time, and run in parallel. The animation group - finishes when the longest lasting animation has finished. + QParallelAnimationGroup--a \l{QAnimationGroup}{container for + animations}--starts all its animations when it is + \l{QAbstractAnimation::start()}{started} itself, i.e., runs all + animations in parallel. The animation group finishes when the + longest lasting animation has finished. + + You can treat QParallelAnimation as any other QAbstractAnimation, + e.g., pause, resume, or add it to other animation groups. + + \code + QParallelAnimationGroup *group = new QParallelAnimationGroup; + group->addAnimation(anim1); + group->addAnimation(anim2); + + group->start(); + \endcode + + In this example, \c anim1 and \c anim2 are two + \l{QPropertyAnimation}s that have already been set up. + + \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp index 86c3049..cf3bb3b 100644 --- a/src/corelib/animation/qpauseanimation.cpp +++ b/src/corelib/animation/qpauseanimation.cpp @@ -45,6 +45,22 @@ \since 4.5 \ingroup group_animation \preliminary + + If you wish to introduce a delay between animations in a + QSequentialAnimationGroup, you can insert a QPauseAnimation. This + class does not animate anything, but does not + \l{QAbstractAnimation::finished()}{finish} before a specified + number of milliseconds have elapsed from when it was started. You + specify the duration of the pause in the constructor. It can also + be set directly with setDuration(). + + It is not necessary to construct a QPauseAnimation yourself. + QSequentialAnimationGroup provides the convenience functions + \l{QSequentialAnimationGroup::}{addPause()} and + \l{QSequentialAnimationGroup::}{insertPauseAt()}. These functions + simply take the number of milliseconds the pause should last. + + \sa QSequentialAnimationGroup */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index ed20e667..4bdffa4 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -48,14 +48,14 @@ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt properties}. As property values are stored in \l{QVariant}s, the class inherits QVariantAnimation, and supports animation of the - same \l{QVariant::Type}{variant types} as its super class. + same \l{QVariant::Type}{variant types} as its super class. A class declaring properties must be a QObject. To make it possible to animate a property, it must provide a setter (so that QPropertyAnimation can set the property's value). Note that this makes it possible to animate many of Qt's widgets. Let's look at an example: - + \code QPropertyAnimation animation(myWidget, "geometry"); animation.setDuration(10000); diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h index ed3666d..9d9dd31 100644 --- a/src/corelib/animation/qpropertyanimation_p.h +++ b/src/corelib/animation/qpropertyanimation_p.h @@ -70,7 +70,6 @@ public: { } - QPointer<QObject> target; //for the QProperty diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 45673c2..c610b4f 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -46,13 +46,36 @@ \ingroup group_animation \preliminary - The first animation in the group is started first, and when it finishes, the next animation - is started, and so on. The animation group finishes when the last animation has finished. + QSequentialAnimationGroup is a QAnimationGroup that runs its + animations in sequence, i.e., it starts one animation after + another has finished playing. The animations are played in the + order they are added to the group (using + \l{QAnimationGroup::}{addAnimation()} or + \l{QAnimationGroup::}{insertAnimationAt()}). The animation group + finishes when its last animation has finished. - At each moment there is at most one animation that is active in the group, called currentAnimation. - An empty group has no current animation. + At each moment there is at most one animation that is active in + the group; it is returned by currentAnimation(). An empty group + has no current animation. - You can call addPause() or insertPause() to add a pause to a sequential animation group. + A sequential animation group can be treated as any other + animation, i.e., it can be started, stopped, and added to other + groups. You can also call addPause() or insertPauseAt() to add a + pause to a sequential animation group. + + \code + QSequentialAnimationGroup group; + + group.addAnimation(anim1); + group.addAnimation(anim2); + + group.start(); + \endcode + + In this example, \c anim1 and \c anim2 are two already set up + \l{QPropertyAnimation}s. + + \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 331024e..e27cde8 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -64,13 +64,15 @@ QT_BEGIN_NAMESPACE shared functionality. QVariantAnimation cannot be used directly as it is an abstract - class; it does not implement \l{updateCurrentValue()}. The class - performs interpolation over \l{QVariant}s, but leaves using the - interpolated values to its subclasses. Currently, Qt provides - QPropertyAnimation, which animates Qt \l{Qt's Property System} - {properties}. See the QPropertyAnimation class description if you - wish to animate such properties. - + class; it does not implement + \l{QAbstractAnimation::}{updateCurrentValue()} from + QAbstractAnimation. The class performs interpolation over + \l{QVariant}s, but leaves using the interpolated values to its + subclasses. Currently, Qt provides QPropertyAnimation, which + animates Qt \l{Qt's Property System}{properties}. See the + QPropertyAnimation class description if you wish to animate such + properties. + You can then set start and end values for the property by calling setStartValue() and setEndValue(), and finally call start() to start the animation. QVariantAnimation will interpolate the @@ -109,12 +111,12 @@ QT_BEGIN_NAMESPACE \o \l{QMetaType::}{QSizeF} \o \l{QMetaType::}{QRect} \o \l{QMetaType::}{QRectF} - \endlist + \endlist If you need to interpolate other variant types, including custom types, you have to implement interpolation for these yourself. You do this by reimplementing interpolated(), which returns - interpolation values for the value being interpolated. + interpolation values for the value being interpolated. \omit We need some snippets around here. \endomit @@ -150,7 +152,7 @@ template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF f.getRect(&x1, &y1, &w1, &h1); qreal x2, y2, w2, h2; t.getRect(&x2, &y2, &w2, &h2); - return QRectF( _q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress), + return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress), _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress)); } @@ -172,47 +174,61 @@ void QVariantAnimationPrivate::convertValues(int t) if (pair.second.userType() != t) pair.second.convert(static_cast<QVariant::Type>(t)); } - currentInterval.start.first = 2; // this will force the refresh - interpolator = 0; // if the type changed we need to update the interpolator + interpolator = 0; // if the type changed we need to update the interpolator } /*! - \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0; - This pure virtual function is called when the animated value is changed. - \a value is the new value. + \internal + The goal of this function is to update the currentInterval member. As a consequence, we also + need to update the currentValue. + Set \a force to true to always recalculate the interval. */ - -void QVariantAnimationPrivate::updateCurrentValue() +void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/) { - Q_Q(QVariantAnimation); + // can't interpolate if we have only 1 key value + if (keyValues.count() <= 1) + return; + const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration))); - if (progress < currentInterval.start.first || progress > currentInterval.end.first) { + if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) { //let's update currentInterval - QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), keyValues.constEnd(), qMakePair(progress, QVariant()), animationValueLessThan); + QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), + keyValues.constEnd(), + qMakePair(progress, QVariant()), + animationValueLessThan); QVariantAnimation::KeyValues::const_iterator itEnd = itStart; // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0). // This is because the easing function can return a value slightly outside the range [0, 1] if (itStart != keyValues.constEnd()) { - - //this can't happen because we always prepend the default start value there - if (itStart == keyValues.begin()) { + // this can't happen because we always prepend the default start value there + if (itStart == keyValues.constBegin()) { ++itEnd; - if (itEnd == keyValues.constEnd()) - return; //there is no upper bound } else { --itStart; } - //update all the values of the currentInterval + // update all the values of the currentInterval currentInterval.start = *itStart; currentInterval.end = *itEnd; } } + setCurrentValueForProgress(progress); +} + +void QVariantAnimationPrivate::setCurrentValue() +{ + const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration))); + setCurrentValueForProgress(progress); +} - const qreal startProgress = currentInterval.start.first, - endProgress = currentInterval.end.first; +void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) +{ + Q_Q(QVariantAnimation); + + const qreal startProgress = currentInterval.start.first; + const qreal endProgress = currentInterval.end.first; const qreal localProgress = (progress - startProgress) / (endProgress - startProgress); QVariant ret = q->interpolated(currentInterval.start.second, @@ -225,11 +241,10 @@ void QVariantAnimationPrivate::updateCurrentValue() #endif if (currentValue != ret) { //the value has changed - emit q->valueChanged(currentValue); + emit q->valueChanged(currentValue); } } - QVariant QVariantAnimationPrivate::valueAt(qreal step) const { QVariantAnimation::KeyValues::const_iterator result = @@ -240,7 +255,6 @@ QVariant QVariantAnimationPrivate::valueAt(qreal step) const return QVariant(); } - void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) { if (step < qreal(0.0) || step > qreal(1.0)) { @@ -255,15 +269,14 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) keyValues.insert(result, pair); } else { if (value.isValid()) - result->second = value; //remove the previous value + result->second = value; // replaces the previous value else if (step == 0 && !hasStartValue && defaultStartValue.isValid()) - result->second = defaultStartValue; //we reset to the default start value + result->second = defaultStartValue; // resets to the default start value else - keyValues.erase(result); //replace the previous value + keyValues.erase(result); // removes the previous value } - currentInterval.start.first = 2; // this will force the refresh - updateCurrentValue(); + recalculateCurrentInterval(/*force=*/true); } void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value) @@ -322,7 +335,7 @@ void QVariantAnimation::setEasingCurve(const QEasingCurve &easing) { Q_D(QVariantAnimation); d->easing = easing; - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } Q_GLOBAL_STATIC(QVector<QVariantAnimation::Interpolator>, registeredInterpolators) @@ -433,7 +446,7 @@ void QVariantAnimation::setDuration(int msecs) if (d->duration == msecs) return; d->duration = msecs; - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } /*! @@ -543,8 +556,8 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues) Q_D(QVariantAnimation); d->keyValues = keyValues; qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan); - d->currentInterval.start.first = 2; // this will force the refresh d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0; + d->recalculateCurrentInterval(/*force=*/true); } /*! @@ -569,7 +582,7 @@ QVariant QVariantAnimation::currentValue() const { Q_D(const QVariantAnimation); if (!d->currentValue.isValid()) - const_cast<QVariantAnimationPrivate*>(d)->updateCurrentValue(); + const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval(); return d->currentValue; } @@ -585,12 +598,10 @@ bool QVariantAnimation::event(QEvent *event) \reimp */ void QVariantAnimation::updateState(QAbstractAnimation::State oldState, - QAbstractAnimation::State newState) + QAbstractAnimation::State newState) { Q_UNUSED(oldState); Q_UNUSED(newState); - Q_D(QVariantAnimation); - d->currentValue = QVariant(); // this will force the refresh } /*! @@ -633,7 +644,7 @@ void QVariantAnimation::updateCurrentTime(int msecs) { Q_D(QVariantAnimation); Q_UNUSED(msecs); - d->updateCurrentValue(); + d->recalculateCurrentInterval(); } QT_END_NAMESPACE diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index 14a3ef6..9e81649 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -108,7 +108,9 @@ public: quint32 changedSignalMask; - void updateCurrentValue(); + void setCurrentValue(); + void setCurrentValueForProgress(const qreal progress); + void recalculateCurrentInterval(bool force=false); void setValueAt(qreal, const QVariant &); QVariant valueAt(qreal step) const; void convertValues(int t); diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h index b263aab..ea9954b 100644 --- a/src/corelib/arch/qatomic_mips.h +++ b/src/corelib/arch/qatomic_mips.h @@ -103,16 +103,25 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() #if defined(Q_CC_GNU) && !defined(Q_OS_IRIX) +#if _MIPS_SIM == _ABIO32 +#define SET_MIPS2 ".set mips2\n\t" +#else +#define SET_MIPS2 +#endif + inline bool QBasicAtomicInt::ref() { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addiu %[newValue], %[originalValue], %[one]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -125,12 +134,15 @@ inline bool QBasicAtomicInt::deref() { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addiu %[newValue], %[originalValue], %[minusOne]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -143,7 +155,9 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -153,6 +167,7 @@ inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -166,7 +181,9 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -177,6 +194,7 @@ inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) "nop\n" "sync\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -190,7 +208,9 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) { register int result; register int tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" @@ -201,6 +221,7 @@ inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -219,12 +240,15 @@ inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -237,13 +261,16 @@ inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) { register int originalValue; register int tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -256,13 +283,16 @@ inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) { register int originalValue; register int tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" "sc %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -280,12 +310,15 @@ inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -298,13 +331,16 @@ inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -317,13 +353,16 @@ inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) { register int originalValue; register int newValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" "ll %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" "sc %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -350,7 +389,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu { register T *result; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -360,6 +401,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValu "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -374,7 +416,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu { register T *result; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" "bnez %[result], 0f\n" @@ -385,6 +429,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValu "nop\n" "sync\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -399,7 +444,9 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu { register T *result; register T *tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[result], %[_q_value]\n" "xor %[result], %[result], %[expectedValue]\n" @@ -410,6 +457,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValu "beqz %[tempValue], 0b\n" "nop\n" "0:\n" + ".set pop\n" : [result] "=&r" (result), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -430,12 +478,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -449,13 +500,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -469,13 +523,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) { register T *originalValue; register T *tempValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[originalValue], %[_q_value]\n" "move %[tempValue], %[newValue]\n" SCP" %[tempValue], %[_q_value]\n" "beqz %[tempValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [tempValue] "=&r" (tempValue), [_q_value] "+m" (_q_value) @@ -495,12 +552,15 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -514,13 +574,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("0:\n" + asm volatile(".set push\n" + SET_MIPS2 + "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" "sync\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) @@ -534,13 +597,16 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueTo { register T *originalValue; register T *newValue; - asm volatile("sync\n" + asm volatile(".set push\n" + SET_MIPS2 + "sync\n" "0:\n" LLP" %[originalValue], %[_q_value]\n" "addu %[newValue], %[originalValue], %[valueToAdd]\n" SCP" %[newValue], %[_q_value]\n" "beqz %[newValue], 0b\n" "nop\n" + ".set pop\n" : [originalValue] "=&r" (originalValue), [_q_value] "+m" (_q_value), [newValue] "=&r" (newValue) diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index ea35e9e..39d7698 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -465,7 +465,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event) break; emit q->progressValueChanged(event->index1); - if (event->text != QString()) // ### + if (!event->text.isNull()) // ### q->progressTextChanged(event->text); break; case QFutureCallOutEvent::ProgressRange: diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 3690d4b..8f37e25 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -10,9 +10,9 @@ HEADERS += \ io/qdiriterator.h \ io/qfile.h \ io/qfileinfo.h \ - io/qfileinfo_p.h \ io/qiodevice.h \ io/qiodevice_p.h \ + io/qnoncontiguousbytedevice_p.h \ io/qprocess.h \ io/qprocess_p.h \ io/qtextstream.h \ @@ -38,6 +38,7 @@ SOURCES += \ io/qfile.cpp \ io/qfileinfo.cpp \ io/qiodevice.cpp \ + io/qnoncontiguousbytedevice.cpp \ io/qprocess.cpp \ io/qtextstream.cpp \ io/qtemporaryfile.cpp \ diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 8334146..9b0fbe5 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -51,6 +51,7 @@ #include <QtCore/qstring.h> #include <QtCore/qvector.h> #include <QtCore/qset.h> +#include <QtCore/qcontiguouscache.h> QT_BEGIN_HEADER @@ -232,6 +233,24 @@ inline QDebug operator<<(QDebug debug, const QSet<T> &set) return operator<<(debug, set.toList()); } +#if defined(FORCE_UREF) +template <class T> +inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache) +#else +template <class T> +inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) +#endif +{ + debug.nospace() << "QContiguousCache("; + for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) { + debug << cache[i]; + if (i != cache.lastIndex()) + debug << ", "; + } + debug << ")"; + return debug.space(); +} + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h deleted file mode 100644 index 7d66581..0000000 --- a/src/corelib/io/qfileinfo_p.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore 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 QFILEINFO_P_H -#define QFILEINFO_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of QIODevice. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qfileinfo.h" - -QT_BEGIN_NAMESPACE - -class QFileInfoPrivate -{ -public: - QFileInfoPrivate(const QFileInfo *copy=0); - ~QFileInfoPrivate(); - - void initFileEngine(const QString &); - - enum Access { - ReadAccess, - WriteAccess, - ExecuteAccess - }; - bool hasAccess(Access access) const; - - uint getFileFlags(QAbstractFileEngine::FileFlags) const; - QDateTime &getFileTime(QAbstractFileEngine::FileTime) const; - QString getFileName(QAbstractFileEngine::FileName) const; - - enum { - CachedFileFlags = 0x01, - CachedLinkTypeFlag = 0x02, - CachedBundleTypeFlag= 0x04, - CachedMTime = 0x10, - CachedCTime = 0x20, - CachedATime = 0x40, - CachedSize = 0x08 - }; - - struct Data - { - inline Data() - : ref(1), fileEngine(0), cache_enabled(1) - { - clear(); - } - - inline Data(const Data ©) - : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)), - fileName(copy.fileName), cache_enabled(copy.cache_enabled) - { - clear(); - } - - inline ~Data() - { - delete fileEngine; - } - - inline void clear() - { - fileNames.clear(); - fileFlags = 0; - cachedFlags = 0; - } - - mutable QAtomicInt ref; - - QAbstractFileEngine *fileEngine; - mutable QString fileName; - mutable QHash<int, QString> fileNames; - mutable uint cachedFlags : 31; - mutable uint cache_enabled : 1; - mutable uint fileFlags; - mutable qint64 fileSize; - mutable QDateTime fileTimes[3]; - - inline bool getCachedFlag(uint c) const - { return cache_enabled ? (cachedFlags & c) : 0; } - - inline void setCachedFlag(uint c) - { if (cache_enabled) cachedFlags |= c; } - } *data; - - inline void reset() { - detach(); - data->clear(); - } - - void detach(); -}; - - -QT_END_NAMESPACE -#endif - diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 8a0a3f5..7a6a85b 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -780,7 +780,7 @@ QString QFSFileEngine::fileName(FileName file) const #endif if (len > 0) { QString ret; - if (S_ISDIR(d->st.st_mode) && s[0] != '/') { + if (d->doStat() && S_ISDIR(d->st.st_mode) && s[0] != '/') { QDir parent(d->filePath); parent.cdUp(); ret = parent.path(); diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp new file mode 100644 index 0000000..6233fde --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice.cpp @@ -0,0 +1,542 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore 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 "qnoncontiguousbytedevice_p.h" +#include <QObject> +#include <QBuffer> +#include <QDebug> +#include <QFile> + +QT_BEGIN_NAMESPACE + +/*! + \class QNonContiguousByteDevice + \brief A QNonContiguousByteDevice is a representation of a + file, array or buffer that allows access with a read pointer. + \since 4.6 + + \inmodule QtCore + + The goal of this class is to have a data representation that + allows us to avoid doing a memcpy as we have to do with QIODevice. + + \sa QNonContiguousByteDeviceFactory + + \internal +*/ +/*! + \fn virtual const char* QNonContiguousByteDevice::readPointer(qint64 maximumLength, qint64 &len) + + Return a byte pointer for at most \a maximumLength bytes of that device. + if \a maximumLength is -1, the caller does not care about the length and + the device may return what it desires to. + The actual number of bytes the pointer is valid for is returned in + the \a len variable. + \a len will be -1 if EOF or an error occurs. + If it was really EOF can then afterwards be checked with atEnd() + Returns 0 if it is not possible to read at that position. + + \sa atEnd() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::advanceReadPointer(qint64 amount) + + will advance the internal read pointer by \a amount bytes. + The old readPointer is invalid after this call. + + \sa readPointer() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::atEnd() + + Returns true if everything has been read and the read + pointer cannot be advanced anymore. + + \sa readPointer(), advanceReadPointer(), reset() + + \internal +*/ +/*! + \fn virtual bool QNonContiguousByteDevice::reset() + + Moves the internal read pointer back to the beginning. + Returns false if this was not possible. + + \sa atEnd(), disableReset() + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::disableReset() + + Disable the reset() call, e.g. it will always + do nothing and return false. + + \sa reset() + + \internal +*/ +/*! + \fn virtual qint64 QNonContiguousByteDevice::size() + + Returns the size of the complete device or -1 if unknown. + May also return less/more than what can be actually read with readPointer() + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::readyRead() + + Emitted when there is data available + + \internal +*/ +/*! + \fn void QNonContiguousByteDevice::readProgress(qint64 current, qint64 total) + + Emitted when data has been "read" by advancing the read pointer + + \internal +*/ + +QNonContiguousByteDevice::QNonContiguousByteDevice() : QObject((QObject*)0), resetDisabled(false) +{ +}; + +QNonContiguousByteDevice::~QNonContiguousByteDevice() +{ +}; + +void QNonContiguousByteDevice::disableReset() +{ + resetDisabled = true; +} + +QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b) : QNonContiguousByteDevice() +{ + buffer = b; + byteArray = QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(), buffer->size() - buffer->pos()); + arrayImpl = new QNonContiguousByteDeviceByteArrayImpl(&byteArray); + arrayImpl->setParent(this); + connect(arrayImpl, SIGNAL(readyRead()), SIGNAL(readyRead())); + connect(arrayImpl, SIGNAL(readProgress(qint64,qint64)), SIGNAL(readProgress(qint64,qint64))); +} + +QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl() +{ +} + +const char* QNonContiguousByteDeviceBufferImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + return arrayImpl->readPointer(maximumLength, len); +} + +bool QNonContiguousByteDeviceBufferImpl::advanceReadPointer(qint64 amount) +{ + return arrayImpl->advanceReadPointer(amount); +} + +bool QNonContiguousByteDeviceBufferImpl::atEnd() +{ + return arrayImpl->atEnd(); +} + +bool QNonContiguousByteDeviceBufferImpl::reset() +{ + if (resetDisabled) + return false; + return arrayImpl->reset(); +} + +qint64 QNonContiguousByteDeviceBufferImpl::size() +{ + return arrayImpl->size(); +} + +QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0) +{ + byteArray = ba; +} + +QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl() +{ +} + +const char* QNonContiguousByteDeviceByteArrayImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (atEnd()) { + len = -1; + return 0; + } + + if (maximumLength != -1) + len = qMin(maximumLength, size() - currentPosition); + else + len = size() - currentPosition; + + return byteArray->constData() + currentPosition; +} + +bool QNonContiguousByteDeviceByteArrayImpl::advanceReadPointer(qint64 amount) +{ + currentPosition += amount; + emit readProgress(currentPosition, size()); + return true; +} + +bool QNonContiguousByteDeviceByteArrayImpl::atEnd() +{ + return currentPosition >= size(); +} + +bool QNonContiguousByteDeviceByteArrayImpl::reset() +{ + if (resetDisabled) + return false; + + currentPosition = 0; + return true; +} + +qint64 QNonContiguousByteDeviceByteArrayImpl::size() +{ + return byteArray->size(); +} + +QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb) + : QNonContiguousByteDevice(), currentPosition(0) +{ + ringBuffer = rb; +} + +QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl() +{ +}; + +const char* QNonContiguousByteDeviceRingBufferImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (atEnd()) { + len = -1; + return 0; + } + + const char *returnValue = ringBuffer->readPointerAtPosition(currentPosition, len); + + if (maximumLength != -1) + len = qMin(len, maximumLength); + + return returnValue; +}; + +bool QNonContiguousByteDeviceRingBufferImpl::advanceReadPointer(qint64 amount) +{ + currentPosition += amount; + emit readProgress(currentPosition, size()); + return true; +}; + +bool QNonContiguousByteDeviceRingBufferImpl::atEnd() +{ + return currentPosition >= size(); +}; + +bool QNonContiguousByteDeviceRingBufferImpl::reset() +{ + if (resetDisabled) + return false; + + currentPosition = 0; + return true; +}; + +qint64 QNonContiguousByteDeviceRingBufferImpl::size() +{ + return ringBuffer->size(); +}; + +QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d) + : QNonContiguousByteDevice(), + currentReadBuffer(0), currentReadBufferSize(16*1024), + currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0), + eof(false) +{ + device = d; + initialPosition = d->pos(); + connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection); + connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection); +}; + +QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl() +{ + delete currentReadBuffer; +}; + +const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len) +{ + if (eof == true) { + len = -1; + return 0; + } + + if (currentReadBuffer == 0) + currentReadBuffer = new QByteArray(currentReadBufferSize, '\0'); // lazy alloc + + if (maximumLength == -1) + maximumLength = currentReadBufferSize; + + if (currentReadBufferAmount - currentReadBufferPosition > 0) { + len = currentReadBufferAmount - currentReadBufferPosition; + return currentReadBuffer->data() + currentReadBufferPosition; + } + + qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize)); + + if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) { + eof = true; + len = -1; + // size was unknown before, emit a readProgress with the final size + if (size() == -1) + emit readProgress(totalAdvancements, totalAdvancements); + return 0; + } + + currentReadBufferAmount = haveRead; + currentReadBufferPosition = 0; + + len = haveRead; + return currentReadBuffer->data(); +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount) +{ + totalAdvancements += amount; + + // normal advancement + currentReadBufferPosition += amount; + + // advancing over that what has actually been read before + if (currentReadBufferPosition > currentReadBufferAmount) { + qint64 i = currentReadBufferPosition - currentReadBufferAmount; + while (i > 0) { + if (device->getChar(0) == false) { + emit readProgress(totalAdvancements - i, size()); + return false; // ### FIXME handle eof + } + i--; + } + + currentReadBufferPosition = 0; + currentReadBufferAmount = 0; + } + + if (size() == -1) + emit readProgress(totalAdvancements, totalAdvancements); + else + emit readProgress(totalAdvancements, size()); + + return true; +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::atEnd() +{ + return eof == true; +}; + +bool QNonContiguousByteDeviceIoDeviceImpl::reset() +{ + if (resetDisabled) + return false; + + if (device->seek(initialPosition)) { + eof = false; // assume eof is false, it will be true after a read has been attempted + return true; + } + + return false; +}; + +qint64 QNonContiguousByteDeviceIoDeviceImpl::size() +{ + // note that this is different from the size() implementation of QIODevice! + + if (device->isSequential()) + return -1; + + return device->size() - initialPosition; +}; + +QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0) +{ + byteDevice = bd; + connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead())); + + open(ReadOnly); +} + +QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice() +{ + +} + +bool QByteDeviceWrappingIoDevice::isSequential() const +{ + return (byteDevice->size() == -1); +} + +bool QByteDeviceWrappingIoDevice::atEnd() const +{ + return byteDevice->atEnd(); +} + +bool QByteDeviceWrappingIoDevice::reset() +{ + return byteDevice->reset(); +} + +qint64 QByteDeviceWrappingIoDevice::size() const +{ + if (isSequential()) + return 0; + + return byteDevice->size(); +} + + +qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize) +{ + qint64 len; + const char *readPointer = byteDevice->readPointer(maxSize, len); + if (len == -1) + return -1; + + memcpy(data, readPointer, len); + byteDevice->advanceReadPointer(len); + return len; +} + +qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize) +{ + return -1; +} + +/*! + \class QNonContiguousByteDeviceFactory + \since 4.6 + + \inmodule QtCore + + Creates a QNonContiguousByteDevice out of a QIODevice, + QByteArray etc. + + \sa QNonContiguousByteDevice + + \internal +*/ + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device); + + Create a QNonContiguousByteDevice out of a QIODevice. + For QFile, QBuffer and all other QIoDevice, sequential or not. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device) +{ + // shortcut if it is a QBuffer + if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) { + return new QNonContiguousByteDeviceBufferImpl(buffer); + } + + // ### FIXME special case if device is a QFile that supports map() + // then we can actually deal with the file without using read/peek + + // generic QIODevice + return new QNonContiguousByteDeviceIoDeviceImpl(device); // FIXME +}; + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer); + + Create a QNonContiguousByteDevice out of a QRingBuffer. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer) +{ + return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer); +}; + +/*! + \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray); + + Create a QNonContiguousByteDevice out of a QByteArray. + + \internal +*/ +QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray) +{ + return new QNonContiguousByteDeviceByteArrayImpl(byteArray); +}; + +/*! + \fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice); + + Wrap the \a byteDevice (possibly again) into a QIODevice. + + \internal +*/ +QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice) +{ + // ### FIXME if it already has been based on QIoDevice, we could that one out again + // and save some calling + + // needed for FTP backend + + return new QByteDeviceWrappingIoDevice(byteDevice); +} + +QT_END_NAMESPACE + diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h new file mode 100644 index 0000000..2a7e40b --- /dev/null +++ b/src/corelib/io/qnoncontiguousbytedevice_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore 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 QNONCONTIGUOUSBYTEDEVICE_H +#define QNONCONTIGUOUSBYTEDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QtCore/qbytearray.h> +#include <QtCore/qbuffer.h> +#include <QtCore/qiodevice.h> +#include "private/qringbuffer_p.h" + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject +{ + Q_OBJECT +public: + virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0; + virtual bool advanceReadPointer(qint64 amount) = 0; + virtual bool atEnd() = 0; + virtual bool reset() = 0; + void disableReset(); + virtual qint64 size() = 0; + +protected: + QNonContiguousByteDevice(); + virtual ~QNonContiguousByteDevice(); + + bool resetDisabled; +signals: + void readyRead(); + void readProgress(qint64 current, qint64 total); +}; + +class Q_CORE_EXPORT QNonContiguousByteDeviceFactory +{ +public: + static QNonContiguousByteDevice* create(QIODevice *device); + static QNonContiguousByteDevice* create(QByteArray *byteArray); + static QNonContiguousByteDevice* create(QRingBuffer *ringBuffer); + static QIODevice* wrap(QNonContiguousByteDevice* byteDevice); +}; + +// the actual implementations +// + +class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba); + ~QNonContiguousByteDeviceByteArrayImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QByteArray* byteArray; + qint64 currentPosition; +}; + +class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb); + ~QNonContiguousByteDeviceRingBufferImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QRingBuffer* ringBuffer; + qint64 currentPosition; +}; + + +class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d); + ~QNonContiguousByteDeviceIoDeviceImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QIODevice* device; + QByteArray* currentReadBuffer; + qint64 currentReadBufferSize; + qint64 currentReadBufferAmount; + qint64 currentReadBufferPosition; + qint64 totalAdvancements; + bool eof; + qint64 initialPosition; +}; + +class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice +{ + Q_OBJECT +public: + QNonContiguousByteDeviceBufferImpl(QBuffer *b); + ~QNonContiguousByteDeviceBufferImpl(); + const char* readPointer(qint64 maximumLength, qint64 &len); + bool advanceReadPointer(qint64 amount); + bool atEnd(); + bool reset(); + qint64 size(); +protected: + QBuffer* buffer; + QByteArray byteArray; + QNonContiguousByteDeviceByteArrayImpl* arrayImpl; +}; + +// ... and the reverse thing +class QByteDeviceWrappingIoDevice : public QIODevice +{ + Q_OBJECT +public: + QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd); + ~QByteDeviceWrappingIoDevice (); + virtual bool isSequential () const; + virtual bool atEnd () const; + virtual bool reset (); + virtual qint64 size () const; +protected: + virtual qint64 readData ( char * data, qint64 maxSize ); + virtual qint64 writeData ( const char * data, qint64 maxSize ); + + QNonContiguousByteDevice *byteDevice; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c21cf87..77ef096 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1710,7 +1710,7 @@ QString QCoreApplication::applicationDirPath() } QCoreApplicationPrivate *d = self->d_func(); - if (d->cachedApplicationDirPath == QString()) + if (d->cachedApplicationDirPath.isNull()) d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path(); return d->cachedApplicationDirPath; } @@ -1738,7 +1738,7 @@ QString QCoreApplication::applicationFilePath() } QCoreApplicationPrivate *d = self->d_func(); - if (d->cachedApplicationFilePath != QString()) + if (!d->cachedApplicationFilePath.isNull()) return d->cachedApplicationFilePath; #if defined( Q_WS_WIN ) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index b53e91f..b504604 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1173,8 +1173,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; and versatile, but may prove less memory and speed efficient than storing specific types in standard data structures. - QVariant also supports the notion of null values, where you have - a defined type with no value set. + QVariant also supports the notion of null values, where you can + have a defined type with no value set. However, note that QVariant + types can only be cast when they have had a value set. \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1 diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 3f84314..7e59a7d 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -129,36 +129,16 @@ void QAbstractStatePrivate::emitExited() Constructs a new state with the given \a parent state. */ QAbstractState::QAbstractState(QState *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QAbstractStatePrivate, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QAbstractStatePrivate) -#endif + : QObject(*new QAbstractStatePrivate, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! \internal */ QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif + : QObject(dd, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! @@ -166,9 +146,6 @@ QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent) */ QAbstractState::~QAbstractState() { -#ifdef QT_STATEMACHINE_SOLUTION - delete d_ptr; -#endif } /*! diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index f6b4b21..d0ebb52 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -76,9 +76,6 @@ protected: bool event(QEvent *e); protected: -#ifdef QT_STATEMACHINE_SOLUTION - QAbstractStatePrivate *d_ptr; -#endif QAbstractState(QAbstractStatePrivate &dd, QState *parent); private: diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index 6c09696..1a99d6c 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -53,9 +53,7 @@ // We mean it. // -#ifndef QT_STATEMACHINE_SOLUTION #include <private/qobject_p.h> -#endif QT_BEGIN_NAMESPACE @@ -63,9 +61,7 @@ class QStateMachine; class QAbstractState; class Q_CORE_EXPORT QAbstractStatePrivate -#ifndef QT_STATEMACHINE_SOLUTION : public QObjectPrivate -#endif { Q_DECLARE_PUBLIC(QAbstractState) @@ -82,10 +78,6 @@ public: void emitEntered(); void emitExited(); - -#ifdef QT_STATEMACHINE_SOLUTION - QAbstractState *q_ptr; -#endif }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 1897aa6..a930581 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -125,9 +125,9 @@ QStateMachine *QAbstractTransitionPrivate::machine() const return 0; } -bool QAbstractTransitionPrivate::callEventTest(QEvent *e) const +bool QAbstractTransitionPrivate::callEventTest(QEvent *e) { - Q_Q(const QAbstractTransition); + Q_Q(QAbstractTransition); return q->eventTest(e); } @@ -147,18 +147,8 @@ QState *QAbstractTransitionPrivate::sourceState() const Constructs a new QAbstractTransition object with the given \a sourceState. */ QAbstractTransition::QAbstractTransition(QState *sourceState) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QAbstractTransitionPrivate, -#endif - sourceState) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QAbstractTransitionPrivate) -#endif + : QObject(*new QAbstractTransitionPrivate, sourceState) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! @@ -167,20 +157,9 @@ QAbstractTransition::QAbstractTransition(QState *sourceState) */ QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QAbstractTransitionPrivate, -#endif - sourceState) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QAbstractTransitionPrivate) -#endif + : QObject(*new QAbstractTransitionPrivate, sourceState) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif - Q_D(QAbstractTransition); - d->targetStates = targets; + setTargetStates(targets); } /*! @@ -188,18 +167,8 @@ QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets, */ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif + : QObject(dd, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! @@ -208,20 +177,9 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif + : QObject(dd, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif - Q_D(QAbstractTransition); - d->targetStates = targets; + setTargetStates(targets); } /*! @@ -229,9 +187,6 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, */ QAbstractTransition::~QAbstractTransition() { -#ifdef QT_STATEMACHINE_SOLUTION - delete d_ptr; -#endif } /*! @@ -265,7 +220,7 @@ void QAbstractTransition::setTargetState(QAbstractState* target) if (!target) d->targetStates.clear(); else - d->targetStates = QList<QAbstractState*>() << target; + setTargetStates(QList<QAbstractState*>() << target); } /*! @@ -275,7 +230,13 @@ void QAbstractTransition::setTargetState(QAbstractState* target) QList<QAbstractState*> QAbstractTransition::targetStates() const { Q_D(const QAbstractTransition); - return d->targetStates; + QList<QAbstractState*> result; + for (int i = 0; i < d->targetStates.size(); ++i) { + QAbstractState *target = d->targetStates.at(i); + if (target) + result.append(target); + } + return result; } /*! @@ -284,7 +245,22 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets) { Q_D(QAbstractTransition); - d->targetStates = targets; + + for (int i=0; i<targets.size(); ++i) { + QAbstractState *target = targets.at(i); + if (!target) { + qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null"); + return; + } + if (target->machine() != 0 && target->machine()->rootState() == target) { + qWarning("QAbstractTransition::setTargetStates: root state cannot be target of transition"); + return; + } + } + + d->targetStates.clear(); + for (int i = 0; i < targets.size(); ++i) + d->targetStates.append(targets.at(i)); } /*! diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index e207944..c63d55a 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -88,16 +88,13 @@ public: #endif protected: - virtual bool eventTest(QEvent *event) const = 0; + virtual bool eventTest(QEvent *event) = 0; virtual void onTransition(QEvent *event) = 0; bool event(QEvent *e); protected: -#ifdef QT_STATEMACHINE_SOLUTION - QAbstractTransitionPrivate *d_ptr; -#endif QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent); QAbstractTransition(QAbstractTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent); diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h index b4e1c88..a6db220 100644 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ b/src/corelib/statemachine/qabstracttransition_p.h @@ -53,11 +53,10 @@ // We mean it. // -#ifndef QT_STATEMACHINE_SOLUTION #include <private/qobject_p.h> -#endif #include <QtCore/qlist.h> +#include <QtCore/qpointer.h> QT_BEGIN_NAMESPACE @@ -67,9 +66,7 @@ class QStateMachine; class QAbstractTransition; class Q_CORE_EXPORT QAbstractTransitionPrivate -#ifndef QT_STATEMACHINE_SOLUTION : public QObjectPrivate -#endif { Q_DECLARE_PUBLIC(QAbstractTransition) public: @@ -78,20 +75,16 @@ public: static QAbstractTransitionPrivate *get(QAbstractTransition *q); static const QAbstractTransitionPrivate *get(const QAbstractTransition *q); - bool callEventTest(QEvent *e) const; + bool callEventTest(QEvent *e); void callOnTransition(QEvent *e); QState *sourceState() const; QStateMachine *machine() const; - QList<QAbstractState*> targetStates; + QList<QPointer<QAbstractState> > targetStates; #ifndef QT_NO_ANIMATION QList<QAbstractAnimation*> animations; #endif - -#ifdef QT_STATEMACHINE_SOLUTION - QAbstractTransition *q_ptr; -#endif }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 86259e4..74eb577 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -252,14 +252,10 @@ void QEventTransition::setEventObject(QObject *object) /*! \reimp */ -bool QEventTransition::eventTest(QEvent *event) const +bool QEventTransition::eventTest(QEvent *event) { Q_D(const QEventTransition); -#ifdef QT_STATEMACHINE_SOLUTION - if (event->type() == QEvent::Type(QEvent::User-3)) { -#else if (event->type() == QEvent::Wrapped) { -#endif QWrappedEvent *we = static_cast<QWrappedEvent*>(event); return (we->object() == d->object) && (we->event()->type() == d->eventType); diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index a128cee..3530bdd 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -42,11 +42,7 @@ #ifndef QEVENTTRANSITION_H #define QEVENTTRANSITION_H -#ifndef QT_STATEMACHINE_SOLUTION #include <QtCore/qabstracttransition.h> -#else -#include "qabstracttransition.h" -#endif #include <QtCore/qcoreevent.h> QT_BEGIN_HEADER @@ -60,9 +56,7 @@ class Q_CORE_EXPORT QEventTransition : public QAbstractTransition { Q_OBJECT Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject) -#ifndef QT_STATEMACHINE_SOLUTION Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType) -#endif public: QEventTransition(QState *sourceState = 0); QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0); @@ -77,7 +71,7 @@ public: void setEventType(QEvent::Type type); protected: - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h index eb8aa0f..fa68394 100644 --- a/src/corelib/statemachine/qfinalstate.h +++ b/src/corelib/statemachine/qfinalstate.h @@ -42,11 +42,7 @@ #ifndef QFINALSTATE_H #define QFINALSTATE_H -#ifndef QT_STATEMACHINE_SOLUTION #include <QtCore/qabstractstate.h> -#else -#include "qabstractstate.h" -#endif QT_BEGIN_HEADER diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index d0f75de..a0682bd 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -42,11 +42,7 @@ #ifndef QHISTORYSTATE_H #define QHISTORYSTATE_H -#ifndef QT_STATEMACHINE_SOLUTION #include <QtCore/qabstractstate.h> -#else -#include "qabstractstate.h" -#endif QT_BEGIN_HEADER diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h index d18def8..cf0ea1e 100644 --- a/src/corelib/statemachine/qsignaleventgenerator_p.h +++ b/src/corelib/statemachine/qsignaleventgenerator_p.h @@ -62,11 +62,7 @@ class QStateMachine; class QSignalEventGenerator : public QObject { public: - QSignalEventGenerator( -#ifdef QT_STATEMACHINE_SOLUTION - int signalIndex, -#endif - QStateMachine *parent); + QSignalEventGenerator(QStateMachine *parent); static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; @@ -74,9 +70,6 @@ public: virtual int qt_metacall(QMetaObject::Call, int, void **argv); private: -#ifdef QT_STATEMACHINE_SOLUTION - int signalIndex; -#endif Q_DISABLE_COPY(QSignalEventGenerator) }; diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index d5833bd..4caa917 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -225,14 +225,10 @@ void QSignalTransition::setSignal(const QByteArray &signal) true if the event's sender and signal index match this transition, and returns false otherwise. */ -bool QSignalTransition::eventTest(QEvent *event) const +bool QSignalTransition::eventTest(QEvent *event) { Q_D(const QSignalTransition); -#ifndef QT_STATEMACHINE_SOLUTION if (event->type() == QEvent::Signal) { -#else - if (event->type() == QEvent::Type(QEvent::User-1)) { -#endif if (d->signalIndex == -1) return false; QSignalEvent *se = static_cast<QSignalEvent*>(event); diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index 98a9ae7..b485785 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -42,11 +42,7 @@ #ifndef QSIGNALTRANSITION_H #define QSIGNALTRANSITION_H -#ifndef QT_STATEMACHINE_SOLUTION #include <QtCore/qabstracttransition.h> -#else -#include "qabstracttransition.h" -#endif QT_BEGIN_HEADER @@ -76,7 +72,7 @@ public: void setSignal(const QByteArray &signal); protected: - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 4c9e033..e42e463 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -193,9 +193,6 @@ QList<QAbstractState*> QStatePrivate::childStates() const { QList<QAbstractState*> result; QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif for (it = children.constBegin(); it != children.constEnd(); ++it) { QAbstractState *s = qobject_cast<QAbstractState*>(*it); if (!s || qobject_cast<QHistoryState*>(s)) @@ -209,9 +206,6 @@ QList<QHistoryState*> QStatePrivate::historyStates() const { QList<QHistoryState*> result; QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif for (it = children.constBegin(); it != children.constEnd(); ++it) { QHistoryState *h = qobject_cast<QHistoryState*>(*it); if (h) @@ -224,9 +218,6 @@ QList<QAbstractTransition*> QStatePrivate::transitions() const { QList<QAbstractTransition*> result; QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif for (it = children.constBegin(); it != children.constEnd(); ++it) { QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it); if (t) @@ -280,11 +271,15 @@ QAbstractState *QState::errorState() const void QState::setErrorState(QAbstractState *state) { Q_D(QState); - if (state != 0 && QAbstractStatePrivate::get(state)->machine() != d->machine()) { + if (state != 0 && state->machine() != machine()) { qWarning("QState::setErrorState: error state cannot belong " "to a different state machine"); return; } + if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) { + qWarning("QStateMachine::setErrorState: root state cannot be error state"); + return; + } d->errorState = state; } @@ -301,7 +296,14 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) qWarning("QState::addTransition: cannot add null transition"); return 0; } - const QList<QAbstractState*> &targets = QAbstractTransitionPrivate::get(transition)->targetStates; + + // machine() will always be non-null for root state + if (machine() != 0 && machine()->rootState() == this) { + qWarning("QState::addTransition: cannot add transition from root state"); + return 0; + } + + const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates; for (int i = 0; i < targets.size(); ++i) { QAbstractState *t = targets.at(i); if (!t) { @@ -316,6 +318,8 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) } } transition->setParent(this); + if (machine() != 0 && machine()->configuration().contains(this)) + QStateMachinePrivate::get(machine())->registerTransitions(this); return transition; } @@ -335,6 +339,15 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, qWarning("QState::addTransition: signal cannot be null"); return 0; } + if (!target) { + qWarning("QState::addTransition: cannot add transition to null state"); + return 0; + } + if (*signal && sender->metaObject()->indexOfSignal(signal+1) == -1) { + qWarning("QState::addTransition: no such signal %s::%s", + sender->metaObject()->className(), signal+1); + return 0; + } QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target); addTransition(trans); return trans; @@ -350,7 +363,7 @@ public: : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: void onTransition(QEvent *) {} - bool eventTest(QEvent *) const { return true; } + bool eventTest(QEvent *) { return true; } }; } // namespace @@ -361,9 +374,12 @@ protected: */ QAbstractTransition *QState::addTransition(QAbstractState *target) { + if (!target) { + qWarning("QState::addTransition: cannot add transition to null state"); + return 0; + } UnconditionalTransition *trans = new UnconditionalTransition(target); - addTransition(trans); - return trans; + return addTransition(trans); } /*! diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 73955d7..6729c69 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -42,11 +42,7 @@ #ifndef QSTATE_H #define QSTATE_H -#ifndef QT_STATEMACHINE_SOLUTION #include <QtCore/qabstractstate.h> -#else -#include "qabstractstate.h" -#endif QT_BEGIN_HEADER diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index ff3fb7d..744515b 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -54,10 +54,8 @@ #include "qfinalstate.h" #include "qhistorystate.h" #include "qhistorystate_p.h" -#ifndef QT_STATEMACHINE_SOLUTION #include "private/qobject_p.h" #include "private/qthread_p.h" -#endif #ifndef QT_NO_STATEMACHINE_EVENTFILTER #include "qeventtransition.h" @@ -68,11 +66,7 @@ #ifndef QT_NO_ANIMATION #include "qpropertyanimation.h" #include "qanimationgroup.h" -# ifndef QT_STATEMACHINE_SOLUTION -# include <private/qvariantanimation_p.h> -# else -# include "qvariantanimation_p.h" -# endif +#include <private/qvariantanimation_p.h> #endif #include <QtCore/qmetaobject.h> @@ -89,68 +83,98 @@ QT_BEGIN_NAMESPACE \since 4.6 \ingroup statemachine - The QStateMachine class provides a hierarchical finite state machine based - on \l{Statecharts: A visual formalism for complex systems}{Statecharts} - concepts and notation. QStateMachine is part of \l{The State Machine - Framework}. - - A state machine manages a set of states (QAbstractState objects) and - transitions (QAbstractTransition objects) between those states; the states - and the transitions collectively define a state graph. Once a state graph - has been defined, the state machine can execute it. QStateMachine's - execution algorithm is based on the \l{State Chart XML: State Machine - Notation for Control Abstraction}{State Chart XML (SCXML)} algorithm. - - The QState class provides a state that you can use to set properties and - invoke methods on QObjects when the state is entered or exited. This is + QStateMachine is based on the concepts and notation of + \l{Statecharts: A visual formalism for complex + systems}{Statecharts}. QStateMachine is part of \l{The State + Machine Framework}. + + A state machine manages a set of states (classes that inherit from + QAbstractState) and transitions (descendants of + QAbstractTransition) between those states; these states and + transitions define a state graph. Once a state graph has been + built, the state machine can execute it. \l{QStateMachine}'s + execution algorithm is based on the \l{State Chart XML: State + Machine Notation for Control Abstraction}{State Chart XML (SCXML)} + algorithm. The framework's \l{The State Machine + Framework}{overview} gives several state graphs and the code to + build them. + + The rootState() is the parent of all top-level states in the + machine; it is used, for instance, when the state graph is + deleted. It is created by the machine. + + Use the addState() function to add a state to the state machine. + All top-level states are added to the root state. States are + removed with the removeState() function. Removing states while the + machine is running is discouraged. + + Before the machine can be started, the \l{initialState}{initial + state} must be set. The initial state is the state that the + machine enters when started. You can then start() the state + machine. The started() signal is emitted when the initial state is + entered. + + The machine is event driven and keeps its own event loop. Events + are posted to the machine through postEvent(). Note that this + means that it executes asynchronously, and that it will not + progress without a running event loop. You will normally not have + to post events to the machine directly as Qt's transitions, e.g., + QEventTransition and its subclasses, handle this. But for custom + transitions triggered by events, postEvent() is useful. + + The state machine processes events and takes transitions until a + top-level final state is entered; the state machine then emits the + finished() signal. You can also stop() the state machine + explicitly. The stopped() signal is emitted in this case. + + The following snippet shows a state machine that will finish when a button + is clicked: + + \code + QPushButton button; + + QStateMachine machine; + QState *s1 = new QState(); + s1->assignProperty(&button, "text", "Click me"); + + QFinalState *s2 = new QFinalState(); + s1->addTransition(&button, SIGNAL(clicked()), s2); + + machine.addState(s1); + machine.addState(s2); + machine.setInitialState(s1); + machine.start(); + \endcode + + This code example uses QState, which inherits QAbstractState. The + QState class provides a state that you can use to set properties + and invoke methods on \l{QObject}s when the state is entered or + exited. It also contains convenience functions for adding + transitions, e.g., \l{QSignalTransition}s as in this example. See + the QState class description for further details. + + If an error is encountered, the machine will enter the + \l{errorState}{error state}, which is a special state created by + the machine. The types of errors possible are described by the + \l{QStateMachine::}{Error} enum. After the error state is entered, + the type of the error can be retrieved with error(). The execution + of the state graph will not stop when the error state is entered. + So it is possible to handle the error, for instance, by connecting + to the \l{QAbstractState::}{entered()} signal of the error state. + It is also possible to set a custom error state with + setErrorState(). + + \omit This stuff will be moved elsewhere +This is typically used in conjunction with \l{Signals and Slots}{signals}; the signals determine the flow of the state graph, whereas the states' property assignments and method invocations are the actions. - Use the addState() function to add a state to the state machine; - alternatively, pass the machine's rootState() to the state constructor. Use - the removeState() function to remove a state from the state machine. - - The following snippet shows a state machine that will finish when a button - is clicked: - - \code - QPushButton button; - - QStateMachine machine; - QState *s1 = new QState(); - s1->assignProperty(&button, "text", "Click me"); - - QFinalState *s2 = new QFinalState(); - s1->addTransition(&button, SIGNAL(clicked()), s2); - - machine.addState(s1); - machine.addState(s2); - machine.setInitialState(s1); - machine.start(); - \endcode - - The setInitialState() function sets the state machine's initial state; this - state is entered when the state machine is started. - - The start() function starts the state machine. The state machine executes - asynchronously, i.e. you need to run an event loop in order for it to make - progress. The started() signal is emitted when the state machine has entered - the initial state. - - The state machine processes events and takes transitions until a top-level - final state is entered; the state machine then emits the finished() signal. - - The stop() function stops the state machine. The stopped() signal is emitted - when the state machine has stopped. - The postEvent() function posts an event to the state machine. This is useful when you are using custom events to trigger transitions. + \endomit - The rootState() function returns the state machine's root state. All - top-level states have the root state as their parent. - - \sa QAbstractState, QAbstractTransition + \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework} */ /*! @@ -212,9 +236,7 @@ QStateMachinePrivate::QStateMachinePrivate() globalRestorePolicy = QStateMachine::DoNotRestoreProperties; rootState = 0; initialErrorStateForRoot = 0; -#ifndef QT_STATEMACHINE_SOLUTION signalEventGenerator = 0; -#endif #ifndef QT_NO_ANIMATION animationsEnabled = true; #endif @@ -1011,6 +1033,8 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta } Q_ASSERT(currentErrorState != 0); + Q_ASSERT(currentErrorState != rootState); + QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } @@ -1100,7 +1124,7 @@ public: InitialTransition(QAbstractState *target) : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: - virtual bool eventTest(QEvent *) const { return true; } + virtual bool eventTest(QEvent *) { return true; } virtual void onTransition(QEvent *) {} }; @@ -1222,10 +1246,12 @@ void QStateMachinePrivate::_q_process() break; case Finished: state = NotRunning; + unregisterAllTransitions(); emit q->finished(); break; case Stopped: state = NotRunning; + unregisterAllTransitions(); emit q->stopped(); break; } @@ -1270,8 +1296,6 @@ void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition) #endif } -#ifndef QT_STATEMACHINE_SOLUTION - static int senderSignalIndex(const QObject *sender) { QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject*>(sender)); @@ -1288,8 +1312,6 @@ static int senderSignalIndex(const QObject *sender) return d->currentSender->signal; } -#endif - void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition) { Q_Q(QStateMachine); @@ -1307,14 +1329,12 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio sender->metaObject()->className(), signal.constData()); return; } - QList<int> &connectedSignalIndexes = connections[sender]; - if (!connectedSignalIndexes.contains(signalIndex)) { -#ifndef QT_STATEMACHINE_SOLUTION + QVector<int> &connectedSignalIndexes = connections[sender]; + if (connectedSignalIndexes.size() <= signalIndex) + connectedSignalIndexes.resize(signalIndex+1); + if (connectedSignalIndexes.at(signalIndex) == 0) { if (!signalEventGenerator) signalEventGenerator = new QSignalEventGenerator(q); -#else - QSignalEventGenerator *signalEventGenerator = new QSignalEventGenerator(signalIndex, q); -#endif bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator, signalEventGenerator->metaObject()->methodOffset()); if (!ok) { @@ -1325,8 +1345,8 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio #endif return; } - connectedSignalIndexes.append(signalIndex); } + ++connectedSignalIndexes[signalIndex]; QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex; #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": added signal transition from" << transition->sourceState() @@ -1340,20 +1360,35 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex; if (signalIndex == -1) return; // not registered -#ifndef QT_STATEMACHINE_SOLUTION + QSignalTransitionPrivate::get(transition)->signalIndex = -1; const QObject *sender = QSignalTransitionPrivate::get(transition)->sender; - QList<int> &connectedSignalIndexes = connections[sender]; - Q_ASSERT(connectedSignalIndexes.contains(signalIndex)); - Q_ASSERT(signalEventGenerator != 0); - bool ok = QMetaObject::disconnect(sender, signalIndex, signalEventGenerator, - signalEventGenerator->metaObject()->methodOffset()); - if (ok) { - connectedSignalIndexes.removeOne(signalIndex); - if (connectedSignalIndexes.isEmpty()) + QVector<int> &connectedSignalIndexes = connections[sender]; + Q_ASSERT(connectedSignalIndexes.size() > signalIndex); + Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0); + if (--connectedSignalIndexes[signalIndex] == 0) { + Q_ASSERT(signalEventGenerator != 0); + QMetaObject::disconnect(sender, signalIndex, signalEventGenerator, + signalEventGenerator->metaObject()->methodOffset()); + int sum = 0; + for (int i = 0; i < connectedSignalIndexes.size(); ++i) + sum += connectedSignalIndexes.at(i); + if (sum == 0) connections.remove(sender); - QSignalTransitionPrivate::get(transition)->signalIndex = -1; } -#endif +} + +void QStateMachinePrivate::unregisterAllTransitions() +{ + { + QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState); + for (int i = 0; i < transitions.size(); ++i) + unregisterSignalTransition(transitions.at(i)); + } + { + QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState); + for (int i = 0; i < transitions.size(); ++i) + unregisterEventTransition(transitions.at(i)); + } } #ifndef QT_NO_STATEMACHINE_EVENTFILTER @@ -1369,12 +1404,10 @@ void QStateMachinePrivate::registerEventTransition(QEventTransition *transition) QObject *object = QEventTransitionPrivate::get(transition)->object; if (!object) return; -#ifndef QT_STATEMACHINE_SOLUTION QObjectPrivate *od = QObjectPrivate::get(object); if (!od->eventFilters.contains(q)) -#endif object->installEventFilter(q); - qobjectEvents[object].insert(transition->eventType()); + ++qobjectEvents[object][transition->eventType()]; QEventTransitionPrivate::get(transition)->registered = true; #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": added event transition from" << transition->sourceState() @@ -1389,11 +1422,18 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio if (!QEventTransitionPrivate::get(transition)->registered) return; QObject *object = QEventTransitionPrivate::get(transition)->object; - QSet<QEvent::Type> &events = qobjectEvents[object]; - events.remove(transition->eventType()); - if (events.isEmpty()) { - qobjectEvents.remove(object); - object->removeEventFilter(q); + QHash<QEvent::Type, int> &events = qobjectEvents[object]; + Q_ASSERT(events.value(transition->eventType()) > 0); + if (--events[transition->eventType()] == 0) { + events.remove(transition->eventType()); + int sum = 0; + QHash<QEvent::Type, int>::const_iterator it; + for (it = events.constBegin(); it != events.constEnd(); ++it) + sum += it.value(); + if (sum == 0) { + qobjectEvents.remove(object); + object->removeEventFilter(q); + } } QEventTransitionPrivate::get(transition)->registered = false; } @@ -1402,8 +1442,8 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex, void **argv) { - const QList<int> &connectedSignalIndexes = connections[sender]; - Q_ASSERT(connectedSignalIndexes.contains(signalIndex)); + const QVector<int> &connectedSignalIndexes = connections[sender]; + Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0); const QMetaObject *meta = sender->metaObject(); QMetaMethod method = meta->method(signalIndex); QList<QByteArray> parameterTypes = method.parameterTypes(); @@ -1426,36 +1466,16 @@ void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int sig Constructs a new state machine with the given \a parent. */ QStateMachine::QStateMachine(QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QStateMachinePrivate, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QStateMachinePrivate) -#endif + : QObject(*new QStateMachinePrivate, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! \internal */ QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif + : QObject(dd, parent) { -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif } /*! @@ -1463,9 +1483,6 @@ QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent) */ QStateMachine::~QStateMachine() { -#ifdef QT_STATEMACHINE_SOLUTION - delete d_ptr; -#endif } namespace { @@ -2065,11 +2082,9 @@ int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a) if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: { -#ifndef QT_STATEMACHINE_SOLUTION // ### in Qt 4.6 we can use QObject::senderSignalIndex() int signalIndex = senderSignalIndex(this); Q_ASSERT(signalIndex != -1); -#endif QStateMachine *machine = qobject_cast<QStateMachine*>(parent()); QStateMachinePrivate::get(machine)->handleTransitionSignal(sender(), signalIndex, _a); break; @@ -2081,15 +2096,8 @@ int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a) return _id; } -QSignalEventGenerator::QSignalEventGenerator( -#ifdef QT_STATEMACHINE_SOLUTION - int sigIdx, -#endif - QStateMachine *parent) +QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) : QObject(parent) -#ifdef QT_STATEMACHINE_SOLUTION - , signalIndex(sigIdx) -#endif { } @@ -2120,13 +2128,8 @@ QSignalEventGenerator::QSignalEventGenerator( */ QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex, const QList<QVariant> &arguments) - : -#ifndef QT_STATEMACHINE_SOLUTION - QEvent(QEvent::Signal) -#else - QEvent(QEvent::Type(QEvent::User-1)) -#endif - , m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments) + : QEvent(QEvent::Signal), m_sender(sender), + m_signalIndex(signalIndex), m_arguments(arguments) { } @@ -2185,12 +2188,7 @@ QSignalEvent::~QSignalEvent() and \a event. */ QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) -#ifdef QT_STATEMACHINE_SOLUTION - : QEvent(QEvent::Type(QEvent::User-3)) -#else - : QEvent(QEvent::Wrapped) -#endif - , m_object(object), m_event(event) + : QEvent(QEvent::Wrapped), m_object(object), m_event(event) { } diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 5dc6c0b..2a98a9a 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -42,11 +42,7 @@ #ifndef QSTATEMACHINE_H #define QSTATEMACHINE_H -#ifndef QT_STATEMACHINE_SOLUTION -# include <QtCore/qabstractstate.h> -#else -# include "qabstractstate.h" -#endif +#include <QtCore/qabstractstate.h> #include <QtCore/qlist.h> #include <QtCore/qobject.h> @@ -151,9 +147,6 @@ protected: bool event(QEvent *e); protected: -#ifdef QT_STATEMACHINE_SOLUTION - QStateMachinePrivate *d_ptr; -#endif QStateMachine(QStateMachinePrivate &dd, QObject *parent); private: diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index bb4a78c..dfa5575 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -53,14 +53,13 @@ // We mean it. // -#ifndef QT_STATEMACHINE_SOLUTION #include <private/qobject_p.h> -#endif #include <QtCore/qcoreevent.h> #include <QtCore/qhash.h> #include <QtCore/qlist.h> #include <QtCore/qpair.h> #include <QtCore/qset.h> +#include <QtCore/qvector.h> #include "qstate.h" #include "qstate_p.h" @@ -83,9 +82,7 @@ class QAbstractAnimation; class QStateMachine; class Q_CORE_EXPORT QStateMachinePrivate -#ifndef QT_STATEMACHINE_SOLUTION : public QObjectPrivate -#endif { Q_DECLARE_PUBLIC(QStateMachine) public: @@ -150,6 +147,7 @@ public: void unregisterEventTransition(QEventTransition *transition); #endif void unregisterTransition(QAbstractTransition *transition); + void unregisterAllTransitions(); void handleTransitionSignal(const QObject *sender, int signalIndex, void **args); void scheduleProcess(); @@ -198,12 +196,11 @@ public: #endif // QT_NO_ANIMATION -#ifndef QT_STATEMACHINE_SOLUTION QSignalEventGenerator *signalEventGenerator; -#endif - QHash<const QObject*, QList<int> > connections; + + QHash<const QObject*, QVector<int> > connections; #ifndef QT_NO_STATEMACHINE_EVENTFILTER - QHash<QObject*, QSet<QEvent::Type> > qobjectEvents; + QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents; #endif QHash<int, QEvent*> delayedEvents; @@ -213,10 +210,6 @@ public: }; static const Handler *handler; - -#ifdef QT_STATEMACHINE_SOLUTION - QStateMachine *q_ptr; -#endif }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp new file mode 100644 index 0000000..7db3a5a --- /dev/null +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore 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 "qcontiguouscache.h" +#include <QDebug> + +QT_BEGIN_NAMESPACE + +void QContiguousCacheData::dump() const +{ + qDebug() << "capacity:" << alloc; + qDebug() << "count:" << count; + qDebug() << "start:" << start; + qDebug() << "offset:" << offset; +} + +/*! \class QContiguousCache + \brief The QContiguousCache class is a template class that provides a contiguous cache. + \ingroup tools + \ingroup shared + \reentrant + + The QContiguousCache class provides an efficient way of caching items for + display in a user interface view. Unlike QCache, it adds a restriction + that elements within the cache are contiguous. This has the advantage + of matching how user interface views most commonly request data, as + a set of rows localized around the current scrolled position. This + restriction allows the cache to consume less memory and processor + cycles than QCache. The QContiguousCache class also can provide + an upper bound on memory usage via setCapacity(). + + The simplest way of using a contiguous cache is to use the append() + and prepend(). + +\code +MyRecord record(int row) const +{ + Q_ASSERT(row >= 0 && row < count()); + + while(row > cache.lastIndex()) + cache.append(slowFetchRecord(cache.lastIndex()+1)); + while(row < cache.firstIndex()) + cache.prepend(slowFetchRecord(cache.firstIndex()-1)); + + return cache.at(row); +} +\endcode + + If the cache is full then the item at the opposite end of the cache from + where the new item is appended or prepended will be removed. + + This usage can be further optimized by using the insert() function + in the case where the requested row is a long way from the currently cached + items. If there is a gap between where the new item is inserted and the currently + cached items then the existing cached items are first removed to retain + the contiguous nature of the cache. Hence it is important to take some care then + when using insert() in order to avoid unwanted clearing of the cache. + + The range of valid indexes for the QContiguousCache class are from + 0 to INT_MAX. Calling prepend() such that the first index would become less + than 0 or append() such that the last index would become greater + than INT_MAX can result in the indexes of the cache being invalid. + When the cache indexes are invalid it is important to call + normalizeIndexes() before calling any of containsIndex(), firstIndex(), + lastIndex(), at() or the [] operator. Calling these + functions when the cache has invalid indexes will result in undefined + behavior. The indexes can be checked by using areIndexesValid() + + In most cases the indexes will not exceed 0 to INT_MAX, and + normalizeIndexes() will not need to be used. + + See the \l{Contiguous Cache Example}{Contiguous Cache} example. +*/ + +/*! \fn QContiguousCache::QContiguousCache(int capacity) + + Constructs a cache with the given \a capacity. + + \sa setCapacity() +*/ + +/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QContiguousCache is + \l{implicitly shared}. This makes returning a QContiguousCache from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QContiguousCache::~QContiguousCache() + + Destroys the cache. +*/ + +/*! \fn void QContiguousCache::detach() + + \internal +*/ + +/*! \fn bool QContiguousCache::isDetached() const + + \internal +*/ + +/*! \fn void QContiguousCache::setSharable(bool sharable) + + \internal +*/ + +/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other) + + Assigns \a other to this cache and returns a reference to this cache. +*/ + +/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const + + Returns true if \a other is equal to this cache; otherwise returns false. + + Two caches are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const + + Returns true if \a other is not equal to this cache; otherwise + returns false. + + Two caches are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator==() +*/ + +/*! \fn int QContiguousCache::capacity() const + + Returns the number of items the cache can store before it is full. + When a cache contains a number of items equal to its capacity, adding new + items will cause items farthest from the added item to be removed. + + \sa setCapacity(), size() +*/ + +/*! \fn int QContiguousCache::count() const + + \overload + + Same as size(). +*/ + +/*! \fn int QContiguousCache::size() const + + Returns the number of items contained within the cache. + + \sa capacity() +*/ + +/*! \fn bool QContiguousCache::isEmpty() const + + Returns true if no items are stored within the cache. + + \sa size(), capacity() +*/ + +/*! \fn bool QContiguousCache::isFull() const + + Returns true if the number of items stored within the cache is equal + to the capacity of the cache. + + \sa size(), capacity() +*/ + +/*! \fn int QContiguousCache::available() const + + Returns the number of items that can be added to the cache before it becomes full. + + \sa size(), capacity(), isFull() +*/ + +/*! \fn void QContiguousCache::clear() + + Removes all items from the cache. The capacity is unchanged. +*/ + +/*! \fn void QContiguousCache::setCapacity(int size) + + Sets the capacity of the cache to the given \a size. A cache can hold a + number of items equal to its capacity. When inserting, appending or prepending + items to the cache, if the cache is already full then the item farthest from + the added item will be removed. + + If the given \a size is smaller than the current count of items in the cache + then only the last \a size items from the cache will remain. + + \sa capacity(), isFull() +*/ + +/*! \fn const T &QContiguousCache::at(int i) const + + Returns the item at index position \a i in the cache. \a i must + be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()). + + The indexes in the cache refer to the number of positions the item is from the + first item appended into the cache. That is to say a cache with a capacity of + 100, that has had 150 items appended will have a valid index range of + 50 to 149. This allows inserting and retrieving items into the cache based + on a theoretical infinite list + + \sa firstIndex(), lastIndex(), insert(), operator[]() +*/ + +/*! \fn T &QContiguousCache::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. If + the cache does not contain an item at the given index position \a i + then it will first insert an empty item at that position. + + In most cases it is better to use either at() or insert(). + + Note that using non-const operators can cause QContiguousCache to do a deep + copy. + + \sa insert(), at() +*/ + +/*! \fn const T &QContiguousCache::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! \fn void QContiguousCache::append(const T &value) + + Inserts \a value at the end of the cache. If the cache is already full + the item at the start of the cache will be removed. + + \sa prepend(), insert(), isFull() +*/ + +/*! \fn void QContiguousCache::prepend(const T &value) + + Inserts \a value at the start of the cache. If the cache is already full + the item at the end of the cache will be removed. + + \sa append(), insert(), isFull() +*/ + +/*! \fn void QContiguousCache::insert(int i, const T &value) + + Inserts the \a value at the index position \a i. If the cache already contains + an item at \a i then that value is replaced. If \a i is either one more than + lastIndex() or one less than firstIndex() it is the equivalent to an append() + or a prepend(). + + If the given index \a i is not within the current range of the cache nor adjacent + to the bounds of the cache's index range, the cache is first cleared before + inserting the item. At this point the cache will have a size of 1. It is + worthwhile taking effort to insert items in an order that starts adjacent + to the current index range for the cache. + + The range of valid indexes for the QContiguousCache class are from + 0 to INT_MAX. Inserting outside of this range has undefined behavior. + + + \sa prepend(), append(), isFull(), firstIndex(), lastIndex() +*/ + +/*! \fn bool QContiguousCache::containsIndex(int i) const + + Returns true if the cache's index range includes the given index \a i. + + \sa firstIndex(), lastIndex() +*/ + +/*! \fn int QContiguousCache::firstIndex() const + + Returns the first valid index in the cache. The index will be invalid if the + cache is empty. + + \sa capacity(), size(), lastIndex() +*/ + +/*! \fn int QContiguousCache::lastIndex() const + + Returns the last valid index in the cache. The index will be invalid if the cache is empty. + + \sa capacity(), size(), firstIndex() +*/ + + +/*! \fn T &QContiguousCache::first() + + Returns a reference to the first item in the cache. This function + assumes that the cache isn't empty. + + \sa last(), isEmpty() +*/ + +/*! \fn T &QContiguousCache::last() + + Returns a reference to the last item in the cache. This function + assumes that the cache isn't empty. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QContiguousCache::first() const + + \overload +*/ + +/*! \fn const T& QContiguousCache::last() const + + \overload +*/ + +/*! \fn void QContiguousCache::removeFirst() + + Removes the first item from the cache. This function assumes that + the cache isn't empty. + + \sa removeLast() +*/ + +/*! \fn void QContiguousCache::removeLast() + + Removes the last item from the cache. This function assumes that + the cache isn't empty. + + \sa removeFirst() +*/ + +/*! \fn T QContiguousCache::takeFirst() + + Removes the first item in the cache and returns it. This function + assumes that the cache isn't empty. + + If you don't use the return value, removeFirst() is more efficient. + + \sa takeLast(), removeFirst() +*/ + +/*! \fn T QContiguousCache::takeLast() + + Removes the last item in the cache and returns it. This function + assumes that the cache isn't empty. + + If you don't use the return value, removeLast() is more efficient. + + \sa takeFirst(), removeLast() +*/ + +/*! \fn void QContiguousCache::normalizeIndexes() + + Moves the first index and last index of the cache + such that they point to valid indexes. The function does not modify + the contents of the cache or the ordering of elements within the cache. + + It is provided so that index overflows can be corrected when using the + cache as a circular buffer. + + \code + QContiguousCache<int> cache(10); + cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX + cache.append(2); // cache contains two values but does not have valid indexes. + cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity(). + \endcode + + \sa areIndexesValid(), append(), prepend() +*/ + +/*! \fn bool QContiguousCache::areIndexesValid() const + + Returns whether the indexes for items stored in the cache are valid. + Indexes can become invalid if items are appended after the index position + INT_MAX or prepended before the index position 0. This is only expected + to occur in very long lived circular buffer style usage of the + contiguous cache. Indexes can be made valid again by calling + normalizeIndexs(). + + \sa normalizeIndexes(), append(), prepend() +*/ + +/*! \fn void QContiguousCache::dump() const + + \internal + + Sends information about the cache's internal structure to qDebug() +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h new file mode 100644 index 0000000..5cd1582 --- /dev/null +++ b/src/corelib/tools/qcontiguouscache.h @@ -0,0 +1,424 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore 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 QCONTIGUOUSCACHE_H +#define QCONTIGUOUSCACHE_H + +#include <QtCore/qatomic.h> +#include <limits.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +struct Q_CORE_EXPORT QContiguousCacheData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + void dump() const; +}; + +template <typename T> +struct QContiguousCacheTypedData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + T array[1]; +}; + +template<typename T> +class QContiguousCache { + typedef QContiguousCacheTypedData<T> Data; + union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; }; +public: + explicit QContiguousCache(int capacity = 0); + QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + + inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + QContiguousCache<T> &operator=(const QContiguousCache<T> &other); + bool operator==(const QContiguousCache<T> &other) const; + inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); } + + inline int capacity() const {return d->alloc; } + inline int count() const { return d->count; } + inline int size() const { return d->count; } + + inline bool isEmpty() const { return d->count == 0; } + inline bool isFull() const { return d->count == d->alloc; } + inline int available() const { return d->alloc - d->count; } + + void clear(); + void setCapacity(int size); + + const T &at(int pos) const; + T &operator[](int i); + const T &operator[](int i) const; + + void append(const T &value); + void prepend(const T &value); + void insert(int pos, const T &value); + + inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; } + inline int firstIndex() const { return d->offset; } + inline int lastIndex() const { return d->offset + d->count - 1; } + + inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; } + inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; } + inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; } + inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; } + + void removeFirst(); + T takeFirst(); + void removeLast(); + T takeLast(); + + inline bool areIndexesValid() const + { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; } + + inline void normalizeIndexes() { d->offset = d->start; } + // debug + void dump() const { p->dump(); } +private: + void detach_helper(); + + QContiguousCacheData *malloc(int aalloc); + void free(Data *x); + int sizeOfTypedData() { + // this is more or less the same as sizeof(Data), except that it doesn't + // count the padding at the end + return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this); + } +}; + +template <typename T> +void QContiguousCache<T>::detach_helper() +{ + union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x; + + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->count = d->count; + x.d->start = d->start; + x.d->offset = d->offset; + x.d->alloc = d->alloc; + x.d->sharable = true; + + T *dest = x.d->array + x.d->start; + T *src = d->array + d->start; + int count = x.d->count; + while (count--) { + if (QTypeInfo<T>::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + dest++; + if (dest == x.d->array + x.d->alloc) + dest = x.d->array; + src++; + if (src == d->array + d->alloc) + src = d->array; + } + + if (!d->ref.deref()) + free(d); + d = x.d; +} + +template <typename T> +void QContiguousCache<T>::setCapacity(int asize) +{ + if (asize == d->alloc) + return; + detach(); + union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x; + x.p = malloc(asize); + x.d->alloc = asize; + x.d->count = qMin(d->count, asize); + x.d->offset = d->offset + d->count - x.d->count; + x.d->start = x.d->offset % x.d->alloc; + T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; + T *src = d->array + (d->start + d->count-1) % d->alloc; + int count = x.d->count; + while (count--) { + if (QTypeInfo<T>::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + if (dest == x.d->array) + dest = x.d->array + x.d->alloc; + dest--; + if (src == d->array) + src = d->array + d->alloc; + src--; + } + /* free old */ + free(d); + d = x.d; +} + +template <typename T> +void QContiguousCache<T>::clear() +{ + if (d->ref == 1) { + if (QTypeInfo<T>::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + d->count = d->start = d->offset = 0; + } else { + union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x; + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->alloc = d->alloc; + x.d->count = x.d->start = x.d->offset = 0; + x.d->sharable = true; + if (!d->ref.deref()) free(d); + d = x.d; + } +} + +template <typename T> +inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc) +{ + return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); +} + +template <typename T> +QContiguousCache<T>::QContiguousCache(int capacity) +{ + p = malloc(capacity); + d->ref = 1; + d->alloc = capacity; + d->count = d->start = d->offset = 0; + d->sharable = true; +} + +template <typename T> +QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = other.d; + if (!d->sharable) + detach_helper(); + return *this; +} + +template <typename T> +bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const +{ + if (other.d == d) + return true; + if (other.d->start != d->start + || other.d->count != d->count + || other.d->offset != d->offset + || other.d->alloc != d->alloc) + return false; + for (int i = firstIndex(); i <= lastIndex(); ++i) + if (!(at(i) == other.at(i))) + return false; + return true; +} + +template <typename T> +void QContiguousCache<T>::free(Data *x) +{ + if (QTypeInfo<T>::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + qFree(x); +} +template <typename T> +void QContiguousCache<T>::append(const T &value) +{ + detach(); + if (QTypeInfo<T>::isComplex) { + if (d->count == d->alloc) + (d->array + (d->start+d->count) % d->alloc)->~T(); + new (d->array + (d->start+d->count) % d->alloc) T(value); + } else { + d->array[(d->start+d->count) % d->alloc] = value; + } + + if (d->count == d->alloc) { + d->start++; + d->start %= d->alloc; + d->offset++; + } else { + d->count++; + } +} + +template<typename T> +void QContiguousCache<T>::prepend(const T &value) +{ + detach(); + if (d->start) + d->start--; + else + d->start = d->alloc-1; + d->offset--; + + if (d->count != d->alloc) + d->count++; + else + if (d->count == d->alloc) + (d->array + d->start)->~T(); + + if (QTypeInfo<T>::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; +} + +template<typename T> +void QContiguousCache<T>::insert(int pos, const T &value) +{ + Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range"); + detach(); + if (containsIndex(pos)) { + if(QTypeInfo<T>::isComplex) + new (d->array + pos % d->alloc) T(value); + else + d->array[pos % d->alloc] = value; + } else if (pos == d->offset-1) + prepend(value); + else if (pos == d->offset+d->count) + append(value); + else { + // we don't leave gaps. + clear(); + d->offset = pos; + d->start = pos % d->alloc; + d->count = 1; + if (QTypeInfo<T>::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; + } +} + +template <typename T> +inline const T &QContiguousCache<T>::at(int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; } +template <typename T> +inline const T &QContiguousCache<T>::operator[](int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; } + +template <typename T> +inline T &QContiguousCache<T>::operator[](int pos) +{ + detach(); + if (!containsIndex(pos)) + insert(pos, T()); + return d->array[pos % d->alloc]; +} + +template <typename T> +inline void QContiguousCache<T>::removeFirst() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo<T>::isComplex) + (d->array + d->start)->~T(); + d->start = (d->start + 1) % d->alloc; + d->offset++; +} + +template <typename T> +inline void QContiguousCache<T>::removeLast() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo<T>::isComplex) + (d->array + (d->start + d->count) % d->alloc)->~T(); +} + +template <typename T> +inline T QContiguousCache<T>::takeFirst() +{ T t = first(); removeFirst(); return t; } + +template <typename T> +inline T QContiguousCache<T>::takeLast() +{ T t = last(); removeLast(); return t; } + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 21d98b5..2313e0e 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -379,6 +379,107 @@ void QHashData::checkSanity() #endif /*! + \fn uint qHash(const QPair<T1, T2> &key) + \since 4.3 + \relates QHash + + Returns the hash value for the \a key. + + Types \c T1 and \c T2 must be supported by qHash(). +*/ + +/*! \fn uint qHash(char key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uchar key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(signed char key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ushort key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(short key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uint key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(int key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ulong key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(long key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(quint64 key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(qint64 key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(QChar key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QByteArray &key) + \fn uint qHash(const QBitArray &key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QString &key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const T *key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \class QHash \brief The QHash class is a template class that provides a hash-table-based dictionary. @@ -401,7 +502,8 @@ void QHashData::checkSanity() key. With QHash, the items are arbitrarily ordered. \i The key type of a QMap must provide operator<(). The key type of a QHash must provide operator==() and a global - \l{qHash()}{qHash}(Key) function. + hash function called qHash() (see the related non-member + functions). \endlist Here's an example QHash with QString keys and \c int values: @@ -732,7 +834,6 @@ void QHashData::checkSanity() */ /*! \fn const T QHash::value(const Key &key, const T &defaultValue) const - \overload If the hash contains no item with the given \a key, the function returns @@ -1490,121 +1591,6 @@ void QHashData::checkSanity() \sa operator+=(), operator-() */ -/*! \fn uint qHash(char key) - \relates QHash - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(uchar key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(signed char key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(ushort key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(short key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(uint key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(int key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(ulong key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(long key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(quint64 key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(qint64 key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(QChar key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const QByteArray &key) - \fn uint qHash(const QBitArray &key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const QString &key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! \fn uint qHash(const T *key) - \relates QHash - \overload - - Returns the hash value for the \a key. -*/ - -/*! - \fn uint qHash(const QPair<T1, T2> &key) - \relates QHash - \since 4.3 - - Returns the hash value for the \a key. - - Types \c T1 and \c T2 must be supported by qHash(). -*/ - /*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash) \relates QHash diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index eed4ba9..02cc497 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -74,6 +74,52 @@ public: return buffers.isEmpty() ? 0 : (buffers.first().constData() + head); } + // access the bytes at a specified position + // the out-variable length will contain the amount of bytes readable + // from there, e.g. the amount still the same QByteArray + inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const { + if (buffers.isEmpty()) { + length = 0; + return 0; + } + + if (pos >= bufferSize) { + length = 0; + return 0; + } + + // special case: it is in the first buffer + int nextDataBlockSizeValue = nextDataBlockSize(); + if (pos - head < nextDataBlockSizeValue) { + length = nextDataBlockSizeValue - pos; + return buffers.at(0).constData() + head + pos; + } + + // special case: we only had one buffer and tried to read over it + if (buffers.length() == 1) { + length = 0; + return 0; + } + + // skip the first + pos -= nextDataBlockSizeValue; + + // normal case: it is somewhere in the second to the-one-before-the-tailBuffer + for (int i = 1; i < tailBuffer; i++) { + if (pos >= buffers[i].size()) { + pos -= buffers[i].size(); + continue; + } + + length = buffers[i].length() - pos; + return buffers[i].constData() + pos; + } + + // it is in the tail buffer + length = tail - pos; + return buffers[tailBuffer].constData() + pos; + } + inline void free(int bytes) { bufferSize -= bytes; if (bufferSize < 0) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 375d672..c3649e3 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -743,7 +743,9 @@ int QString::grow(int size) /*! \since 4.2 - Returns a copy of the \a string string encoded in ucs4. + Returns a copy of the \a string, where the encoding of \a string depends on + the size of wchar. If wchar is 4 bytes, the \a string is interpreted as ucs-4, + if wchar is 2 bytes it is interpreted as ucs-2. If \a size is -1 (default), the \a string has to be 0 terminated. diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp index 78ce7bd..ee4f73c 100644 --- a/src/corelib/tools/qtimeline.cpp +++ b/src/corelib/tools/qtimeline.cpp @@ -211,7 +211,9 @@ void QTimeLinePrivate::setCurrentTime(int msecs) valueForTime() and emitting valueChanged(). By default, valueForTime() applies an interpolation algorithm to generate these value. You can choose from a set of predefined timeline algorithms by calling - setCurveShape(). By default, QTimeLine uses the EaseInOut curve shape, + setCurveShape(). + + Note that by default, QTimeLine uses the EaseInOut curve shape, which provides a value that grows slowly, then grows steadily, and finally grows slowly. For a custom timeline, you can reimplement valueForTime(), in which case QTimeLine's curveShape property is ignored. diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 41557f0..2a1c1fc 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -20,6 +20,7 @@ HEADERS += \ tools/qlocale_p.h \ tools/qlocale_data_p.h \ tools/qmap.h \ + tools/qcontiguouscache.h \ tools/qpodlist_p.h \ tools/qpoint.h \ tools/qqueue.h \ @@ -55,6 +56,7 @@ SOURCES += \ tools/qlocale.cpp \ tools/qpoint.cpp \ tools/qmap.cpp \ + tools/qcontiguouscache.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ tools/qshareddata.cpp \ diff --git a/src/declarative/3rdparty/qlistmodelinterface.h b/src/declarative/3rdparty/qlistmodelinterface.h index 19284ca..44c4a24 100644 --- a/src/declarative/3rdparty/qlistmodelinterface.h +++ b/src/declarative/3rdparty/qlistmodelinterface.h @@ -42,9 +42,9 @@ #ifndef QLISTMODELINTERFACE_H #define QLISTMODELINTERFACE_H -#include <QHash> -#include <QVariant> -#include <qfxglobal.h> +#include <QtCore/QHash> +#include <QtCore/QVariant> +#include <QtDeclarative/qfxglobal.h> QT_BEGIN_HEADER diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index e1dd0e8..cd50945 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -621,8 +621,10 @@ QSimpleCanvas::~QSimpleCanvas() void QSimpleCanvasPrivate::paint(QPainter &p) { #if defined(QFX_RENDER_QPAINTER) - if (!isSetup) + if (!isSetup) { + ++paintVersion; root->d_func()->setupPainting(0, q->rect()); + } lrpTimer.start(); @@ -920,6 +922,7 @@ bool QSimpleCanvas::event(QEvent *e) unsigned int zero = 0; d->root->d_func()->setupPainting(0, rect(), &zero); #else + ++d->paintVersion; d->root->d_func()->setupPainting(0, rect()); #endif diff --git a/src/declarative/canvas/qsimplecanvas.h b/src/declarative/canvas/qsimplecanvas.h index d57ada4..880fae0 100644 --- a/src/declarative/canvas/qsimplecanvas.h +++ b/src/declarative/canvas/qsimplecanvas.h @@ -42,7 +42,7 @@ #ifndef QSIMPLECANVAS_H #define QSIMPLECANVAS_H -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> #ifdef QFX_RENDER_OPENGL #include <QtGui/qmatrix4x4.h> diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h index 7bc7330..9c3408e 100644 --- a/src/declarative/canvas/qsimplecanvas_p.h +++ b/src/declarative/canvas/qsimplecanvas_p.h @@ -112,6 +112,7 @@ public: #if defined(QFX_RENDER_OPENGL) ,egl(q, this), basicShadersInstance(0) #endif + , paintVersion(1) { } @@ -190,6 +191,7 @@ public: void release(QGLFramebufferObject *); void paintGL(); #endif + int paintVersion; }; #endif diff --git a/src/declarative/canvas/qsimplecanvas_software.cpp b/src/declarative/canvas/qsimplecanvas_software.cpp index 194024d..dd5e201 100644 --- a/src/declarative/canvas/qsimplecanvas_software.cpp +++ b/src/declarative/canvas/qsimplecanvas_software.cpp @@ -41,6 +41,7 @@ #include "qsimplecanvas.h" #include "qsimplecanvasitem_p.h" +#include "qsimplecanvas_p.h" QT_BEGIN_NAMESPACE @@ -48,57 +49,87 @@ QRect QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding { Q_Q(QSimpleCanvasItem); - QRectF boundingRectActive = q->boundingRect(); - QRect rv = - data()->transformActive.mapRect(boundingRectActive).toAlignedRect() & bounding; + bool hasContents = options & QSimpleCanvasItem::HasContents; + + QRect rv; + + if (hasContents || q->clip()) { + QRectF boundingRectActive = q->boundingRect(); + rv = data()->transformActive.mapRect(boundingRectActive).toAlignedRect() & bounding; + } + + data()->doNotPaint = rv.isEmpty(); + data()->doNotPaintChildren = data()->doNotPaint && q->clip(); QRect myBounding = bounding; if (q->clip()) myBounding &= rv; - for (int ii = 0; ii < children.count(); ++ii) { - QSimpleCanvasItem *child = children.at(ii); - - qreal visible = child->visible(); - child->d_func()->data()->activeOpacity = data()->activeOpacity; - if (visible != 1) - child->d_func()->data()->activeOpacity *= visible; - - if (child->d_func()->data()->activeOpacity != 0) { - // Calculate child's transform - qreal x = child->x(); - qreal y = child->y(); - qreal scale = child->scale(); - QSimpleCanvasItem::Flip flip = child->flip(); - - QSimpleCanvas::Matrix &am = child->d_func()->data()->transformActive; - am = data()->transformActive; - if (x != 0 || y != 0) - am.translate(x, y); - if (scale != 1) { - QPointF to = child->d_func()->transformOrigin(); - if (to.x() != 0. || to.y() != 0.) - am.translate(to.x(), to.y()); - am.scale(scale, scale); - if (to.x() != 0. || to.y() != 0.) - am.translate(-to.x(), -to.y()); - } - - if (child->d_func()->data()->transformUser) - am = *child->d_func()->data()->transformUser * am; + if (!data()->doNotPaintChildren) { + for (int ii = 0; ii < children.count(); ++ii) { + QSimpleCanvasItem *child = children.at(ii); + + int childVersion = version; + if (!child->d_func()->data()->transformValid) + childVersion = canvas->d->paintVersion; + + bool recalcNeeded = + (childVersion > child->d_func()->data()->transformVersion); + + if (recalcNeeded) { + qreal visible = child->visible(); + child->d_func()->data()->activeOpacity = data()->activeOpacity; + if (visible != 1) + child->d_func()->data()->activeOpacity *= visible; + } + + if (child->d_func()->data()->activeOpacity != 0) { + if (recalcNeeded) { + // Calculate child's transform + qreal x = child->x(); + qreal y = child->y(); + qreal scale = child->scale(); + QSimpleCanvasItem::Flip flip = child->flip(); + + QSimpleCanvas::Matrix &am = + child->d_func()->data()->transformActive; + am = data()->transformActive; + if (x != 0 || y != 0) + am.translate(x, y); + if (scale != 1) { + QPointF to = child->d_func()->transformOrigin(); + if (to.x() != 0. || to.y() != 0.) + am.translate(to.x(), to.y()); + am.scale(scale, scale); + if (to.x() != 0. || to.y() != 0.) + am.translate(-to.x(), -to.y()); + } + + if (child->d_func()->data()->transformUser) + am = *child->d_func()->data()->transformUser * am; + + if (flip) { + QRectF br = child->boundingRect(); + am.translate(br.width() / 2., br.height() / 2); + am.scale((flip & QSimpleCanvasItem::HorizontalFlip)?-1:1, + (flip & QSimpleCanvasItem::VerticalFlip)?-1:1); + am.translate(-br.width() / 2., -br.height() / 2); + } + child->d_func()->data()->transformValid = true; + child->d_func()->data()->transformVersion = childVersion; + } + rv |= child->d_func()->setupPainting(child->d_func()->data()->transformVersion, myBounding); + } + } + } - if (flip) { - QRectF br = child->boundingRect(); - am.translate(br.width() / 2., br.height() / 2); - am.scale((flip & QSimpleCanvasItem::HorizontalFlip)?-1:1, - (flip & QSimpleCanvasItem::VerticalFlip)?-1:1); - am.translate(-br.width() / 2., -br.height() / 2); - } - child->d_func()->data()->transformValid = true; - rv |= child->d_func()->setupPainting(version, myBounding); + data()->lastPaintRect = rv; + if (!data()->doNotPaintChildren) { + if (!bounding.intersects(rv)) { + data()->doNotPaintChildren = true; + data()->doNotPaint = true; } } - - data()->lastPaintRect = rv; + return rv; } @@ -153,22 +184,28 @@ void QSimpleCanvasItemPrivate::paint(QPainter &p) zOrderChildren(); int upto = 0; - for (upto = 0; upto < children.count(); ++upto) { - QSimpleCanvasItem *c = children.at(upto); - if (c->z() < 0) { - paintChild(p, c); - } else { - break; + if (!data()->doNotPaintChildren) { + for (upto = 0; upto < children.count(); ++upto) { + QSimpleCanvasItem *c = children.at(upto); + if (c->z() < 0) { + paintChild(p, c); + } else { + break; + } } } - p.setWorldTransform(data()->transformActive); - q->paintContents(p); - - for (; upto < children.count(); ++upto) { - QSimpleCanvasItem *c = children.at(upto); - paintChild(p, c); - } + if (!data()->doNotPaint) { + p.setWorldTransform(data()->transformActive); + q->paintContents(p); + } + + if (!data()->doNotPaintChildren) { + for (; upto < children.count(); ++upto) { + QSimpleCanvasItem *c = children.at(upto); + paintChild(p, c); + } + } if (clip) p.restore(); diff --git a/src/declarative/canvas/qsimplecanvasfilter.h b/src/declarative/canvas/qsimplecanvasfilter.h index cb75ddf..d05dc7e 100644 --- a/src/declarative/canvas/qsimplecanvasfilter.h +++ b/src/declarative/canvas/qsimplecanvasfilter.h @@ -43,9 +43,9 @@ #define QSIMPLECANVASFILTER_H #include <QtCore/qobject.h> -#include <qfxglobal.h> -#include <qsimplecanvasitem.h> -#include <qsimplecanvas.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qsimplecanvasitem.h> +#include <QtDeclarative/qsimplecanvas.h> QT_BEGIN_HEADER diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index 12c725c..3666b82 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -50,8 +50,9 @@ QT_BEGIN_NAMESPACE QSimpleCanvasItemData::QSimpleCanvasItemData() : buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip), - dirty(false), transformValid(true), x(0), y(0), z(0), visible(1), - transformUser(0), activeOpacity(1) + dirty(false), transformValid(true), doNotPaint(false), + doNotPaintChildren(false), x(0), y(0), z(0), visible(1), + transformUser(0), transformVersion(0), activeOpacity(1) { } @@ -180,10 +181,18 @@ void QSimpleCanvasItem::childrenChanged() { } +void QSimpleCanvasItem::setPaintMargin(qreal margin) +{ + Q_D(QSimpleCanvasItem); + if (margin < d->paintmargin) + update(); // schedule repaint of old boundingRect + d->paintmargin = margin; +} + QRectF QSimpleCanvasItem::boundingRect() const { Q_D(const QSimpleCanvasItem); - return QRectF(0., 0., d->width, d->height); + return QRectF(-d->paintmargin, -d->paintmargin, d->width+d->paintmargin*2, d->height+d->paintmargin*2); } void QSimpleCanvasItem::paintContents(QPainter &) @@ -934,8 +943,6 @@ QRectF QSimpleCanvasItem::mapToScene(const QRectF &r) const } } -int QSimpleCanvasItemPrivate::nextTransformVersion = 1; - void QSimpleCanvasItemPrivate::freshenTransforms() const { if (freshenNeeded()) @@ -1506,11 +1513,8 @@ void QSimpleCanvasItemPrivate::convertToGraphicsItem(QGraphicsItem *parent) q->setClipType(clip); - for (int ii = 0; ii < children.count(); ++ii) { + for (int ii = 0; ii < children.count(); ++ii) static_cast<QSimpleCanvasItemPrivate*>(children.at(ii)->d_ptr)->convertToGraphicsItem(graphicsItem); - if (children.at(ii)->z() == 0) - children.at(ii)->setZ(ii); - } } /*! diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index cab8492..cf23fc6 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -47,13 +47,13 @@ #include <QtDeclarative/qsimplecanvas.h> #include <QtCore/qobject.h> #include <QtGui/qgraphicsitem.h> -class QPainter; QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QPainter; class QRect; class QSimpleCanvas; class QMouseEvent; @@ -183,6 +183,7 @@ public: }; + void setPaintMargin(qreal margin); QRectF boundingRect() const; virtual void paintContents(QPainter &); virtual void paintGLContents(GLPainter &); diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h index cfe0bba..f0b44e0 100644 --- a/src/declarative/canvas/qsimplecanvasitem_p.h +++ b/src/declarative/canvas/qsimplecanvasitem_p.h @@ -92,6 +92,8 @@ public: QSimpleCanvasItem::Flip flip:2; bool dirty:1; bool transformValid:1; + bool doNotPaint:1; + bool doNotPaintChildren:1; qreal x; qreal y; @@ -100,6 +102,7 @@ public: QSimpleCanvas::Matrix *transformUser; QSimpleCanvas::Matrix transformActive; + int transformVersion; float activeOpacity; @@ -139,7 +142,7 @@ public: focusable(false), wantsActiveFocusPanelPendingCanvas(false), hasBeenActiveFocusPanel(false), hasFocus(false), hasActiveFocus(false), needsZOrder(false), - widthValid(false), heightValid(false), width(0), height(0), scale(1), + widthValid(false), heightValid(false), width(0), height(0), paintmargin(0), scale(1), graphicsItem(0), data_ptr(0) { } @@ -173,6 +176,7 @@ public: qreal width; qreal height; + qreal paintmargin; qreal scale; QSimpleGraphicsItem *graphicsItem; @@ -236,7 +240,6 @@ public: #endif void zOrderChildren(); - static int nextTransformVersion; bool freshenNeeded() const; void doFreshenTransforms() const; diff --git a/src/declarative/extra/qfxintegermodel.h b/src/declarative/extra/qfxintegermodel.h index 3a48a56..2f5c756 100644 --- a/src/declarative/extra/qfxintegermodel.h +++ b/src/declarative/extra/qfxintegermodel.h @@ -42,9 +42,9 @@ #ifndef QFXINTMODEL_H #define QFXINTMODEL_H -#include <QObject> -#include "qml.h" -#include <qlistmodelinterface.h> +#include <QtCore/QObject> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qlistmodelinterface.h> QT_BEGIN_HEADER diff --git a/src/declarative/extra/qmlnumberformatter.h b/src/declarative/extra/qmlnumberformatter.h index e053be5..cdd6b58 100644 --- a/src/declarative/extra/qmlnumberformatter.h +++ b/src/declarative/extra/qmlnumberformatter.h @@ -42,8 +42,8 @@ #ifndef QMLNUMBERFORMATTER_H #define QMLNUMBERFORMATTER_H -#include <qml.h> -#include "qnumberformat.h" +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qnumberformat.h> QT_BEGIN_HEADER diff --git a/src/declarative/extra/qmlsqlconnection.h b/src/declarative/extra/qmlsqlconnection.h index 2cc5774..0fff1b0 100644 --- a/src/declarative/extra/qmlsqlconnection.h +++ b/src/declarative/extra/qmlsqlconnection.h @@ -42,8 +42,8 @@ #ifndef QMLSQLCONNECTION_H #define QMLSQLCONNECTION_H -#include <qml.h> -#include <QSqlDatabase> +#include <QtDeclarative/qml.h> +#include <QtSql/QSqlDatabase> QT_BEGIN_HEADER diff --git a/src/declarative/extra/qmlsqlquery.h b/src/declarative/extra/qmlsqlquery.h index 984483c..3fff127 100644 --- a/src/declarative/extra/qmlsqlquery.h +++ b/src/declarative/extra/qmlsqlquery.h @@ -42,8 +42,8 @@ #ifndef QMLSQLQUERYMODEL_H #define QMLSQLQUERYMODEL_H -#include <qml.h> -#include <QListModelInterface> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/QListModelInterface> QT_BEGIN_HEADER diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h index 1fbe923..f837040 100644 --- a/src/declarative/extra/qmlxmllistmodel.h +++ b/src/declarative/extra/qmlxmllistmodel.h @@ -42,8 +42,8 @@ #ifndef QMLXMLLISTMODEL_H #define QMLXMLLISTMODEL_H -#include <qml.h> -#include <QListModelInterface> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/QListModelInterface> QT_BEGIN_HEADER diff --git a/src/declarative/extra/qnumberformat.h b/src/declarative/extra/qnumberformat.h index 6ee333c..75224ec 100644 --- a/src/declarative/extra/qnumberformat.h +++ b/src/declarative/extra/qnumberformat.h @@ -42,9 +42,9 @@ #ifndef NUMBERFORMAT_H #define NUMBERFORMAT_H -#include "qml.h" -#include <QtGui> - +#include <QtDeclarative/qml.h> +#include <QtCore/QLocale> +#include <QtCore/QTime> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp index 53d0187..235511f 100644 --- a/src/declarative/fx/qfxanchors.cpp +++ b/src/declarative/fx/qfxanchors.cpp @@ -41,6 +41,7 @@ #include "qfxanchors_p.h" #include "qfxitem.h" +#include "qfxitem_p.h" #include <QDebug> #include <QtDeclarative/qmlinfo.h> #include <QtDeclarative/qmlbindablevalue.h> @@ -132,22 +133,175 @@ static qreal adjustedPosition(QFxItem *item, QFxAnchorLine::AnchorLine anchorLin QFxAnchors::QFxAnchors(QObject *parent) : QObject(*new QFxAnchorsPrivate(), parent) { - } -void QFxAnchors::fillChanged() +QFxAnchors::~QFxAnchors() { Q_D(QFxAnchors); - if (!d->fill) + d->remDepend(d->fill); + d->remDepend(d->centeredIn); + d->remDepend(d->left.item); + d->remDepend(d->right.item); + d->remDepend(d->top.item); + d->remDepend(d->bottom.item); + d->remDepend(d->vCenter.item); + d->remDepend(d->hCenter.item); +} + +void QFxAnchorsPrivate::fillChanged() +{ + if (!fill || !isItemComplete()) + return; + + if (fill == item->itemParent()) { //child-parent + setItemPos(QPointF(leftMargin, topMargin)); + } else if (fill->itemParent() == item->itemParent()) { //siblings + setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin)); + } + setItemWidth(fill->width()-leftMargin-rightMargin); + setItemHeight(fill->height()-topMargin-bottomMargin); +} + +void QFxAnchorsPrivate::centeredInChanged() +{ + if (!centeredIn || fill || !isItemComplete()) return; - if (d->fill == d->item->itemParent()) { //child-parent - d->item->setPos(QPointF(leftMargin(), topMargin())); - } else if (d->fill->itemParent() == d->item->itemParent()) { //siblings - d->item->setPos(QPointF(d->fill->x()+leftMargin(), d->fill->y()+topMargin())); + if (centeredIn == item->itemParent()) { + QPointF p((item->itemParent()->width() - item->width()) / 2., + (item->itemParent()->height() - item->height()) / 2.); + setItemPos(p); + + } else if (centeredIn->itemParent() == item->itemParent()) { + + QPointF p(centeredIn->x() + (centeredIn->width() - item->width()) / 2., + centeredIn->y() + (centeredIn->height() - item->height()) / 2.); + setItemPos(p); + } +} + +void QFxAnchorsPrivate::clearItem(QFxItem *item) +{ + if (fill == item) + fill = 0; + if (centeredIn == item) + centeredIn = 0; + if (left.item == item) { + left.item = 0; + usedAnchors &= ~QFxAnchors::HasLeftAnchor; + } + if (right.item == item) { + right.item = 0; + usedAnchors &= ~QFxAnchors::HasRightAnchor; + } + if (top.item == item) { + top.item = 0; + usedAnchors &= ~QFxAnchors::HasTopAnchor; + } + if (bottom.item == item) { + bottom.item = 0; + usedAnchors &= ~QFxAnchors::HasBottomAnchor; + } + if (vCenter.item == item) { + vCenter.item = 0; + usedAnchors &= ~QFxAnchors::HasVCenterAnchor; + } + if (hCenter.item == item) { + hCenter.item = 0; + usedAnchors &= ~QFxAnchors::HasHCenterAnchor; + } +} + +void QFxAnchorsPrivate::addDepend(QFxItem *item) +{ + Q_Q(QFxAnchors); + if (!item) + return; + QFxItemPrivate *p = + static_cast<QFxItemPrivate *>(QObjectPrivate::get(item)); + p->dependantAnchors.append(q); +} + +void QFxAnchorsPrivate::remDepend(QFxItem *item) +{ + Q_Q(QFxAnchors); + if (!item) + return; + QFxItemPrivate *p = + static_cast<QFxItemPrivate *>(QObjectPrivate::get(item)); + p->dependantAnchors.removeAll(q); +} + +bool QFxAnchorsPrivate::isItemComplete() const +{ + return item->isComponentComplete(); +} + +void QFxAnchorsPrivate::setItemHeight(qreal v) +{ + updatingMe = true; + item->setHeight(v); + updatingMe = false; +} + +void QFxAnchorsPrivate::setItemWidth(qreal v) +{ + updatingMe = true; + item->setWidth(v); + updatingMe = false; +} + +void QFxAnchorsPrivate::setItemX(qreal v) +{ + updatingMe = true; + item->setX(v); + updatingMe = false; +} + +void QFxAnchorsPrivate::setItemY(qreal v) +{ + updatingMe = true; + item->setY(v); + updatingMe = false; +} + +void QFxAnchorsPrivate::setItemPos(const QPointF &v) +{ + updatingMe = true; + item->setPos(v); + updatingMe = false; +} + +void QFxAnchorsPrivate::updateMe() +{ + if (updatingMe) { + updatingMe = false; + return; } - d->item->setWidth(d->fill->width()-leftMargin()-rightMargin()); - d->item->setHeight(d->fill->height()-topMargin()-bottomMargin()); + + fillChanged(); + centeredInChanged(); + updateHorizontalAnchors(); + updateVerticalAnchors(); +} + +void QFxAnchorsPrivate::updateOnComplete() +{ + fillChanged(); + centeredInChanged(); + updateHorizontalAnchors(); + updateVerticalAnchors(); +} + +void QFxAnchorsPrivate::update(QFxItem *, const QRectF &newG, const QRectF &oldG) +{ + fillChanged(); + centeredInChanged(); + + if (newG.x() != oldG.x() || newG.width() != oldG.width()) + updateHorizontalAnchors(); + if (newG.y() != oldG.y() || newG.height() != oldG.height()) + updateVerticalAnchors(); } /*! @@ -166,37 +320,11 @@ QFxItem *QFxAnchors::fill() const void QFxAnchors::setFill(QFxItem *f) { Q_D(QFxAnchors); - if (d->fill) { - QObject::disconnect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged())); - QObject::disconnect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged())); - QObject::disconnect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged())); - QObject::disconnect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged())); - QObject::disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged())); - QObject::disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged())); - QObject::disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged())); - QObject::disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged())); - } - + d->remDepend(d->fill); d->fill = f; + d->addDepend(d->fill); - if (d->fill) { - if (d->fill == d->item->itemParent()) { //child-parent - QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged())); - QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged())); - } else if (f->itemParent() == d->item->itemParent()) { //siblings - QObject::connect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged())); - QObject::connect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged())); - QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged())); - QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged())); - } else { - qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling."; - } - } - QObject::connect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged())); - QObject::connect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged())); - QObject::connect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged())); - QObject::connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged())); - fillChanged(); //### can/should we defer until component completion? + d->fillChanged(); } /*! @@ -223,163 +351,12 @@ void QFxAnchors::setCenteredIn(QFxItem* c) qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling."; return; } - d->centeredIn = c; - setHorizontalCenter(c->horizontalCenter()); - setVerticalCenter(c->verticalCenter()); -} - -void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge) -{ - //### should we do disconnects first? (will it be called more than once?) - Q_Q(QFxAnchors); - if (edge.item == item->itemParent()) { //child-parent - switch(edge.anchorLine) { - case QFxAnchorLine::Bottom: - case QFxAnchorLine::VCenter: - QObject::connect(edge.item, SIGNAL(heightChanged()), q, SLOT(updateVerticalAnchors())); - break; - case QFxAnchorLine::Top: //no connection needed - default: - break; - } - } else if (edge.item->itemParent() == item->itemParent()) { //siblings - switch(edge.anchorLine) { - case QFxAnchorLine::Top: - QObject::connect(edge.item, SIGNAL(topChanged()), q, SLOT(updateVerticalAnchors())); - break; - case QFxAnchorLine::Bottom: - QObject::connect(edge.item, SIGNAL(bottomChanged()), q, SLOT(updateVerticalAnchors())); - break; - case QFxAnchorLine::VCenter: - QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, SLOT(updateVerticalAnchors())); - break; - default: - break; - } - } else { - qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling."; - } -} - -void QFxAnchors::connectVAnchors() -{ - Q_D(QFxAnchors); - if (!d->checkVValid()) - return; - - if (d->usedAnchors & HasTopAnchor) { - //Handle stretching connections (if we have multiple horizontal anchors) - QFxAnchorLine *edge = 0; - if (d->usedAnchors & HasBottomAnchor) { - edge = &d->bottom; - connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors())); - } else if (d->usedAnchors & HasVCenterAnchor) { - edge = &d->vCenter; - connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors())); - } - if (edge) { - //we need to stretch - d->connectVHelper(*edge); - } - - //Handle top - d->connectVHelper(d->top); - connect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors())); - updateVerticalAnchors(); - } else if (d->usedAnchors & HasBottomAnchor) { - //Handle stretching connections (if we have multiple horizontal anchors) - if (d->usedAnchors & HasVCenterAnchor) { - d->connectVHelper(d->vCenter); - connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors())); - } - - //Handle bottom - d->connectVHelper(d->bottom); - connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors())); - updateVerticalAnchors(); - } else if (d->usedAnchors & HasVCenterAnchor) { - //Handle vCenter - d->connectVHelper(d->vCenter); - connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors())); - updateVerticalAnchors(); - } -} - -void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge) -{ - //### should we do disconnects first? (will it be called more than once?) - Q_Q(QFxAnchors); - if (edge.item == item->itemParent()) { //child-parent - switch(edge.anchorLine) { - case QFxAnchorLine::Right: - case QFxAnchorLine::HCenter: - QObject::connect(edge.item, SIGNAL(widthChanged()), q, SLOT(updateHorizontalAnchors())); - break; - case QFxAnchorLine::Left: //no connection needed - default: - break; - } - } else if (edge.item->itemParent() == item->itemParent()) { //siblings - switch(edge.anchorLine) { - case QFxAnchorLine::Left: - QObject::connect(edge.item, SIGNAL(leftChanged()), q, SLOT(updateHorizontalAnchors())); - break; - case QFxAnchorLine::Right: - QObject::connect(edge.item, SIGNAL(rightChanged()), q, SLOT(updateHorizontalAnchors())); - break; - case QFxAnchorLine::HCenter: - QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, SLOT(updateHorizontalAnchors())); - break; - default: - break; - } - } else { - qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling."; - } -} - -void QFxAnchors::connectHAnchors() -{ - Q_D(QFxAnchors); - if (!d->checkHValid()) - return; - - if (d->usedAnchors & HasLeftAnchor) { - //Handle stretching connections (if we have multiple horizontal anchors) - QFxAnchorLine *edge = 0; - if (d->usedAnchors & HasRightAnchor) { - edge = &d->right; - connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors())); - } else if (d->usedAnchors & HasHCenterAnchor) { - edge = &d->hCenter; - connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors())); - } - if (edge) { - //we need to stretch - d->connectHHelper(*edge); - } - //Handle left - d->connectHHelper(d->left); - connect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors())); - updateHorizontalAnchors(); - } else if (d->usedAnchors & HasRightAnchor) { - //Handle stretching connections (if we have multiple horizontal anchors) - if (d->usedAnchors & HasHCenterAnchor) { - d->connectHHelper(d->hCenter); - connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors())); - } + d->remDepend(d->centeredIn); + d->centeredIn = c; + d->addDepend(d->centeredIn); - //Handle right - d->connectHHelper(d->right); - connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors())); - updateHorizontalAnchors(); - } else if (d->usedAnchors & HasHCenterAnchor) { - //Handle hCenter - d->connectHHelper(d->hCenter); - connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors())); - updateHorizontalAnchors(); - } + d->centeredInChanged(); } bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1, @@ -411,168 +388,124 @@ bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1, return invalid; } -void QFxAnchors::updateVerticalAnchors() +void QFxAnchorsPrivate::updateVerticalAnchors() { - Q_D(QFxAnchors); - if (!d->updatingVerticalAnchor) { - d->updatingVerticalAnchor = true; - if (d->usedAnchors & HasTopAnchor) { + if (fill || centeredIn || !isItemComplete()) + return; + + if (!updatingVerticalAnchor) { + updatingVerticalAnchor = true; + if (usedAnchors & QFxAnchors::HasTopAnchor) { //Handle stretching bool invalid = true; int height = 0; - if (d->usedAnchors & HasBottomAnchor) { - invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height); - } else if (d->usedAnchors & HasVCenterAnchor) { - invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height); + if (usedAnchors & QFxAnchors::HasBottomAnchor) { + invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QFxAnchorLine::Top, height); + } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) { + invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QFxAnchorLine::Top, height); height *= 2; } if (!invalid) - d->item->setHeight(height); + setItemHeight(height); //Handle top - if (d->top.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin); - } else if (d->top.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin); + if (top.item == item->itemParent()) { + setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin); + } else if (top.item->itemParent() == item->itemParent()) { + setItemY(position(top.item, top.anchorLine) + topMargin); } - } else if (d->usedAnchors & HasBottomAnchor) { + } else if (usedAnchors & QFxAnchors::HasBottomAnchor) { //Handle stretching (top + bottom case is handled above) - if (d->usedAnchors & HasVCenterAnchor) { + if (usedAnchors & QFxAnchors::HasVCenterAnchor) { int height = 0; - bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin, + bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, QFxAnchorLine::Top, height); if (!invalid) - d->item->setHeight(height*2); + setItemHeight(height*2); } //Handle bottom - if (d->bottom.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); - } else if (d->bottom.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); + if (bottom.item == item->itemParent()) { + setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin); + } else if (bottom.item->itemParent() == item->itemParent()) { + setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin); } - } else if (d->usedAnchors & HasVCenterAnchor) { + } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) { //(stetching handled above) //Handle vCenter - if (d->vCenter.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine) - - d->item->height()/2 + d->vCenterOffset); - } else if (d->vCenter.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset); + if (vCenter.item == item->itemParent()) { + setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) + - item->height()/2 + vCenterOffset); + } else if (vCenter.item->itemParent() == item->itemParent()) { + setItemY(position(vCenter.item, vCenter.anchorLine) - item->height()/2 + vCenterOffset); } } - d->updatingVerticalAnchor = false; + updatingVerticalAnchor = false; } else { - qmlInfo(d->item) << "Anchor loop detected on vertical anchor."; + // ### Make this certain :) + qmlInfo(item) << "Possible anchor loop detected on vertical anchor."; } } -void QFxAnchors::updateHorizontalAnchors() +void QFxAnchorsPrivate::updateHorizontalAnchors() { - Q_D(QFxAnchors); - if (!d->updatingHorizontalAnchor) { - d->updatingHorizontalAnchor = true; + if (fill || centeredIn || !isItemComplete()) + return; - //alternate implementation (needs performance testing) - /*switch(d->usedAnchors & QFxAnchors::Horizontal_Mask) { - case 0x03: //(HasLeftAnchor | HasRightAnchor) - { - int width = 0; - if (!d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width)) - d->item->setWidth(width); - //fall though - } - case 0x11: //(HasLeftAnchor | HasHCenterAnchor) - { - if (d->usedAnchors & HasHCenterAnchor) { - int width = 0; - if (!d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width)) - d->item->setWidth(width*2); - } - //fall though - } - case HasLeftAnchor: - if (d->left.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin); - } else if (d->left.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin); - } - break; - case 0x12: //(HasRightAnchor | HasHCenterAnchor) - { - int width = 0; - if (!d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, QFxAnchorLine::Left, width)) - d->item->setWidth(width*2); - //fall though - } - case HasRightAnchor: - if (d->right.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); - } else if (d->right.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); - } - break; - case HasHCenterAnchor: - if (d->hCenter.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); - } else if (d->hCenter.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); - } - break; - default: - break; - }*/ + if (!updatingHorizontalAnchor) { + updatingHorizontalAnchor = true; - if (d->usedAnchors & HasLeftAnchor) { + if (usedAnchors & QFxAnchors::HasLeftAnchor) { //Handle stretching bool invalid = true; int width = 0; - if (d->usedAnchors & HasRightAnchor) { - invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width); - } else if (d->usedAnchors & HasHCenterAnchor) { - invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width); + if (usedAnchors & QFxAnchors::HasRightAnchor) { + invalid = calcStretch(left, right, leftMargin, -rightMargin, QFxAnchorLine::Left, width); + } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) { + invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QFxAnchorLine::Left, width); width *= 2; } if (!invalid) - d->item->setWidth(width); + setItemWidth(width); //Handle left - if (d->left.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin); - } else if (d->left.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin); + if (left.item == item->itemParent()) { + setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin); + } else if (left.item->itemParent() == item->itemParent()) { + setItemX(position(left.item, left.anchorLine) + leftMargin); } - } else if (d->usedAnchors & HasRightAnchor) { + } else if (usedAnchors & QFxAnchors::HasRightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) - if (d->usedAnchors & HasHCenterAnchor) { + if (usedAnchors & QFxAnchors::HasHCenterAnchor) { int width = 0; - bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, + bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, QFxAnchorLine::Left, width); if (!invalid) - d->item->setWidth(width*2); + setItemWidth(width*2); } //Handle right - if (d->right.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); - } else if (d->right.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); + if (right.item == item->itemParent()) { + setItemX(adjustedPosition(right.item, right.anchorLine) - item->width() - rightMargin); + } else if (right.item->itemParent() == item->itemParent()) { + setItemX(position(right.item, right.anchorLine) - item->width() - rightMargin); } - } else if (d->usedAnchors & HasHCenterAnchor) { + } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) { //Handle hCenter - if (d->hCenter.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); - } else if (d->hCenter.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); + if (hCenter.item == item->itemParent()) { + setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset); + } else if (hCenter.item->itemParent() == item->itemParent()) { + setItemX(position(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset); } } - d->updatingHorizontalAnchor = false; + updatingHorizontalAnchor = false; } else { - qmlInfo(d->item) << "Anchor loop detected on horizontal anchor."; + // ### Make this certain :) + qmlInfo(item) << "Possible anchor loop detected on horizontal anchor."; } } @@ -588,29 +521,22 @@ void QFxAnchors::setTop(const QFxAnchorLine &edge) if (!d->checkVAnchorValid(edge)) return; - d->usedAnchors |= HasTopAnchor; + if (edge.item) + d->usedAnchors |= HasTopAnchor; + else + d->usedAnchors &= ~HasTopAnchor; d->checkVValid(); + d->remDepend(d->top.item); d->top = edge; + d->addDepend(d->top.item); + d->updateVerticalAnchors(); } void QFxAnchors::resetTop() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasTopAnchor; - - //clear binding - QmlMetaProperty prop(this, "top"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors())); - disconnect(d->top.item, 0, this, 0); - - updateVerticalAnchors(); + setTop(QFxAnchorLine()); } QFxAnchorLine QFxAnchors::bottom() const @@ -625,29 +551,22 @@ void QFxAnchors::setBottom(const QFxAnchorLine &edge) if (!d->checkVAnchorValid(edge)) return; - d->usedAnchors |= HasBottomAnchor; + if (edge.item) + d->usedAnchors |= HasBottomAnchor; + else + d->usedAnchors &= ~HasBottomAnchor; d->checkVValid(); + d->remDepend(d->bottom.item); d->bottom = edge; + d->addDepend(d->bottom.item); + d->updateVerticalAnchors(); } void QFxAnchors::resetBottom() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasBottomAnchor; - - //clear binding - QmlMetaProperty prop(this, "bottom"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors())); - disconnect(d->bottom.item, 0, this, 0); - - updateVerticalAnchors(); + setBottom(QFxAnchorLine()); } QFxAnchorLine QFxAnchors::verticalCenter() const @@ -662,29 +581,22 @@ void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge) if (!d->checkVAnchorValid(edge)) return; - d->usedAnchors |= HasVCenterAnchor; + if (edge.item) + d->usedAnchors |= HasVCenterAnchor; + else + d->usedAnchors &= ~HasVCenterAnchor; d->checkVValid(); + d->remDepend(d->vCenter.item); d->vCenter = edge; + d->addDepend(d->vCenter.item); + d->updateVerticalAnchors(); } void QFxAnchors::resetVerticalCenter() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasVCenterAnchor; - - //clear binding - QmlMetaProperty prop(this, "verticalCenter"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors())); - disconnect(d->vCenter.item, 0, this, 0); - - updateVerticalAnchors(); + setVerticalCenter(QFxAnchorLine()); } QFxAnchorLine QFxAnchors::left() const @@ -699,29 +611,22 @@ void QFxAnchors::setLeft(const QFxAnchorLine &edge) if (!d->checkHAnchorValid(edge)) return; - d->usedAnchors |= HasLeftAnchor; + if (edge.item) + d->usedAnchors |= HasLeftAnchor; + else + d->usedAnchors &= ~HasLeftAnchor; d->checkHValid(); + d->remDepend(d->left.item); d->left = edge; + d->addDepend(d->left.item); + d->updateHorizontalAnchors(); } void QFxAnchors::resetLeft() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasLeftAnchor; - - //clear binding - QmlMetaProperty prop(this, "left"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors())); - disconnect(d->left.item, 0, this, 0); - - updateHorizontalAnchors(); + setLeft(QFxAnchorLine()); } QFxAnchorLine QFxAnchors::right() const @@ -736,29 +641,23 @@ void QFxAnchors::setRight(const QFxAnchorLine &edge) if (!d->checkHAnchorValid(edge)) return; - d->usedAnchors |= HasRightAnchor; + if (edge.item) + d->usedAnchors |= HasRightAnchor; + else + d->usedAnchors &= ~HasRightAnchor; d->checkHValid(); + d->remDepend(d->right.item); d->right = edge; + d->addDepend(d->right.item); + + d->updateHorizontalAnchors(); } void QFxAnchors::resetRight() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasRightAnchor; - - //clear binding - QmlMetaProperty prop(this, "right"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors())); - disconnect(d->right.item, 0, this, 0); - - updateHorizontalAnchors(); + setRight(QFxAnchorLine()); } QFxAnchorLine QFxAnchors::horizontalCenter() const @@ -773,29 +672,22 @@ void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge) if (!d->checkHAnchorValid(edge)) return; - d->usedAnchors |= HasHCenterAnchor; + if (edge.item) + d->usedAnchors |= HasHCenterAnchor; + else + d->usedAnchors &= ~HasHCenterAnchor; d->checkHValid(); + d->remDepend(d->hCenter.item); d->hCenter = edge; + d->addDepend(d->hCenter.item); + d->updateHorizontalAnchors(); } void QFxAnchors::resetHorizontalCenter() { - Q_D(QFxAnchors); - - //update flags - d->usedAnchors &= ~HasHCenterAnchor; - - //clear binding - QmlMetaProperty prop(this, "horizontalCenter"); - prop.binding()->clearExpression(); - - //disconnect signal/slot connections as needed - disconnect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors())); - disconnect(d->hCenter.item, 0, this, 0); - - updateHorizontalAnchors(); + setHorizontalCenter(QFxAnchorLine()); } int QFxAnchors::leftMargin() const @@ -888,50 +780,6 @@ void QFxAnchors::setVerticalCenterOffset(int offset) emit verticalCenterOffsetChanged(); } -#if 0 -/*! - \property QFxAnchors::baseline - \brief what the baseline of the item should be anchored to (aligned with). - - The baseline of a Text item is the imaginary line on which the text sits. Controls containing - text usually set their baseline to the baseline of their text. - - For non-text items, a default baseline offset of two-thirds of the item's height is used - to determine the baseline. -*/ -int QFxAnchors::baseline() const -{ - return d->item->baseline(); -} - -void QFxAnchors::setBaseline(int baseline) -{ - d->usedAnchors |= HasBaselineAnchor; - - if (d->usedAnchors & HasTopAnchor && d->usedAnchors & HasBottomAnchor) { - qmlInfo(d->item) << "Can't specify top, bottom, and baseline anchors"; - return; - } - - if (d->usedAnchors & HasTopAnchor) { - int hoffset = baseline - d->item->baseline(); - d->item->setHeight(d->item->height() + hoffset); - } else { - if (d->usedAnchors & HasBottomAnchor) { - int hoffset = d->item->baseline() - baseline; - d->item->setHeight(d->item->height() + hoffset); - } - - int boffset = d->item->baseline() - d->item->top(); - QFxItem *parentItem = d->item->itemParent(); - if (parentItem) - d->item->setY(baseline - boffset - parentItem->top()); - else - d->item->setY(baseline - boffset); - } -} -#endif - QFxAnchors::UsedAnchors QFxAnchors::usedAnchors() const { Q_D(const QFxAnchors); diff --git a/src/declarative/fx/qfxanchors.h b/src/declarative/fx/qfxanchors.h index 5a8cc1a..9d776ab 100644 --- a/src/declarative/fx/qfxanchors.h +++ b/src/declarative/fx/qfxanchors.h @@ -42,9 +42,9 @@ #ifndef QFXANCHORS_H #define QFXANCHORS_H -#include <qfxglobal.h> -#include <QObject> -#include <qml.h> +#include <QtCore/QObject> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER @@ -80,6 +80,7 @@ public: Q_DECLARE_METATYPE(QFxAnchorLine); +class QFxAnchorsPrivate; class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject { Q_OBJECT @@ -101,6 +102,7 @@ class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject public: QFxAnchors(QObject *parent=0); + virtual ~QFxAnchors(); enum UsedAnchor { HasLeftAnchor = 0x01, @@ -167,9 +169,6 @@ public: void setItem(QFxItem *item); - void connectHAnchors(); - void connectVAnchors(); - Q_SIGNALS: void leftMarginChanged(); void rightMarginChanged(); @@ -178,13 +177,8 @@ Q_SIGNALS: void verticalCenterOffsetChanged(); void horizontalCenterOffsetChanged(); -private Q_SLOTS: - void fillChanged(); - void updateHorizontalAnchors(); - void updateVerticalAnchors(); - private: - //### should item be a friend? (and make some of the public methods private or protected) + friend class QFxItem; Q_DISABLE_COPY(QFxAnchors) Q_DECLARE_PRIVATE(QFxAnchors) }; diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h index 82c2086..b90380a 100644 --- a/src/declarative/fx/qfxanchors_p.h +++ b/src/declarative/fx/qfxanchors_p.h @@ -63,9 +63,10 @@ class QFxAnchorsPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QFxAnchors) public: QFxAnchorsPrivate() - : item(0), usedAnchors(0), fill(0), centeredIn(0), leftMargin(0), rightMargin(0), - topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0), - updatingHorizontalAnchor(false), updatingVerticalAnchor(false) + : updatingMe(false), updatingHorizontalAnchor(false), + updatingVerticalAnchor(false), item(0), usedAnchors(0), fill(0), + centeredIn(0), leftMargin(0), rightMargin(0), topMargin(0), + bottomMargin(0), vCenterOffset(0), hCenterOffset(0) { } @@ -73,14 +74,37 @@ public: { } + void clearItem(QFxItem *); + + void addDepend(QFxItem *); + void remDepend(QFxItem *); + bool isItemComplete() const; + + bool updatingMe:1; + bool updatingHorizontalAnchor:1; + bool updatingVerticalAnchor:1; + + void setItemHeight(qreal); + void setItemWidth(qreal); + void setItemX(qreal); + void setItemY(qreal); + void setItemPos(const QPointF &); + + void updateOnComplete(); + void updateMe(); + void update(QFxItem *, const QRectF &, const QRectF &); + bool checkHValid() const; bool checkVValid() const; bool checkHAnchorValid(QFxAnchorLine anchor) const; bool checkVAnchorValid(QFxAnchorLine anchor) const; - void connectHHelper(const QFxAnchorLine &anchorLine); - void connectVHelper(const QFxAnchorLine &anchorLine); bool calcStretch(const QFxAnchorLine &edge1, const QFxAnchorLine &edge2, int offset1, int offset2, QFxAnchorLine::AnchorLine line, int &stretch); + void updateHorizontalAnchors(); + void updateVerticalAnchors(); + void fillChanged(); + void centeredInChanged(); + QFxItem *item; QFxAnchors::UsedAnchors usedAnchors; @@ -101,8 +125,6 @@ public: int vCenterOffset; int hCenterOffset; - bool updatingHorizontalAnchor; - bool updatingVerticalAnchor; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxanimatedimageitem.h b/src/declarative/fx/qfxanimatedimageitem.h index 121fe62..a332c8b 100644 --- a/src/declarative/fx/qfxanimatedimageitem.h +++ b/src/declarative/fx/qfxanimatedimageitem.h @@ -42,7 +42,7 @@ #ifndef QFXANIMATEDIMAGEITEM_H #define QFXANIMATEDIMAGEITEM_H -#include <qfximage.h> +#include <QtDeclarative/qfximage.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxblendedimage.h b/src/declarative/fx/qfxblendedimage.h index 5cc0238..2fdf15b 100644 --- a/src/declarative/fx/qfxblendedimage.h +++ b/src/declarative/fx/qfxblendedimage.h @@ -42,7 +42,7 @@ #ifndef QFXBLENDEDIMAGE_H #define QFXBLENDEDIMAGE_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> #if defined(QFX_RENDER_OPENGL2) #include <gltexture.h> #endif @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QFxBlendedImage : public QFxItem +class Q_DECLARATIVE_EXPORT QFxBlendedImage : public QFxItem { Q_OBJECT diff --git a/src/declarative/fx/qfxblurfilter.h b/src/declarative/fx/qfxblurfilter.h index 7a2b5b9..576debf 100644 --- a/src/declarative/fx/qfxblurfilter.h +++ b/src/declarative/fx/qfxblurfilter.h @@ -42,8 +42,8 @@ #ifndef QFXBLURFILTER_H #define QFXBLURFILTER_H -#include <qsimplecanvasfilter.h> -#include <qml.h> +#include <QtDeclarative/qsimplecanvasfilter.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxcomponentinstance.h b/src/declarative/fx/qfxcomponentinstance.h index 64af355..9f84043 100644 --- a/src/declarative/fx/qfxcomponentinstance.h +++ b/src/declarative/fx/qfxcomponentinstance.h @@ -42,7 +42,7 @@ #ifndef QFXCOMPONENTINSTANCE_H #define QFXCOMPONENTINSTANCE_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxcontentwrapper.h b/src/declarative/fx/qfxcontentwrapper.h index 5d5a7e1..0b7253e 100644 --- a/src/declarative/fx/qfxcontentwrapper.h +++ b/src/declarative/fx/qfxcontentwrapper.h @@ -42,7 +42,7 @@ #ifndef QFXCONTENTWRAPPER_H #define QFXCONTENTWRAPPER_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxevents_p.h b/src/declarative/fx/qfxevents_p.h index 30717ef..bcd9f2d 100644 --- a/src/declarative/fx/qfxevents_p.h +++ b/src/declarative/fx/qfxevents_p.h @@ -42,8 +42,8 @@ #ifndef QFXEVENTS_P_H #define QFXEVENTS_P_H -#include <qfxglobal.h> -#include <qml.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> #include <QtCore/qobject.h> #include <QtGui/qevent.h> diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h index c5a0593..3857017 100644 --- a/src/declarative/fx/qfxflickable.h +++ b/src/declarative/fx/qfxflickable.h @@ -42,7 +42,7 @@ #ifndef QFXFLICKABLE_H #define QFXFLICKABLE_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp index 24ae428..edcc7cb 100644 --- a/src/declarative/fx/qfxflipable.cpp +++ b/src/declarative/fx/qfxflipable.cpp @@ -169,7 +169,6 @@ void QFxFlipable::setBack(QFxItem *back) children()->append(d->back); if (Front == d->current) d->back->setOpacity(0.); - d->setBackTransform(); } /*! @@ -203,8 +202,6 @@ void QFxFlipablePrivate::_q_updateAxis() axisRotation.axis()->setEndX(axis->endX()); axisRotation.axis()->setEndY(axis->endY()); axisRotation.axis()->setEndZ(axis->endZ()); - - setBackTransform(); } void QFxFlipablePrivate::setBackTransform() @@ -273,8 +270,10 @@ void QFxFlipable::setRotation(qreal angle) d->current = newSide; if (d->front) d->front->setOpacity((d->current==Front)?1.:0.); - if (d->back) + if (d->back) { + d->setBackTransform(); d->back->setOpacity((d->current==Back)?1.:0.); + } emit sideChanged(); } } diff --git a/src/declarative/fx/qfxflipable.h b/src/declarative/fx/qfxflipable.h index ef1832e..62b62a5 100644 --- a/src/declarative/fx/qfxflipable.h +++ b/src/declarative/fx/qfxflipable.h @@ -42,12 +42,12 @@ #ifndef QFXFLIPABLE_H #define QFXFLIPABLE_H -#include <QObject> -#include <QTransform> +#include <QtCore/QObject> +#include <QtGui/QTransform> #if defined(QFX_RENDER_OPENGL) #include <QtGui/qmatrix4x4.h> #endif -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxfocuspanel.h b/src/declarative/fx/qfxfocuspanel.h index 38f7a15..cec12a1 100644 --- a/src/declarative/fx/qfxfocuspanel.h +++ b/src/declarative/fx/qfxfocuspanel.h @@ -42,7 +42,7 @@ #ifndef QFXFOCUSPANEL_H #define QFXFOCUSPANEL_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxfocusrealm.h b/src/declarative/fx/qfxfocusrealm.h index 6c35405..fdf1525 100644 --- a/src/declarative/fx/qfxfocusrealm.h +++ b/src/declarative/fx/qfxfocusrealm.h @@ -42,7 +42,7 @@ #ifndef QFXFOCUSREALM_H #define QFXFOCUSREALM_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 90bf1ce..99c7cff 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -42,7 +42,7 @@ #ifndef QFXGRIDVIEW_H #define QFXGRIDVIEW_H -#include <qfxflickable.h> +#include <QtDeclarative/qfxflickable.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxhighlightfilter.h b/src/declarative/fx/qfxhighlightfilter.h index 218f4e1..92a3dc7 100644 --- a/src/declarative/fx/qfxhighlightfilter.h +++ b/src/declarative/fx/qfxhighlightfilter.h @@ -42,8 +42,8 @@ #ifndef QFXHIGHLIGHTFILTER_H #define QFXHIGHLIGHTFILTER_H -#include <qsimplecanvasfilter.h> -#include <qml.h> +#include <QtDeclarative/qsimplecanvasfilter.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 9d7a36a..4197a80 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -361,49 +361,57 @@ void QFxImage::paintContents(QPainter &p) p.drawImage(0, 0, pix); } } else { - const int sgl = d->_scaleGrid->left(); - const int sgr = d->_scaleGrid->right(); - const int sgt = d->_scaleGrid->top(); - const int sgb = d->_scaleGrid->bottom(); - const int xSide = qMin(sgl + sgr, int(width())); - const int ySide = qMin(sgt + sgb, int(height())); + int sgl = d->_scaleGrid->left(); + int sgr = d->_scaleGrid->right(); + int sgt = d->_scaleGrid->top(); + int sgb = d->_scaleGrid->bottom(); + + int w = width(); + int h = height(); + if (sgt + sgb > h) + sgt = sgb = h/2; + if (sgl + sgr > w) + sgl = sgr = w/2; + + const int xSide = sgl + sgr; + const int ySide = sgt + sgb; // Upper left if (sgt && sgl) p.drawImage(QRect(0, 0, sgl, sgt), pix, QRect(0, 0, sgl, sgt)); // Upper middle if (pix.width() - xSide && sgt) - p.drawImage(QRect(sgl, 0, width() - xSide, sgt), pix, + p.drawImage(QRect(sgl, 0, w - xSide, sgt), pix, QRect(sgl, 0, pix.width() - xSide, sgt)); // Upper right if (sgt && pix.width() - sgr) - p.drawImage(QPoint(width()-sgr, 0), pix, + p.drawImage(QPoint(w-sgr, 0), pix, QRect(pix.width()-sgr, 0, sgr, sgt)); // Middle left if (sgl && pix.height() - ySide) - p.drawImage(QRect(0, sgt, sgl, height() - ySide), pix, + p.drawImage(QRect(0, sgt, sgl, h - ySide), pix, QRect(0, sgt, sgl, pix.height() - ySide)); // Middle if (pix.width() - xSide && pix.height() - ySide) - p.drawImage(QRect(sgl, sgt, width() - xSide, height() - ySide), + p.drawImage(QRect(sgl, sgt, w - xSide, h - ySide), pix, QRect(sgl, sgt, pix.width() - xSide, pix.height() - ySide)); // Middle right if (sgr && pix.height() - ySide) - p.drawImage(QRect(width()-sgr, sgt, sgr, height() - ySide), pix, + p.drawImage(QRect(w-sgr, sgt, sgr, h - ySide), pix, QRect(pix.width()-sgr, sgt, sgr, pix.height() - ySide)); // Lower left if (sgl && sgr) - p.drawImage(QPoint(0, height() - sgb), pix, + p.drawImage(QPoint(0, h - sgb), pix, QRect(0, pix.height() - sgb, sgl, sgb)); // Lower Middle if (pix.width() - xSide && sgb) - p.drawImage(QRect(sgl, height() - sgb, width() - xSide, sgb), pix, + p.drawImage(QRect(sgl, h - sgb, w - xSide, sgb), pix, QRect(sgl, pix.height() - sgb, pix.width() - xSide, sgb)); // Lower Right if (sgr && sgb) - p.drawImage(QPoint(width()-sgr, height() - sgb), pix, + p.drawImage(QPoint(w-sgr, h - sgb), pix, QRect(pix.width()-sgr, pix.height() - sgb, sgr, sgb)); } diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h index dc13a97..1436551 100644 --- a/src/declarative/fx/qfximage.h +++ b/src/declarative/fx/qfximage.h @@ -42,7 +42,7 @@ #ifndef QFXIMAGE_H #define QFXIMAGE_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> #include <QtNetwork/qnetworkreply.h> diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index b737615..3cbcd6a 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -52,6 +52,7 @@ #include "qmlengine.h" #include "qmlstate.h" #include "qlistmodelinterface.h" +#include "qfxanchors_p.h" #include "qfxtransform.h" #include "qfxscalegrid.h" @@ -434,6 +435,14 @@ void QFxItem::doUpdate() QFxItem::~QFxItem() { Q_D(QFxItem); + for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) { + QFxAnchors *anchor = d->dependantAnchors.at(ii); + anchor->d_func()->clearItem(this); + } + for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) { + QFxAnchors *anchor = d->dependantAnchors.at(ii); + anchor->d_func()->updateOnComplete(); + } delete d->_anchorLines; d->_anchorLines = 0; } @@ -1062,85 +1071,30 @@ void QFxItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QFxItem); - if (newGeometry.width() != oldGeometry.width()) { - int xoffset = oldGeometry.width() - newGeometry.width(); - d->handleWidthChange(xoffset); - } - if (newGeometry.height() != oldGeometry.height()) { - int yoffset = oldGeometry.height() - newGeometry.height(); - d->handleHeightChange(yoffset); - } + if (d->_anchors) + d->_anchors->d_func()->updateMe(); - if (newGeometry.x() != oldGeometry.x()) { - emit leftChanged(); - emit hcenterChanged(); - emit rightChanged(); + if (newGeometry.size() != oldGeometry.size()) { + if (rotation() && transformOrigin() != QFxItem::TopLeft) + setRotation(rotation()); + if (scale() && transformOrigin() != QFxItem::TopLeft) + setScale(scale()); } - if (newGeometry.y() != oldGeometry.y()) { + if (newGeometry.x() != oldGeometry.x()) + emit leftChanged(); + if (newGeometry.width() != oldGeometry.width()) + emit widthChanged(); + if (newGeometry.y() != oldGeometry.y()) emit topChanged(); - emit vcenterChanged(); - emit bottomChanged(); - } -} - -void QFxItemPrivate::handleWidthChange(int xoffset) -{ - Q_Q(QFxItem); - if (!_anchors) { - emit q->hcenterChanged(); - emit q->rightChanged(); - } else { - QFxAnchors::UsedAnchors used = anchors()->usedAnchors(); - if (used & QFxAnchors::HasHCenterAnchor) { - q->setX(q->x() + xoffset/2); - emit q->rightChanged(); - } else if ((used & QFxAnchors::HasRightAnchor) && !(used & QFxAnchors::HasLeftAnchor)) { - q->setX(q->x() + xoffset); - emit q->hcenterChanged(); - } else { - emit q->hcenterChanged(); - emit q->rightChanged(); - } - } - if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft) - q->setRotation(q->rotation()); - if (q->scale() && q->transformOrigin() != QFxItem::TopLeft) - q->setScale(q->scale()); - emit q->widthChanged(); -} + if (newGeometry.height() != oldGeometry.height()) + emit heightChanged(); -void QFxItemPrivate::handleHeightChange(int yoffset) -{ - Q_Q(QFxItem); - if (!_anchors) { - emit q->vcenterChanged(); - emit q->bottomChanged(); - emit q->baselineChanged(); - } else { - QFxAnchors::UsedAnchors used = anchors()->usedAnchors(); - if (used & QFxAnchors::HasBaselineAnchor) { - q->setY(q->y() + yoffset - q->baselineOffset()); - emit q->bottomChanged(); - emit q->vcenterChanged(); - } else if (used & QFxAnchors::HasVCenterAnchor) { - q->setY(q->y() + yoffset/2); - emit q->bottomChanged(); - } else if ((used & QFxAnchors::HasBottomAnchor) && !(used & QFxAnchors::HasTopAnchor)) { - q->setY(q->y() + yoffset); - emit q->vcenterChanged(); - } else { - emit q->vcenterChanged(); - emit q->bottomChanged(); - emit q->baselineChanged(); - } + for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) { + QFxAnchors *anchor = d->dependantAnchors.at(ii); + anchor->d_func()->update(this, newGeometry, oldGeometry); } - if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft) - q->setRotation(q->rotation()); - if (q->scale() && q->transformOrigin() != QFxItem::TopLeft) - q->setScale(q->scale()); - emit q->heightChanged(); } /*! @@ -1483,7 +1437,6 @@ void QFxItem::setBaselineOffset(int offset) d->_baselineOffset = offset; emit baselineOffsetChanged(); - emit baselineChanged(); } /*! @@ -2075,10 +2028,8 @@ void QFxItem::componentComplete() d->_componentComplete = true; if (d->_stateGroup) d->_stateGroup->componentComplete(); - if (d->_anchors) { - d->anchors()->connectHAnchors(); - d->anchors()->connectVAnchors(); - } + if (d->_anchors) + d->anchors()->d_func()->updateOnComplete(); if (!d->_transform.isEmpty()) updateTransform(); } diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 549c9c2..d34a9fb 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -42,9 +42,9 @@ #ifndef QFXITEM_H #define QFXITEM_H -#include <QObject> +#include <QtCore/QObject> #include <QtScript/qscriptvalue.h> -#include <QList> +#include <QtCore/QList> #include <QtDeclarative/qfxanchors.h> #include <QtDeclarative/qfxglobal.h> #include <QtDeclarative/qml.h> @@ -213,14 +213,9 @@ public Q_SLOTS: Q_SIGNALS: void leftChanged(); - void rightChanged(); void widthChanged(); void heightChanged(); void topChanged(); - void bottomChanged(); - void hcenterChanged(); - void vcenterChanged(); - void baselineChanged(); void baselineOffsetChanged(); void stateChanged(const QString &); void focusChanged(); diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h index f2da3ba..85ce171 100644 --- a/src/declarative/fx/qfxitem_p.h +++ b/src/declarative/fx/qfxitem_p.h @@ -53,11 +53,11 @@ // We mean it. // -#include "qfxitem.h" +#include <QtDeclarative/qfxitem.h> #include <private/qsimplecanvasitem_p.h> #include <private/qmlnullablevalue_p.h> -#include <qml.h> -#include <qmlcontext.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlcontext.h> #include <QtCore/qlist.h> QT_BEGIN_NAMESPACE @@ -129,6 +129,7 @@ public: } return _anchors; } + QList<QFxAnchors *> dependantAnchors; QFxAnchors *_anchors; QFxContents *_contents; QFxItem *qmlItem; @@ -171,9 +172,6 @@ public: QmlStateGroup *states(); QmlStateGroup *_stateGroup; - - void handleWidthChange(int xoffset); - void handleHeightChange(int xoffset); }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxkeyactions.h b/src/declarative/fx/qfxkeyactions.h index 7ad323a..a5aec2e 100644 --- a/src/declarative/fx/qfxkeyactions.h +++ b/src/declarative/fx/qfxkeyactions.h @@ -42,10 +42,10 @@ #ifndef QFXKEYACTIONS_H #define QFXKEYACTIONS_H -#include <qfxglobal.h> -#include <QObject> -#include <qml.h> -#include <qfxitem.h> +#include <QtCore/QObject> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxkeyproxy.h b/src/declarative/fx/qfxkeyproxy.h index ae5fce4..6cf0c0d 100644 --- a/src/declarative/fx/qfxkeyproxy.h +++ b/src/declarative/fx/qfxkeyproxy.h @@ -42,7 +42,7 @@ #ifndef QFXKEYPROXY_H #define QFXKEYPROXY_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxlayouts.h b/src/declarative/fx/qfxlayouts.h index acfc0c4..35e41d8 100644 --- a/src/declarative/fx/qfxlayouts.h +++ b/src/declarative/fx/qfxlayouts.h @@ -42,10 +42,10 @@ #ifndef QFXLAYOUTS_H #define QFXLAYOUTS_H -#include <qfxitem.h> -#include <QObject> -#include <QString> -#include <qmlstate.h> +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtDeclarative/qfxitem.h> +#include <QtDeclarative/qmlstate.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxlayouts_p.h b/src/declarative/fx/qfxlayouts_p.h index 859482f..77b0ea1 100644 --- a/src/declarative/fx/qfxlayouts_p.h +++ b/src/declarative/fx/qfxlayouts_p.h @@ -53,11 +53,11 @@ // We mean it. // -#include "qfxlayouts.h" -#include "qfxitem_p.h" -#include <QObject> -#include <QString> -#include <qmlstate.h> +#include <private/qfxitem_p.h> +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtDeclarative/qfxlayouts.h> +#include <QtDeclarative/qmlstate.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 42f7773..87a851b 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -42,7 +42,7 @@ #ifndef QFXLISTVIEW_H #define QFXLISTVIEW_H -#include <qfxflickable.h> +#include <QtDeclarative/qfxflickable.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxmouseregion.h b/src/declarative/fx/qfxmouseregion.h index 2ba4a50..1d1ec93 100644 --- a/src/declarative/fx/qfxmouseregion.h +++ b/src/declarative/fx/qfxmouseregion.h @@ -42,7 +42,7 @@ #ifndef QFXMOUSEREGION_H #define QFXMOUSEREGION_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxpainteditem.h b/src/declarative/fx/qfxpainteditem.h index 015a035..6cd21e6 100644 --- a/src/declarative/fx/qfxpainteditem.h +++ b/src/declarative/fx/qfxpainteditem.h @@ -42,8 +42,8 @@ #ifndef QFXIMAGEITEM_H #define QFXIMAGEITEM_H -#include <qfxglobal.h> -#include <qfxitem.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h index b0432ac..5d5da6b 100644 --- a/src/declarative/fx/qfxpainteditem_p.h +++ b/src/declarative/fx/qfxpainteditem_p.h @@ -53,8 +53,8 @@ // We mean it. // -#include "qfxitem_p.h" -#include <qsimplecanvas.h> +#include <private/qfxitem_p.h> +#include <QtDeclarative/qsimplecanvas.h> #if defined(QFX_RENDER_OPENGL) #include "gltexture.h" diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp index 1aaf256..67c1208 100644 --- a/src/declarative/fx/qfxparticles.cpp +++ b/src/declarative/fx/qfxparticles.cpp @@ -340,6 +340,32 @@ void QFxParticleMotionWander::destroy(QFxParticle &p) } //--------------------------------------------------------------------------- +class QFxParticlesPainter : public QFxItem +{ +public: + QFxParticlesPainter(QFxParticlesPrivate *p, QFxItem* parent) + : QFxItem(parent), d(p) + { + setOptions(HasContents); + maxX = minX = maxY = minY = 0; + } + +#if defined(QFX_RENDER_QPAINTER) + void paintContents(QPainter &p); +#elif defined(QFX_RENDER_OPENGL2) + void paintGLContents(GLPainter &); +#endif + + void updateSize(); + + qreal maxX; + qreal minX; + qreal maxY; + qreal minY; + QFxParticlesPrivate* d; +}; + +//--------------------------------------------------------------------------- class QFxParticlesPrivate : public QFxItemPrivate { Q_DECLARE_PUBLIC(QFxParticles) @@ -359,7 +385,12 @@ public: { } - void init() {} + void init() + { + Q_Q(QFxParticles); + paintItem = new QFxParticlesPainter(this, q); + } + void tick(int time); void createParticle(int time); void updateOpacity(QFxParticle &p, int age); @@ -383,6 +414,7 @@ public: int streamDelay; bool emitting; QFxParticleMotion *motion; + QFxParticlesPainter *paintItem; QList<QFxParticle> particles; QTickAnimationProxy<QFxParticlesPrivate, &QFxParticlesPrivate::tick> clock; @@ -1040,28 +1072,76 @@ QString QFxParticles::propertyInfo() const return d->url.toString(); } +void QFxParticlesPainter::updateSize(){ + setX(-500); + setY(-500); + setWidth(1000); + setHeight(1000); + return ; + const int parentX = parent()->x(); + const int parentY = parent()->y(); + //Have to use statistical approach to needed size as arbitrary particle + //motions make it impossible to calculate. + //max/min vars stored to give a never shrinking rect + for (int i = 0; i < d->particles.count(); ++i) { + const QFxParticle &particle = d->particles.at(i); + if(particle.x > maxX) + maxX = particle.x; + if(particle.x < minX) + minX = particle.x; + if(particle.y > maxY) + maxY = particle.y; + if(particle.y < minY) + minY = particle.y; + } + + int myWidth = (int)(maxX-minX+0.5)+d->image.width(); + int myX = (int)(minX - parentX); + int myHeight = (int)(maxY-minY+0.5)+d->image.height(); + int myY = (int)(minY - parentY); + setWidth(myWidth); + setHeight(myHeight); + setX(myX); + setY(myY); +} + #if defined(QFX_RENDER_QPAINTER) void QFxParticles::paintContents(QPainter &p) { - Q_D(QFxParticles); + Q_UNUSED(p); + //painting is done by the ParticlesPainter, so it can have the right size +} + +void QFxParticlesPainter::paintContents(QPainter &p) +{ if (d->image.isNull()) return; - const int myX = x(); - const int myY = y(); + updateSize(); + const int myX = x() + parent()->x(); + const int myY = y() + parent()->y(); + for (int i = 0; i < d->particles.count(); ++i) { const QFxParticle &particle = d->particles.at(i); p.setOpacity(particle.opacity); - p.drawImage(particle.x-myX, particle.y-myY, d->image); + p.drawImage(particle.x - myX, particle.y - myY, d->image); } + update();//Should I need this? (GV does) } #elif defined(QFX_RENDER_OPENGL2) -void QFxParticles::paintGLContents(GLPainter &p) +void QFxParticles::paintGLContents(GLPainter &) { - Q_D(QFxParticles); + //painting is done by the ParticlesPainter, so it can have the right size +} + +void QFxParticlesPainter::paintGLContents(GLPainter &p) +{ + if (d->image.isNull()) return; + updateSize(); + if (d->texDirty && !d->image.isNull()) { d->tex.setImage(d->image); d->tex.setHorizontalWrap(GLTexture::Repeat); @@ -1075,8 +1155,8 @@ void QFxParticles::paintGLContents(GLPainter &p) glBindTexture(GL_TEXTURE_2D, d->tex.texture()); - const int myX = (int)x(); - const int myY = (int)y(); + const int myX = (int)(x() + parent()->x()); + const int myY = (int)(y() + parent()->y()); float widthV = d->image.width(); float heightV = d->image.height(); for (int i = 0; i < d->particles.count(); ++i) { diff --git a/src/declarative/fx/qfxparticles.h b/src/declarative/fx/qfxparticles.h index 0696e60..31a00fb 100644 --- a/src/declarative/fx/qfxparticles.h +++ b/src/declarative/fx/qfxparticles.h @@ -42,7 +42,7 @@ #ifndef QFXPARTICLES_H #define QFXPARTICLES_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> #if defined(QFX_RENDER_OPENGL) #include "gltexture.h" @@ -56,7 +56,7 @@ QT_MODULE(Declarative) class QFxParticle; class QFxParticles; -class QFxParticleMotion : public QObject +class Q_DECLARATIVE_EXPORT QFxParticleMotion : public QObject { Q_OBJECT public: @@ -68,7 +68,7 @@ public: }; QML_DECLARE_TYPE(QFxParticleMotion); -class QFxParticleMotionLinear : public QFxParticleMotion +class Q_DECLARATIVE_EXPORT QFxParticleMotionLinear : public QFxParticleMotion { Q_OBJECT public: @@ -79,7 +79,7 @@ public: }; QML_DECLARE_TYPE(QFxParticleMotionLinear); -class QFxParticleMotionGravity : public QFxParticleMotion +class Q_DECLARATIVE_EXPORT QFxParticleMotionGravity : public QFxParticleMotion { Q_OBJECT @@ -108,7 +108,7 @@ private: }; QML_DECLARE_TYPE(QFxParticleMotionGravity); -class QFxParticleMotionWander : public QFxParticleMotion +class Q_DECLARATIVE_EXPORT QFxParticleMotionWander : public QFxParticleMotion { Q_OBJECT public: diff --git a/src/declarative/fx/qfxpath.h b/src/declarative/fx/qfxpath.h index c594793..10cf252 100644 --- a/src/declarative/fx/qfxpath.h +++ b/src/declarative/fx/qfxpath.h @@ -42,10 +42,10 @@ #ifndef QFXPATH_H #define QFXPATH_H -#include <QObject> -#include <QPainterPath> -#include <qml.h> -#include <qfxitem.h> +#include <QtCore/QObject> +#include <QtGui/QPainterPath> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxpathview.h b/src/declarative/fx/qfxpathview.h index 04804b7..33db566 100644 --- a/src/declarative/fx/qfxpathview.h +++ b/src/declarative/fx/qfxpathview.h @@ -42,8 +42,8 @@ #ifndef QFXPATHVIEW_H #define QFXPATHVIEW_H -#include <qfxitem.h> -#include <qfxpath.h> +#include <QtDeclarative/qfxitem.h> +#include <QtDeclarative/qfxpath.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h index 297dba7..fd56ee4 100644 --- a/src/declarative/fx/qfxpixmap.h +++ b/src/declarative/fx/qfxpixmap.h @@ -42,10 +42,10 @@ #ifndef QFXPIXMAP_H #define QFXPIXMAP_H -#include <QString> -#include <qsimplecanvas.h> -#include <qfxglobal.h> -#include <QPixmap> +#include <QtCore/QString> +#include <QtGui/QPixmap> +#include <QtDeclarative/qsimplecanvas.h> +#include <QtDeclarative/qfxglobal.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index dafd8a2..f1cbb58 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -52,6 +52,11 @@ QML_DEFINE_TYPE(QFxPen,Pen); \ingroup group_utility \brief The QFxPen class provides a pen used for drawing rect borders on a QFxView. + By default, the pen is invalid and nothing is drawn. You must either set a color (then the default + width is 0) or a width (then the default color is black). + + A width of 0 is a single-pixel line on the border of the item being painted. + Example: \qml Rect { pen.width: 2; pen.color: "red" ... } @@ -61,8 +66,9 @@ QML_DEFINE_TYPE(QFxPen,Pen); /*! \property QFxPen::width \brief the width of the pen. - The default width is 1. If the width is less than 1 the pen is considered invalid - and won't be used. + A width of 0 is a single-pixel line on the border of the item being painted. + + If the width is less than 0 the pen is considered invalid and won't be used. */ /*! @@ -86,8 +92,28 @@ QML_DEFINE_TYPE(QFxPen,Pen); void QFxPen::setColor(const QColor &c) { _color = c; - emit updated(); _valid = _color.alpha() ? true : false; + emit updated(); +} + +/*! + \property QFxPen::width + \brief the width of the pen. + + \qml + // rect with green border using hexidecimal notation + Rect { pen.width: 4 } + \endqml + + A width of 0 creates a thin line. For no line, use a negative width or a transparent color. + + Odd pen widths generally lead to half-pixel painting. +*/ +void QFxPen::setWidth(int w) +{ + _width = w; + _valid = (_width < 0) ? false : true; + emit updated(); } @@ -167,6 +193,8 @@ void QFxRect::doUpdate() Q_D(QFxRect); d->_rectTexture.clear(); #endif + const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + setPaintMargin((pw+1)/2); update(); } @@ -372,14 +400,19 @@ void QFxRect::generateRoundedRect() { Q_D(QFxRect); if (d->_rectImage.isNull()) { - d->_rectImage = QImage(d->_radius*2 + 1, d->_radius*2 + 1, QImage::Format_ARGB32_Premultiplied); + const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + d->_rectImage = QImage(d->_radius*2 + 1 + pw*2, d->_radius*2 + 1 + pw*2, QImage::Format_ARGB32_Premultiplied); d->_rectImage.fill(0); QPainter p(&(d->_rectImage)); - QPen pn(QColor(pen()->color()), pen()->width()); p.setRenderHint(QPainter::Antialiasing); - p.setPen(pn); + if (d->_pen && d->_pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } p.setBrush(d->_color); - p.drawRoundedRect(0, 0, d->_rectImage.width(), d->_rectImage.height(), d->_radius, d->_radius); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2, d->_radius, d->_radius); } } @@ -387,14 +420,19 @@ void QFxRect::generateBorderedRect() { Q_D(QFxRect); if (d->_rectImage.isNull()) { - d->_rectImage = QImage(d->pen()->width()*2 + 1, d->pen()->width()*2 + 1, QImage::Format_ARGB32_Premultiplied); + const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + d->_rectImage = QImage(d->pen()->width()*2 + 1 + pw*2, d->pen()->width()*2 + 1 + pw*2, QImage::Format_ARGB32_Premultiplied); d->_rectImage.fill(0); QPainter p(&(d->_rectImage)); - QPen pn(QColor(pen()->color()), pen()->width()); p.setRenderHint(QPainter::Antialiasing); - p.setPen(pn); + if (d->_pen && d->_pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } p.setBrush(d->_color); - p.drawRect(0, 0, d->_rectImage.width(), d->_rectImage.height()); + p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, d->_rectImage.width()-(pw+1)/2*2, d->_rectImage.height()-(pw+1)/2*2); } } #elif defined(QFX_RENDER_OPENGL) @@ -402,14 +440,19 @@ void QFxRect::generateRoundedRect() { Q_D(QFxRect); if (d->_rectTexture.isNull()) { - QImage roundRect(int(d->_radius*2 + 1), int(d->_radius*2 + 1), QImage::Format_ARGB32); + const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + QImage roundRect(d->_radius*2 + 4 + pw*2, d->_radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied); roundRect.fill(0); QPainter p(&roundRect); - QPen pn(QColor(pen()->color()), pen()->width()); p.setRenderHint(QPainter::Antialiasing); - p.setPen(pn); + if (d->_pen && d->_pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } p.setBrush(d->_color); - p.drawRoundedRect(0, 0, roundRect.width(), roundRect.height(), d->_radius, d->_radius); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->_radius, d->_radius); d->_rectTexture.setImage(roundRect); } } @@ -418,14 +461,19 @@ void QFxRect::generateBorderedRect() { Q_D(QFxRect); if (d->_rectTexture.isNull()) { - QImage borderedRect(d->pen()->width()*2 + 1, d->pen()->width()*2 + 1, QImage::Format_ARGB32_Premultiplied); + const int pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0; + QImage borderedRect(pw*2 + 4, pw*2 + 4, QImage::Format_ARGB32_Premultiplied); borderedRect.fill(0); QPainter p(&(borderedRect)); - QPen pn(QColor(pen()->color()), pen()->width()); p.setRenderHint(QPainter::Antialiasing); - p.setPen(pn); + if (d->_pen && d->_pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } p.setBrush(d->_color); - p.drawRect(0, 0, borderedRect.width(), borderedRect.height()); + p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); d->_rectTexture.setImage(borderedRect); } } @@ -458,9 +506,13 @@ void QFxRect::drawRect(QPainter &p) // XXX This path is still slower than the image path // Image path won't work for gradients though p.save(); - QPen pn(QColor(pen()->color()), pen()->width()); p.setRenderHint(QPainter::Antialiasing); - p.setPen(pn); + if (d->_pen && d->_pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } if (d->_gradcolor.isValid()){ QLinearGradient grad(0, 0, 0, height()); grad.setColorAt(0, d->_color); @@ -476,55 +528,72 @@ void QFxRect::drawRect(QPainter &p) p.restore(); } else { int offset = 0; + const int pw = d->_pen && d->_pen->isValid() ? (d->_pen->width()+1)/2*2 : 0; + if (d->_radius > 0) { generateRoundedRect(); //### implicit conversion to int - offset = d->_radius; + offset = int(d->_radius+0.5+pw); } else { generateBorderedRect(); - offset = d->pen()->width(); + offset = pw; } //basically same code as QFxImage uses to paint sci images - int xSide = qMin(offset * 2, int(width())); - int ySide = qMin(offset * 2, int(height()));; + int w = width()+pw; + int h = height()+pw; + int xOffset = offset; + int xSide = xOffset * 2; + bool xMiddles=true; + if (xSide > w) { + xMiddles=false; + xOffset = w/2 + 1; + xSide = xOffset * 2; + } + int yOffset = offset; + int ySide = yOffset * 2; + bool yMiddles=true; + if (ySide > h) { + yMiddles = false; + yOffset = h/2 + 1; + ySide = yOffset * 2; + } // Upper left - p.drawImage(QRect(0, 0, offset, offset), d->_rectImage, QRect(0, 0, offset, offset)); + p.drawImage(QRect(-pw/2, -pw/2, xOffset, yOffset), d->_rectImage, QRect(0, 0, xOffset, yOffset)); // Upper middle - if (d->_rectImage.width() - xSide) - p.drawImage(QRect(offset, 0, width() - xSide, offset), d->_rectImage, - QRect(offset, 0, d->_rectImage.width() - xSide, offset)); + if (xMiddles) + p.drawImage(QRect(xOffset-pw/2, -pw/2, width() - xSide + pw, yOffset), d->_rectImage, + QRect(d->_rectImage.width()/2, 0, 1, yOffset)); // Upper right - if (d->_rectImage.width() - offset) { - p.drawImage(QPoint(width()-offset, 0), d->_rectImage, - QRect(d->_rectImage.width()-offset, 0, offset, offset)); - } + p.drawImage(QPoint(width()-xOffset+pw/2, -pw/2), d->_rectImage, + QRect(d->_rectImage.width()-xOffset, 0, xOffset, yOffset)); // Middle left - if (d->_rectImage.height() - ySide) - p.drawImage(QRect(0, offset, offset, height() - ySide), d->_rectImage, - QRect(0, offset, offset, d->_rectImage.height() - ySide)); + if (yMiddles) + p.drawImage(QRect(-pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage, + QRect(0, d->_rectImage.height()/2, xOffset, 1)); // Middle - if (d->_rectImage.width() - xSide && d->_rectImage.height() - ySide) - p.drawImage(QRect(offset, offset, width() - xSide, height() - ySide), d->_rectImage, - QRect(offset, offset, d->_rectImage.width() - xSide, d->_rectImage.height() - ySide)); - // Midlle right - if (d->_rectImage.height() - ySide) - p.drawImage(QRect(width()-offset, offset, offset, height() - ySide), d->_rectImage, - QRect(d->_rectImage.width()-offset, offset, offset, d->_rectImage.height() - ySide)); + if (xMiddles && yMiddles) + // XXX paint errors in animation example + //p.fillRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw, d->getColor()); + p.drawImage(QRect(xOffset-pw/2, yOffset-pw/2, width() - xSide + pw, height() - ySide + pw), d->_rectImage, + QRect(d->_rectImage.width()/2, d->_rectImage.height()/2, 1, 1)); + // Middle right + if (yMiddles) + p.drawImage(QRect(width()-xOffset+pw/2, yOffset-pw/2, xOffset, height() - ySide + pw), d->_rectImage, + QRect(d->_rectImage.width()-xOffset, d->_rectImage.height()/2, xOffset, 1)); // Lower left - p.drawImage(QPoint(0, height() - offset), d->_rectImage, QRect(0, d->_rectImage.height() - offset, offset, offset)); + p.drawImage(QPoint(-pw/2, height() - yOffset + pw/2), d->_rectImage, QRect(0, d->_rectImage.height() - yOffset, xOffset, yOffset)); // Lower Middle - if (d->_rectImage.width() - xSide) - p.drawImage(QRect(offset, height() - offset, width() - xSide, offset), d->_rectImage, - QRect(offset, d->_rectImage.height() - offset, d->_rectImage.width() - xSide, offset)); + if (xMiddles) + p.drawImage(QRect(xOffset-pw/2, height() - yOffset +pw/2, width() - xSide + pw, yOffset), d->_rectImage, + QRect(d->_rectImage.width()/2, d->_rectImage.height() - yOffset, 1, yOffset)); // Lower Right - if (d->_rectImage.width() - offset) - p.drawImage(QPoint(width()-offset, height() - offset), d->_rectImage, - QRect(d->_rectImage.width()-offset, d->_rectImage.height() - offset, offset, offset)); + p.drawImage(QPoint(width()-xOffset+pw/2, height() - yOffset+pw/2), d->_rectImage, + QRect(d->_rectImage.width()-xOffset, d->_rectImage.height() - yOffset, xOffset, yOffset)); } } #endif @@ -586,53 +655,60 @@ void QFxRect::paintGLContents(GLPainter &p) } } else { qreal offset = 0; + qreal pw = d->_pen && d->_pen->isValid() ? d->_pen->width() : 0.0; + if (d->_radius > 0) { generateRoundedRect(); - offset = d->_radius; + offset = d->_radius + pw+1.5; } else { generateBorderedRect(); - offset = d->pen()->width(); + offset = pw+1.5; } QGLShaderProgram *shader = p.useTextureShader(); - float imgWidth = d->_rectTexture.width(); - float imgHeight = d->_rectTexture.height(); - if (!imgWidth || !imgHeight) + float texWidth = d->_rectTexture.width(); + float texHeight = d->_rectTexture.height(); + if (!texWidth || !texHeight) return; - float widthV = width(); - float heightV = height(); + float widthV = qreal(width())+pw/2; + float heightV = qreal(height())+pw/2; - float texleft = 0; - float texright = 1; - float textop = 1; - float texbottom = 0; - float imgleft = 0; - float imgright = widthV; - float imgtop = 0; - float imgbottom = heightV; + float xOffset = offset; + bool xMiddles = true; + if (xOffset*2 > width()+pw) { + xMiddles = false; + xOffset = (width()+pw)/2; + } + float yOffset = offset; + bool yMiddles = true; + if (yOffset*2 > height()+pw) { + yMiddles = false; + yOffset = (height()+pw)/2; + } - texleft = float(offset) / imgWidth; - imgleft = offset; - texright = 1. - float(offset) / imgWidth; - imgright = widthV - offset; - textop = 1. - float(offset) / imgHeight; - imgtop = offset; - texbottom = float(offset) / imgHeight; - imgbottom = heightV - offset; + float texleft = xOffset / texWidth; + float imgleft = xOffset-pw/2; + float texright = (texWidth-xOffset) / texWidth; + float imgright = widthV - xOffset; + + float textop = yOffset / texHeight; + float imgtop = yOffset-pw/2; + float texbottom = (texHeight-yOffset) / texHeight; + float imgbottom = heightV - yOffset; //Bug 231768: Inappropriate interpolation was occuring on 3x3 textures if (offset==1) texleft=texright=textop=texbottom=0.5; - float vert1[] = { 0, 0, - 0, imgtop, - imgleft, 0, + float vert1[] = { -pw/2, -pw/2, + -pw/2, imgtop, + imgleft, -pw/2, imgleft, imgtop, - imgright, 0, + imgright, -pw/2, imgright, imgtop, - widthV, 0, + widthV, -pw/2, widthV, imgtop }; float tex1[] = { 0, 0, 0, textop, @@ -642,8 +718,8 @@ void QFxRect::paintGLContents(GLPainter &p) texright, textop, 1, 0, 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, + float vert2[] = { -pw/2, imgtop, + -pw/2, imgbottom, imgleft, imgtop, imgleft, imgbottom, imgright, imgtop, @@ -658,31 +734,33 @@ void QFxRect::paintGLContents(GLPainter &p) texright, texbottom, 1, textop, 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, + float vert3[] = { -pw/2, heightV, + -pw/2, imgbottom, imgleft, heightV, - imgright, imgbottom, + imgleft, imgbottom, imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, - 0, 0, + imgright, imgbottom, + widthV, heightV, + widthV, imgbottom }; + float tex3[] = { 0, 1, + 0, texbottom, + texleft, 1, texleft, texbottom, - texleft, 0, + texright, 1, texright, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; + 1, 1, + 1, texbottom }; glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + if (yMiddles) { + shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + } shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); @@ -761,9 +839,9 @@ void QFxRect::paintGLContents(GLPainter &p) glColor4f(1, 1, 1, p.activeOpacity); } - float imgWidth = d->_rectTexture.width(); - float imgHeight = d->_rectTexture.height(); - if (!imgWidth || !imgHeight) + float texWidth = d->_rectTexture.width(); + float texHeight = d->_rectTexture.height(); + if (!texWidth || !texHeight) return; float widthV = width(); @@ -778,13 +856,13 @@ void QFxRect::paintGLContents(GLPainter &p) float imgtop = 0; float imgbottom = heightV; - texleft = float(offset) / imgWidth; + texleft = float(offset) / texWidth; imgleft = offset; - texright = 1. - float(offset) / imgWidth; + texright = 1. - float(offset) / texWidth; imgright = widthV - offset; - textop = 1. - float(offset) / imgHeight; + textop = 1. - float(offset) / texHeight; imgtop = offset; - texbottom = float(offset) / imgHeight; + texbottom = float(offset) / texHeight; imgbottom = heightV - offset; float vert1[] = { 0, 0, diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h index 42e7b2f..420ec44 100644 --- a/src/declarative/fx/qfxrect.h +++ b/src/declarative/fx/qfxrect.h @@ -42,7 +42,7 @@ #ifndef QFXRECT_H #define QFXRECT_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER @@ -58,11 +58,11 @@ class Q_DECLARATIVE_EXPORT QFxPen : public QObject Q_PROPERTY(QColor color READ color WRITE setColor) public: QFxPen(QObject *parent=0) - : QObject(parent), _width(1), _color("#000000"), _valid(false) + : QObject(parent), _width(0), _color("#000000"), _valid(false) {} int width() const { return _width; } - void setWidth(int w) { _width = w; emit updated(); _valid = (_width < 1) ? false : true; } + void setWidth(int w); QColor color() const { return _color; } void setColor(const QColor &c); diff --git a/src/declarative/fx/qfxreflectionfilter.h b/src/declarative/fx/qfxreflectionfilter.h index b0cc7b2..383e12f 100644 --- a/src/declarative/fx/qfxreflectionfilter.h +++ b/src/declarative/fx/qfxreflectionfilter.h @@ -42,8 +42,8 @@ #ifndef QFXREFLECTIONFILTER_H #define QFXREFLECTIONFILTER_H -#include <qsimplecanvasfilter.h> -#include <qml.h> +#include <QtDeclarative/qsimplecanvasfilter.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxrepeater.h b/src/declarative/fx/qfxrepeater.h index 8efd281..362242b 100644 --- a/src/declarative/fx/qfxrepeater.h +++ b/src/declarative/fx/qfxrepeater.h @@ -42,7 +42,7 @@ #ifndef QFXREPEATER_H #define QFXREPEATER_H -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxscalegrid.h b/src/declarative/fx/qfxscalegrid.h index 9010ce7..d0f735f 100644 --- a/src/declarative/fx/qfxscalegrid.h +++ b/src/declarative/fx/qfxscalegrid.h @@ -42,13 +42,13 @@ #ifndef QFXSCALEGRID_H #define QFXSCALEGRID_H -#include <qfxglobal.h> -#include <QImage> -#include <QString> -#include <QObject> -#include <qsimplecanvas.h> -#include <qfxpixmap.h> -#include <qml.h> +#include <QtCore/QString> +#include <QtCore/QObject> +#include <QtGui/QImage> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qsimplecanvas.h> +#include <QtDeclarative/qfxpixmap.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxshadowfilter.h b/src/declarative/fx/qfxshadowfilter.h index 9ba3b7b..fc54e01 100644 --- a/src/declarative/fx/qfxshadowfilter.h +++ b/src/declarative/fx/qfxshadowfilter.h @@ -42,8 +42,8 @@ #ifndef QFXSHADOWFILTER_H #define QFXSHADOWFILTER_H -#include <qsimplecanvasfilter.h> -#include <qml.h> +#include <QtDeclarative/qsimplecanvasfilter.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index a43219d..e84255d 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -458,10 +458,11 @@ void QFxTextPrivate::updateSize() singleline = !tmp.contains(QChar::LineSeparator); if (singleline && elideMode != Qt::ElideNone && q->widthValid()) tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...? - QTextLayout layout; + layout.clearLayout(); layout.setFont(f); layout.setText(tmp); size = setupTextLayout(&layout); + cachedLayoutSize = size; } if (richText) { singleline = false; // richtext can't elide or be optimized for single-line case @@ -608,18 +609,11 @@ QImage QFxTextPrivate::wrappedTextImage(bool drawStyle) //do layout Q_Q(const QFxText); QFont f; if (_font) f = _font->font(); - QString tmp = text; - if (singleline && elideMode != Qt::ElideNone && q->widthValid()) { - QFontMetrics fm(f); - tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...? - } - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); - QTextLayout textLayout(tmp, f); - QSize size = setupTextLayout(&textLayout); + QSize size = cachedLayoutSize; int x = 0; - for (int i = 0; i < textLayout.lineCount(); ++i) { - QTextLine line = textLayout.lineAt(i); + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); if (hAlign == QFxText::AlignLeft) { x = 0; } else if (hAlign == QFxText::AlignRight) { @@ -640,7 +634,7 @@ QImage QFxTextPrivate::wrappedTextImage(bool drawStyle) else p.setPen(color); p.setFont(f); - textLayout.draw(&p, QPointF(0, 0)); + layout.draw(&p, QPointF(0, 0)); return img; } @@ -749,7 +743,16 @@ void QFxText::paintContents(QPainter &p) break; } + bool needClip = !clip() && (d->imgCache.width() > width() || + d->imgCache.height() > height()); + + if (needClip) { + p.save(); + p.setClipRect(boundingRect()); + } p.drawImage(x, y, d->imgCache); + if (needClip) + p.restore(); } #elif defined(QFX_RENDER_OPENGL2) diff --git a/src/declarative/fx/qfxtext.h b/src/declarative/fx/qfxtext.h index 0de884b..ee9082b 100644 --- a/src/declarative/fx/qfxtext.h +++ b/src/declarative/fx/qfxtext.h @@ -42,8 +42,8 @@ #ifndef QFXTEXT_H #define QFXTEXT_H -#include <qfxitem.h> -#include <qmlfont.h> +#include <QtDeclarative/qfxitem.h> +#include <QtDeclarative/qmlfont.h> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxtext_p.h b/src/declarative/fx/qfxtext_p.h index 4296891..8bb3142 100644 --- a/src/declarative/fx/qfxtext_p.h +++ b/src/declarative/fx/qfxtext_p.h @@ -56,6 +56,7 @@ #include "qfxitem.h" #include "qfxitem_p.h" #include "qml.h" +#include <QtGui/qtextlayout.h> #if defined(QFX_RENDER_OPENGL) #include "gltexture.h" @@ -72,7 +73,9 @@ class QFxTextPrivate : public QFxItemPrivate Q_DECLARE_PUBLIC(QFxText) public: QFxTextPrivate() - : _font(0), color((QRgb)0), style(QFxText::Normal), imgDirty(true), hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone), dirty(false), wrap(false), richText(false), singleline(false), control(0), doc(0) + : _font(0), color((QRgb)0), style(QFxText::Normal), imgDirty(true), + hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone), + dirty(false), wrap(false), richText(false), singleline(false), control(0), doc(0) { } @@ -126,6 +129,8 @@ public: bool singleline; QTextControl *control; QTextDocument *doc; + QTextLayout layout; + QSize cachedLayoutSize; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index 35b1173..8667c9e 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -662,7 +662,6 @@ void QFxTextEdit::keyReleaseEvent(QKeyEvent *event) */ void QFxTextEdit::focusChanged(bool hasFocus) { - Q_D(QFxTextEdit); setCursorVisible(hasFocus); } @@ -675,29 +674,6 @@ void QFxTextEdit::selectAll() d->control->selectAll(); } -static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e) -{ - QEvent::Type t; - switch(e->type()) { - default: - case QEvent::GraphicsSceneMousePress: - t = QEvent::MouseButtonPress; - break; - case QEvent::GraphicsSceneMouseRelease: - t = QEvent::MouseButtonRelease; - break; - case QEvent::GraphicsSceneMouseMove: - t = QEvent::MouseMove; - break; - case QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick: - t = QEvent::MouseButtonDblClick; - break; - } - - QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), e->button(), e->buttons(), 0); - return me; -} - /*! \overload Handles the given mouse \a event. @@ -707,10 +683,7 @@ void QFxTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) Q_D(QFxTextEdit); if (d->focusOnPress) setFocus(true); - QMouseEvent *me = sceneMouseEventToMouseEvent(event); - d->control->processEvent(me, QPointF(0, 0)); - event->setAccepted(me->isAccepted()); - delete me; + d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QFxPaintedItem::mousePressEvent(event); } @@ -722,10 +695,7 @@ Handles the given mouse \a event. void QFxTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QFxTextEdit); - QMouseEvent *me = sceneMouseEventToMouseEvent(event); - d->control->processEvent(me, QPointF(0, 0)); - event->setAccepted(me->isAccepted()); - delete me; + d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QFxPaintedItem::mousePressEvent(event); } @@ -737,10 +707,7 @@ Handles the given mouse \a event. void QFxTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QFxTextEdit); - QMouseEvent *me = sceneMouseEventToMouseEvent(event); - d->control->processEvent(me, QPointF(0, 0)); - event->setAccepted(me->isAccepted()); - delete me; + d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QFxPaintedItem::mousePressEvent(event); } diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h index 0aaa17b..f702101 100644 --- a/src/declarative/fx/qfxtextedit.h +++ b/src/declarative/fx/qfxtextedit.h @@ -42,8 +42,8 @@ #ifndef QFXTEXTEDIT_H #define QFXTEXTEDIT_H -#include <qfxtext.h> -#include <qfxpainteditem.h> +#include <QtDeclarative/qfxtext.h> +#include <QtDeclarative/qfxpainteditem.h> #include <QtGui/qtextdocument.h> #include <QtGui/qtextoption.h> diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp index 7b76367..d99af27 100644 --- a/src/declarative/fx/qfxtransform.cpp +++ b/src/declarative/fx/qfxtransform.cpp @@ -179,6 +179,20 @@ void QFxAxis::setEndZ(qreal z) emit updated(); } +/*! + \qmlclass Rotation + \brief A Rotation object provides a way to rotate an Item around a point. + + The following example rotates a Rect around its interior point 25, 25: + \qml + Rect { + width: 100; height: 100 + color: "blue" + transform: Rotation { originX: 25; originY: 25; angle: 45} + } + \endqml +*/ + QFxRotation::QFxRotation(QObject *parent) : QFxTransform(parent), _originX(0), _originY(0), _angle(0), _dirty(true) { @@ -188,6 +202,12 @@ QFxRotation::~QFxRotation() { } +/*! + \qmlproperty real Rotation::originX + \qmlproperty real Rotation::originY + + The point to rotate around. +*/ qreal QFxRotation::originX() const { return _originX; @@ -210,6 +230,11 @@ void QFxRotation::setOriginY(qreal oy) update(); } +/*! + \qmlproperty real Rotation::angle + + The angle, in degrees, to rotate. +*/ qreal QFxRotation::angle() const { return _angle; @@ -217,8 +242,11 @@ qreal QFxRotation::angle() const void QFxRotation::setAngle(qreal angle) { + if (_angle == angle) + return; _angle = angle; update(); + emit angleChanged(); } bool QFxRotation::isIdentity() const @@ -244,7 +272,9 @@ QMatrix4x4 QFxRotation::transform() const if (_dirty) { _transform = QMatrix4x4(); _dirty = false; - _transform.rotate(_angle, _originX, _originY); + _transform.translate(_originX, _originY); + _transform.rotate(_angle, 0, 0, 1); + _transform.translate(-_originX, -_originY); } return _transform; } diff --git a/src/declarative/fx/qfxtransform.h b/src/declarative/fx/qfxtransform.h index a3a1a83..31374df 100644 --- a/src/declarative/fx/qfxtransform.h +++ b/src/declarative/fx/qfxtransform.h @@ -42,12 +42,12 @@ #ifndef QFXTRANSFORM_H #define QFXTRANSFORM_H -#include <QObject> -#include <QTransform> +#include <QtCore/QObject> +#include <QtGui/QTransform> #if defined(QFX_RENDER_OPENGL) #include <QtGui/qmatrix4x4.h> #endif -#include <qfxitem.h> +#include <QtDeclarative/qfxitem.h> QT_BEGIN_HEADER @@ -115,7 +115,7 @@ class Q_DECLARATIVE_EXPORT QFxRotation : public QFxTransform Q_PROPERTY(qreal originX READ originX WRITE setOriginX) Q_PROPERTY(qreal originY READ originY WRITE setOriginY) - Q_PROPERTY(qreal angle READ angle WRITE setAngle) + Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged()) public: QFxRotation(QObject *parent=0); ~QFxRotation(); @@ -132,6 +132,9 @@ public: virtual bool isIdentity() const; virtual QSimpleCanvas::Matrix transform() const; +Q_SIGNALS: + void angleChanged(); + private Q_SLOTS: void update(); private: diff --git a/src/declarative/fx/qfxvisualitemmodel.h b/src/declarative/fx/qfxvisualitemmodel.h index 7156d70..622065c 100644 --- a/src/declarative/fx/qfxvisualitemmodel.h +++ b/src/declarative/fx/qfxvisualitemmodel.h @@ -44,7 +44,7 @@ #include <QtCore/qobject.h> #include <QtCore/qabstractitemmodel.h> -#include <qml.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER @@ -62,7 +62,7 @@ class QFxItem; class QmlComponent; class QmlPackage; class QFxVisualItemModelPrivate; -class QFxVisualItemModel : public QObject +class Q_DECLARATIVE_EXPORT QFxVisualItemModel : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QFxVisualItemModel) diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h index afd5b0f..6a3dad5 100644 --- a/src/declarative/fx/qfxwebview.h +++ b/src/declarative/fx/qfxwebview.h @@ -42,12 +42,12 @@ #ifndef QFXWEBVIEW_H #define QFXWEBVIEW_H -#include <QAction> -#include <QUrl> -#include <qfxglobal.h> -#include <qfxpainteditem.h> +#include <QtGui/QAction> +#include <QtCore/QUrl> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qfxpainteditem.h> #include <QtNetwork/qnetworkaccessmanager.h> -#include <QWebPage> +#include <QtWebKit/QWebPage> QT_BEGIN_HEADER diff --git a/src/declarative/fx/qfxwidgetcontainer.h b/src/declarative/fx/qfxwidgetcontainer.h index 65e4352..3b1f016 100644 --- a/src/declarative/fx/qfxwidgetcontainer.h +++ b/src/declarative/fx/qfxwidgetcontainer.h @@ -48,6 +48,8 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Declarative) + class QGraphicsWidget; class Q_DECLARATIVE_EXPORT QFxWidgetContainer : public QFxItem diff --git a/src/declarative/opengl/glheaders.h b/src/declarative/opengl/glheaders.h index f0f6a55..fd1da18 100644 --- a/src/declarative/opengl/glheaders.h +++ b/src/declarative/opengl/glheaders.h @@ -42,7 +42,7 @@ #ifndef _GLHEADERS_H_ #define _GLHEADERS_H_ -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> #define GL_GLEXT_PROTOTYPES 1 #include <QtOpenGL/qgl.h> diff --git a/src/declarative/opengl/glsave.h b/src/declarative/opengl/glsave.h index cca3d3c..8256162 100644 --- a/src/declarative/opengl/glsave.h +++ b/src/declarative/opengl/glsave.h @@ -42,9 +42,9 @@ #ifndef _GLSAVE_H_ #define _GLSAVE_H_ -#include <qglobal.h> -#include <qfxglobal.h> -#include <QRect> +#include <QtCore/qglobal.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtCore/QRect> #include "glheaders.h" diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h index f920b60..8704498 100644 --- a/src/declarative/opengl/gltexture.h +++ b/src/declarative/opengl/gltexture.h @@ -42,10 +42,10 @@ #ifndef _GLTEXTURE_H_ #define _GLTEXTURE_H_ -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> -#include <QRect> -#include <QPoint> +#include <QtCore/QRect> +#include <QtCore/QPoint> #include "glheaders.h" diff --git a/src/declarative/qml/parser/javascript.g b/src/declarative/qml/parser/javascript.g index 48e8244..155630b 100644 --- a/src/declarative/qml/parser/javascript.g +++ b/src/declarative/qml/parser/javascript.g @@ -46,7 +46,7 @@ %decl javascriptparser_p.h %impl javascriptparser.cpp %expect 2 -%expect-rr 1 +%expect-rr 2 %token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" %token T_BREAK "break" T_CASE "case" T_CATCH "catch" @@ -207,86 +207,71 @@ #include "javascriptgrammar_p.h" #include "javascriptast_p.h" +#include "javascriptengine_p.h" + #include <QtCore/QList> QT_BEGIN_NAMESPACE class QString; -class JavaScriptEnginePrivate; -class JavaScriptNameIdImpl; -class JavaScriptParser: protected $table +namespace JavaScript { + +class Engine; +class NameId; + +class Parser: protected $table { public: union Value { int ival; double dval; - JavaScriptNameIdImpl *sval; - JavaScript::AST::ArgumentList *ArgumentList; - JavaScript::AST::CaseBlock *CaseBlock; - JavaScript::AST::CaseClause *CaseClause; - JavaScript::AST::CaseClauses *CaseClauses; - JavaScript::AST::Catch *Catch; - JavaScript::AST::DefaultClause *DefaultClause; - JavaScript::AST::ElementList *ElementList; - JavaScript::AST::Elision *Elision; - JavaScript::AST::ExpressionNode *Expression; - JavaScript::AST::Finally *Finally; - JavaScript::AST::FormalParameterList *FormalParameterList; - JavaScript::AST::FunctionBody *FunctionBody; - JavaScript::AST::FunctionDeclaration *FunctionDeclaration; - JavaScript::AST::Node *Node; - JavaScript::AST::PropertyName *PropertyName; - JavaScript::AST::PropertyNameAndValueList *PropertyNameAndValueList; - JavaScript::AST::SourceElement *SourceElement; - JavaScript::AST::SourceElements *SourceElements; - JavaScript::AST::Statement *Statement; - JavaScript::AST::StatementList *StatementList; - JavaScript::AST::Block *Block; - JavaScript::AST::VariableDeclaration *VariableDeclaration; - JavaScript::AST::VariableDeclarationList *VariableDeclarationList; - - JavaScript::AST::UiProgram *UiProgram; - JavaScript::AST::UiImportList *UiImportList; - JavaScript::AST::UiImport *UiImport; - JavaScript::AST::UiPublicMember *UiPublicMember; - JavaScript::AST::UiObjectDefinition *UiObjectDefinition; - JavaScript::AST::UiObjectInitializer *UiObjectInitializer; - JavaScript::AST::UiObjectBinding *UiObjectBinding; - JavaScript::AST::UiScriptBinding *UiScriptBinding; - JavaScript::AST::UiArrayBinding *UiArrayBinding; - JavaScript::AST::UiObjectMember *UiObjectMember; - JavaScript::AST::UiObjectMemberList *UiObjectMemberList; - JavaScript::AST::UiQualifiedId *UiQualifiedId; - }; - - struct DiagnosticMessage { - enum Kind { Warning, Error }; - - DiagnosticMessage() - : kind(Error) {} - - DiagnosticMessage(Kind kind, const JavaScript::AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} - - bool isWarning() const - { return kind == Warning; } - - bool isError() const - { return kind == Error; } - - Kind kind; - JavaScript::AST::SourceLocation loc; - QString message; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiQualifiedId *UiQualifiedId; }; public: - JavaScriptParser(); - ~JavaScriptParser(); + Parser(Engine *engine); + ~Parser(); - bool parse(JavaScriptEnginePrivate *driver); + bool parse(); - JavaScript::AST::UiProgram *ast() + AST::UiProgram *ast() { return program; } QList<DiagnosticMessage> diagnosticMessages() const @@ -317,17 +302,20 @@ protected: inline Value &sym(int index) { return sym_stack [tos + index - 1]; } - inline JavaScript::AST::SourceLocation &loc(int index) + inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + protected: + Engine *driver; int tos; int stack_size; Value *sym_stack; int *state_stack; - JavaScript::AST::SourceLocation *location_stack; + AST::SourceLocation *location_stack; - JavaScript::AST::UiProgram *program; + AST::UiProgram *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; @@ -335,12 +323,12 @@ protected: struct SavedToken { int token; double dval; - JavaScript::AST::SourceLocation loc; + AST::SourceLocation loc; }; double yylval; - JavaScript::AST::SourceLocation yylloc; - JavaScript::AST::SourceLocation yyprevlloc; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; @@ -349,12 +337,16 @@ protected: QList<DiagnosticMessage> diagnostic_messages; }; +} // end of namespace JavaScript + + :/ /. #include "javascriptparser_p.h" +#include <QVarLengthArray> // // This file is automatically generated from javascript.g. @@ -365,7 +357,7 @@ using namespace JavaScript; QT_BEGIN_NAMESPACE -void JavaScriptParser::reallocateStack() +void Parser::reallocateStack() { if (! stack_size) stack_size = 128; @@ -377,7 +369,7 @@ void JavaScriptParser::reallocateStack() location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); } -inline static bool automatic(JavaScriptEnginePrivate *driver, int token) +inline static bool automatic(Engine *driver, int token) { return token == $table::T_RBRACE || token == 0 @@ -385,7 +377,8 @@ inline static bool automatic(JavaScriptEnginePrivate *driver, int token) } -JavaScriptParser::JavaScriptParser(): +Parser::Parser(Engine *engine): + driver(engine), tos(0), stack_size(0), sym_stack(0), @@ -396,7 +389,7 @@ JavaScriptParser::JavaScriptParser(): { } -JavaScriptParser::~JavaScriptParser() +Parser::~Parser() { if (stack_size) { qFree(sym_stack); @@ -415,7 +408,35 @@ static inline AST::SourceLocation location(Lexer *lexer) return loc; } -bool JavaScriptParser::parse(JavaScriptEnginePrivate *driver) +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<AST::SourceLocation, 4> locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { + AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse() { Lexer *lexer = driver->lexer(); bool hadErrors = false; @@ -475,7 +496,7 @@ UiProgram: UiImportListOpt UiRootMember ; case $rule_number: { program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; + sym(1).UiProgram = program; } break; ./ @@ -580,23 +601,11 @@ case $rule_number: { } break; ./ -UiObjectMember: UiQualifiedId T_COLON T_IDENTIFIER UiObjectInitializer ; +UiObjectDefinition: UiQualifiedId UiObjectInitializer ; /. case $rule_number: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(3).sval, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - -UiObjectDefinition: T_IDENTIFIER UiObjectInitializer ; -/. -case $rule_number: { - AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).sval, + AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(2).UiObjectInitializer); - node->identifierToken = loc(1); sym(1).Node = node; } break; ./ @@ -634,11 +643,46 @@ case $rule_number: { } break; ./ -UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ; -/. case $rule_number: ./ -UiObjectMember: UiQualifiedId T_COLON Statement ; + +UiObjectMember: UiQualifiedId T_COLON Expression UiObjectInitializer ; /. case $rule_number: { + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { + AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; + } else { + sym(1).Node = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), + QLatin1String("Expected a type name after token `:'"))); + + return false; // ### recover + } +} break; +./ + +UiObjectMember: UiQualifiedId T_COLON Block ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; +/.case $rule_number:./ + +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:./ + +/. +{ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(3).Statement); node->colonToken = loc(2); @@ -648,7 +692,7 @@ case $rule_number: { UiPropertyType: T_VAR ; /. -case $rule_number: +case $rule_number: ./ UiPropertyType: T_RESERVED_WORD ; /. @@ -663,7 +707,7 @@ UiPropertyType: T_IDENTIFIER ; UiObjectMember: T_SIGNAL T_IDENTIFIER ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (JavaScriptNameIdImpl *)0, sym(2).sval); + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -779,25 +823,6 @@ case $rule_number: { } ./ -UiQualifiedId: JsIdentifier ; -/. -case $rule_number: { - AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ - -UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ; -/. -case $rule_number: { - AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; -./ - - -------------------------------------------------------------------------------------------------------- -- Expressions -------------------------------------------------------------------------------------------------------- @@ -899,10 +924,20 @@ case $rule_number: { } break; ./ -PrimaryExpression: T_LBRACKET ElisionOpt T_RBRACKET ; +PrimaryExpression: T_LBRACKET T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->rbracketToken = loc(2); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision); + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; @@ -919,10 +954,23 @@ case $rule_number: { } break; ./ -PrimaryExpression: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET ; +PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision); + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); @@ -973,51 +1021,73 @@ case $rule_number: { } break; ./ -ElementList: ElisionOpt AssignmentExpression ; +UiQualifiedId: JsIdentifier ; +/. +case $rule_number: { + AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision, sym(2).Expression); + AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +ElementList: AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; ./ -ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression ; +ElementList: Elision AssignmentExpression ; /. case $rule_number: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision, sym(4).Expression); - node->commaToken = loc(2); - sym(1).Node = node; + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); } break; ./ -Elision: T_COMMA ; +ElementList: ElementList T_COMMA AssignmentExpression ; /. case $rule_number: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); - node->commaToken = loc(1); + 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; ./ -Elision: Elision T_COMMA ; +ElementList: ElementList T_COMMA Elision AssignmentExpression ; /. case $rule_number: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + 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; ./ -ElisionOpt: %prec SHIFT_THERE ; +Elision: T_COMMA ; /. case $rule_number: { - sym(1).Node = 0; + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); + node->commaToken = loc(1); + sym(1).Node = node; } break; ./ -ElisionOpt: Elision ; +Elision: Elision T_COMMA ; /. case $rule_number: { - sym(1).Elision = sym(1).Elision->finish (); + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; } break; ./ @@ -1038,7 +1108,7 @@ case $rule_number: { sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); - sym(1).Node = node; + sym(1).Node = node; } break; ./ @@ -1047,7 +1117,7 @@ PropertyName: T_IDENTIFIER %prec REDUCE_HERE ; case $rule_number: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; ./ @@ -1059,7 +1129,7 @@ PropertyName: T_PROPERTY ; case $rule_number: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; ./ @@ -1068,7 +1138,7 @@ PropertyName: T_STRING_LITERAL ; case $rule_number: { AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; ./ @@ -1077,7 +1147,7 @@ PropertyName: T_NUMERIC_LITERAL ; case $rule_number: { AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; ./ @@ -1086,7 +1156,7 @@ PropertyName: ReservedIdentifier ; case $rule_number: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; ./ diff --git a/src/declarative/qml/parser/javascriptast.cpp b/src/declarative/qml/parser/javascriptast.cpp index 8a10650..083dd28 100644 --- a/src/declarative/qml/parser/javascriptast.cpp +++ b/src/declarative/qml/parser/javascriptast.cpp @@ -813,6 +813,7 @@ void UiPublicMember::accept0(Visitor *visitor) void UiObjectDefinition::accept0(Visitor *visitor) { if (visitor->visit(this)) { + acceptChild(qualifiedTypeNameId, visitor); acceptChild(initializer, visitor); } @@ -833,6 +834,7 @@ void UiObjectBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { acceptChild(qualifiedId, visitor); + acceptChild(qualifiedTypeNameId, visitor); acceptChild(initializer, visitor); } diff --git a/src/declarative/qml/parser/javascriptast_p.h b/src/declarative/qml/parser/javascriptast_p.h index cd47e42..134f3cc 100644 --- a/src/declarative/qml/parser/javascriptast_p.h +++ b/src/declarative/qml/parser/javascriptast_p.h @@ -53,18 +53,15 @@ // We mean it. // -#include <QtCore/QString> - - - #include "javascriptastvisitor_p.h" +#include <QtCore/QString> QT_BEGIN_NAMESPACE #define JAVASCRIPT_DECLARE_AST_NODE(name) \ enum { K = Kind_##name }; -class JavaScriptNameIdImpl; +class NameId; namespace QSOperator // ### rename { @@ -120,27 +117,6 @@ _T1 cast(_T2 *ast) return 0; } -class SourceLocation -{ -public: - SourceLocation(quint32 offset = 0, quint32 length = 0) - : offset(offset), length(length), - startLine(0), startColumn(0) - { } - - bool isValid() const { return length != 0; } - - quint32 begin() const { return offset; } - quint32 end() const { return offset + length; } - -// attributes - // ### encode - quint32 offset; - quint32 length; - quint32 startLine; - quint32 startColumn; -}; - class Node { public: @@ -339,7 +315,7 @@ class IdentifierExpression: public ExpressionNode public: JAVASCRIPT_DECLARE_AST_NODE(IdentifierExpression) - IdentifierExpression(JavaScriptNameIdImpl *n): + IdentifierExpression(NameId *n): name (n) { kind = K; } virtual ~IdentifierExpression() {} @@ -353,7 +329,7 @@ public: { return identifierToken; } // attributes - JavaScriptNameIdImpl *name; + NameId *name; SourceLocation identifierToken; }; @@ -444,7 +420,7 @@ class StringLiteral: public ExpressionNode public: JAVASCRIPT_DECLARE_AST_NODE(StringLiteral) - StringLiteral(JavaScriptNameIdImpl *v): + StringLiteral(NameId *v): value (v) { kind = K; } virtual ~StringLiteral() {} @@ -458,7 +434,7 @@ public: { return literalToken; } // attributes: - JavaScriptNameIdImpl *value; + NameId *value; SourceLocation literalToken; }; @@ -467,7 +443,7 @@ class RegExpLiteral: public ExpressionNode public: JAVASCRIPT_DECLARE_AST_NODE(RegExpLiteral) - RegExpLiteral(JavaScriptNameIdImpl *p, int f): + RegExpLiteral(NameId *p, int f): pattern (p), flags (f) { kind = K; } virtual ~RegExpLiteral() {} @@ -481,7 +457,7 @@ public: { return literalToken; } // attributes: - JavaScriptNameIdImpl *pattern; + NameId *pattern; int flags; SourceLocation literalToken; }; @@ -667,7 +643,7 @@ class IdentifierPropertyName: public PropertyName public: JAVASCRIPT_DECLARE_AST_NODE(IdentifierPropertyName) - IdentifierPropertyName(JavaScriptNameIdImpl *n): + IdentifierPropertyName(NameId *n): id (n) { kind = K; } virtual ~IdentifierPropertyName() {} @@ -675,7 +651,7 @@ public: virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *id; + NameId *id; }; class StringLiteralPropertyName: public PropertyName @@ -683,14 +659,14 @@ class StringLiteralPropertyName: public PropertyName public: JAVASCRIPT_DECLARE_AST_NODE(StringLiteralPropertyName) - StringLiteralPropertyName(JavaScriptNameIdImpl *n): + StringLiteralPropertyName(NameId *n): id (n) { kind = K; } virtual ~StringLiteralPropertyName() {} virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *id; + NameId *id; }; class NumericLiteralPropertyName: public PropertyName @@ -739,7 +715,7 @@ class FieldMemberExpression: public ExpressionNode public: JAVASCRIPT_DECLARE_AST_NODE(FieldMemberExpression) - FieldMemberExpression(ExpressionNode *b, JavaScriptNameIdImpl *n): + FieldMemberExpression(ExpressionNode *b, NameId *n): base (b), name (n) { kind = K; } @@ -755,7 +731,7 @@ public: // attributes ExpressionNode *base; - JavaScriptNameIdImpl *name; + NameId *name; SourceLocation dotToken; SourceLocation identifierToken; }; @@ -1288,7 +1264,7 @@ class VariableDeclaration: public Node public: JAVASCRIPT_DECLARE_AST_NODE(VariableDeclaration) - VariableDeclaration(JavaScriptNameIdImpl *n, ExpressionNode *e): + VariableDeclaration(NameId *n, ExpressionNode *e): name (n), expression (e), readOnly(false) { kind = K; } @@ -1297,7 +1273,7 @@ public: virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *name; + NameId *name; ExpressionNode *expression; bool readOnly; SourceLocation identifierToken; @@ -1602,7 +1578,7 @@ class ContinueStatement: public Statement public: JAVASCRIPT_DECLARE_AST_NODE(ContinueStatement) - ContinueStatement(JavaScriptNameIdImpl *l = 0): + ContinueStatement(NameId *l = 0): label (l) { kind = K; } virtual ~ContinueStatement() {} @@ -1616,7 +1592,7 @@ public: { return semicolonToken; } // attributes - JavaScriptNameIdImpl *label; + NameId *label; SourceLocation continueToken; SourceLocation identifierToken; SourceLocation semicolonToken; @@ -1627,7 +1603,7 @@ class BreakStatement: public Statement public: JAVASCRIPT_DECLARE_AST_NODE(BreakStatement) - BreakStatement(JavaScriptNameIdImpl *l = 0): + BreakStatement(NameId *l = 0): label (l) { kind = K; } virtual ~BreakStatement() {} @@ -1641,7 +1617,7 @@ public: { return semicolonToken; } // attributes - JavaScriptNameIdImpl *label; + NameId *label; SourceLocation breakToken; SourceLocation identifierToken; SourceLocation semicolonToken; @@ -1823,7 +1799,7 @@ class LabelledStatement: public Statement public: JAVASCRIPT_DECLARE_AST_NODE(LabelledStatement) - LabelledStatement(JavaScriptNameIdImpl *l, Statement *stmt): + LabelledStatement(NameId *l, Statement *stmt): label (l), statement (stmt) { kind = K; } @@ -1838,7 +1814,7 @@ public: { return statement->lastSourceLocation(); } // attributes - JavaScriptNameIdImpl *label; + NameId *label; Statement *statement; SourceLocation identifierToken; SourceLocation colonToken; @@ -1873,7 +1849,7 @@ class Catch: public Node public: JAVASCRIPT_DECLARE_AST_NODE(Catch) - Catch(JavaScriptNameIdImpl *n, Block *stmt): + Catch(NameId *n, Block *stmt): name (n), statement (stmt) { kind = K; } @@ -1882,7 +1858,7 @@ public: virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *name; + NameId *name; Block *statement; SourceLocation catchToken; SourceLocation lparenToken; @@ -1954,7 +1930,7 @@ class FunctionExpression: public ExpressionNode public: JAVASCRIPT_DECLARE_AST_NODE(FunctionExpression) - FunctionExpression(JavaScriptNameIdImpl *n, FormalParameterList *f, FunctionBody *b): + FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b): name (n), formals (f), body (b) { kind = K; } @@ -1969,7 +1945,7 @@ public: { return rbraceToken; } // attributes - JavaScriptNameIdImpl *name; + NameId *name; FormalParameterList *formals; FunctionBody *body; SourceLocation functionToken; @@ -1985,7 +1961,7 @@ class FunctionDeclaration: public FunctionExpression public: JAVASCRIPT_DECLARE_AST_NODE(FunctionDeclaration) - FunctionDeclaration(JavaScriptNameIdImpl *n, FormalParameterList *f, FunctionBody *b): + FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b): FunctionExpression(n, f, b) { kind = K; } @@ -1999,11 +1975,11 @@ class FormalParameterList: public Node public: JAVASCRIPT_DECLARE_AST_NODE(FormalParameterList) - FormalParameterList(JavaScriptNameIdImpl *n): + FormalParameterList(NameId *n): name (n), next (this) { kind = K; } - FormalParameterList(FormalParameterList *previous, JavaScriptNameIdImpl *n): + FormalParameterList(FormalParameterList *previous, NameId *n): name (n) { kind = K; @@ -2023,7 +1999,7 @@ public: } // attributes - JavaScriptNameIdImpl *name; + NameId *name; FormalParameterList *next; SourceLocation commaToken; SourceLocation identifierToken; @@ -2185,11 +2161,11 @@ class UiQualifiedId: public Node public: JAVASCRIPT_DECLARE_AST_NODE(UiQualifiedId) - UiQualifiedId(JavaScriptNameIdImpl *name) + UiQualifiedId(NameId *name) : next(this), name(name) { kind = K; } - UiQualifiedId(UiQualifiedId *previous, JavaScriptNameIdImpl *name) + UiQualifiedId(UiQualifiedId *previous, NameId *name) : name(name) { kind = K; @@ -2210,7 +2186,7 @@ public: // attributes UiQualifiedId *next; - JavaScriptNameIdImpl *name; + NameId *name; SourceLocation identifierToken; }; @@ -2219,14 +2195,14 @@ class UiImport: public Node public: JAVASCRIPT_DECLARE_AST_NODE(UiImport) - UiImport(JavaScriptNameIdImpl *fileName) + UiImport(NameId *fileName) : fileName(fileName) { kind = K; } virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *fileName; + NameId *fileName; SourceLocation importToken; SourceLocation fileNameToken; SourceLocation semicolonToken; @@ -2324,13 +2300,13 @@ class UiPublicMember: public UiObjectMember public: JAVASCRIPT_DECLARE_AST_NODE(UiPublicMember) - UiPublicMember(JavaScriptNameIdImpl *memberType, - JavaScriptNameIdImpl *name) + UiPublicMember(NameId *memberType, + NameId *name) : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false) { kind = K; } - UiPublicMember(JavaScriptNameIdImpl *memberType, - JavaScriptNameIdImpl *name, + UiPublicMember(NameId *memberType, + NameId *name, ExpressionNode *expression) : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false) { kind = K; } @@ -2352,8 +2328,8 @@ public: // attributes enum { Signal, Property } type; - JavaScriptNameIdImpl *memberType; - JavaScriptNameIdImpl *name; + NameId *memberType; + NameId *name; ExpressionNode *expression; bool isDefaultMember; SourceLocation defaultToken; @@ -2369,28 +2345,22 @@ class UiObjectDefinition: public UiObjectMember public: JAVASCRIPT_DECLARE_AST_NODE(UiObjectDefinition) - UiObjectDefinition(JavaScriptNameIdImpl *name, + UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) - : name(name), initializer(initializer) + : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) { kind = K; } virtual SourceLocation firstSourceLocation() const - { return identifierToken; } + { return qualifiedTypeNameId->identifierToken; } virtual SourceLocation lastSourceLocation() const - { - if (initializer) - return initializer->rbraceToken; - - return identifierToken; - } + { return initializer->rbraceToken; } virtual void accept0(Visitor *visitor); // attributes - JavaScriptNameIdImpl *name; + UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; - SourceLocation identifierToken; }; class UiSourceElement: public UiObjectMember @@ -2435,10 +2405,10 @@ public: JAVASCRIPT_DECLARE_AST_NODE(UiObjectBinding) UiObjectBinding(UiQualifiedId *qualifiedId, - JavaScriptNameIdImpl *name, + UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) : qualifiedId(qualifiedId), - name(name), + qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) { kind = K; } @@ -2452,10 +2422,9 @@ public: // attributes UiQualifiedId *qualifiedId; - JavaScriptNameIdImpl *name; + UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; SourceLocation colonToken; - SourceLocation identifierToken; }; class UiScriptBinding: public UiObjectMember diff --git a/src/declarative/qml/parser/javascriptastfwd_p.h b/src/declarative/qml/parser/javascriptastfwd_p.h index 858e393..822a2d7 100644 --- a/src/declarative/qml/parser/javascriptastfwd_p.h +++ b/src/declarative/qml/parser/javascriptastfwd_p.h @@ -59,7 +59,26 @@ QT_BEGIN_NAMESPACE namespace JavaScript { namespace AST { -class SourceLocation; +class SourceLocation +{ +public: + SourceLocation(quint32 offset = 0, quint32 length = 0) + : offset(offset), length(length), + startLine(0), startColumn(0) + { } + + bool isValid() const { return length != 0; } + + quint32 begin() const { return offset; } + quint32 end() const { return offset + length; } + +// attributes + // ### encode + quint32 offset; + quint32 length; + quint32 startLine; + quint32 startColumn; +}; class Visitor; class Node; diff --git a/src/declarative/qml/parser/javascriptengine_p.cpp b/src/declarative/qml/parser/javascriptengine_p.cpp index ca15b75..d893a90 100644 --- a/src/declarative/qml/parser/javascriptengine_p.cpp +++ b/src/declarative/qml/parser/javascriptengine_p.cpp @@ -29,7 +29,6 @@ #include "javascriptengine_p.h" #include "javascriptnodepool_p.h" -#include "javascriptvalue.h" #include <qnumeric.h> #include <QHash> @@ -37,7 +36,10 @@ QT_BEGIN_NAMESPACE namespace JavaScript { -QString numberToString(qjsreal value) +uint qHash(const JavaScript::NameId &id) +{ return qHash(id.asString()); } + +QString numberToString(double value) { return QString::number(value); } int Ecma::RegExp::flagFromChar(const QChar &ch) @@ -67,9 +69,10 @@ QString Ecma::RegExp::flagsToString(int flags) return result; } -NodePool::NodePool(const QString &fileName, JavaScriptEnginePrivate *engine) +NodePool::NodePool(const QString &fileName, Engine *engine) : m_fileName(fileName), m_engine(engine) { + m_engine->setNodePool(this); } NodePool::~NodePool() @@ -93,12 +96,12 @@ static int toDigit(char c) return -1; } -qjsreal integerFromString(const char *buf, int size, int radix) +double integerFromString(const char *buf, int size, int radix) { if (size == 0) return qSNaN(); - qjsreal sign = 1.0; + double sign = 1.0; int i = 0; if (buf[0] == '+') { ++i; @@ -130,7 +133,7 @@ qjsreal integerFromString(const char *buf, int size, int radix) if ((d == -1) || (d >= radix)) break; } - qjsreal result; + double result; if (j == i) { if (!qstrcmp(buf, "Infinity")) result = qInf(); @@ -138,7 +141,7 @@ qjsreal integerFromString(const char *buf, int size, int radix) result = qSNaN(); } else { result = 0; - qjsreal multiplier = 1; + double multiplier = 1; for (--i ; i >= j; --i, multiplier *= radix) result += toDigit(buf[i]) * multiplier; } @@ -146,12 +149,43 @@ qjsreal integerFromString(const char *buf, int size, int radix) return result; } -qjsreal integerFromString(const QString &str, int radix) +double integerFromString(const QString &str, int radix) { QByteArray ba = str.trimmed().toUtf8(); return integerFromString(ba.constData(), ba.size(), radix); } + +Engine::Engine() + : _lexer(0), _nodePool(0) +{ } + +Engine::~Engine() +{ } + +QSet<NameId> Engine::literals() const +{ return _literals; } + +NameId *Engine::intern(const QChar *u, int s) +{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); } + +QString Engine::toString(NameId *id) +{ return id->asString(); } + +Lexer *Engine::lexer() const +{ return _lexer; } + +void Engine::setLexer(Lexer *lexer) +{ _lexer = lexer; } + +NodePool *Engine::nodePool() const +{ return _nodePool; } + +void Engine::setNodePool(NodePool *nodePool) +{ _nodePool = nodePool; } + + + } // end of namespace JavaScript QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/javascriptengine_p.h b/src/declarative/qml/parser/javascriptengine_p.h index 1e6e568..3bd924a 100644 --- a/src/declarative/qml/parser/javascriptengine_p.h +++ b/src/declarative/qml/parser/javascriptengine_p.h @@ -30,23 +30,50 @@ #ifndef JAVASCRIPTENGINE_P_H #define JAVASCRIPTENGINE_P_H -#include "javascriptvalue.h" #include <QString> #include <QSet> +#include "javascriptastfwd_p.h" + QT_BEGIN_NAMESPACE namespace JavaScript { +class NameId +{ + QString _text; -class Node; -class Lexer; -class NodePool; +public: + NameId(const QChar *u, int s) + : _text(u, s) + { } -namespace AST { + const QString asString() const + { return _text; } -class Node; + bool operator == (const NameId &other) const + { return _text == other._text; } -} // end of namespace AST + bool operator != (const NameId &other) const + { return _text != other._text; } + + bool operator < (const NameId &other) const + { return _text < other._text; } +}; + +uint qHash(const JavaScript::NameId &id); + +} // end of namespace JavaScript + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +//this ensures that code outside JavaScript can use the hash function +//it also a workaround for some compilers +inline uint qHash(const JavaScript::NameId &nameId) { return JavaScript::qHash(nameId); } +#endif + +namespace JavaScript { + +class Lexer; +class NodePool; namespace Ecma { @@ -66,79 +93,53 @@ public: } // end of namespace Ecma -} // end of namespace JavaScript - - - -class JavaScriptNameIdImpl +class DiagnosticMessage { - QString _text; - public: - JavaScriptNameIdImpl(const QChar *u, int s) - : _text(u, s) - { } + enum Kind { Warning, Error }; - const QString asString() const - { return _text; } + DiagnosticMessage() + : kind(Error) {} - bool operator == (const JavaScriptNameIdImpl &other) const - { return _text == other._text; } + DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) + : kind(kind), loc(loc), message(message) {} - bool operator != (const JavaScriptNameIdImpl &other) const - { return _text != other._text; } + bool isWarning() const + { return kind == Warning; } - bool operator < (const JavaScriptNameIdImpl &other) const - { return _text < other._text; } -}; + bool isError() const + { return kind == Error; } -inline uint qHash(const JavaScriptNameIdImpl &id) -{ return qHash(id.asString()); } + Kind kind; + AST::SourceLocation loc; + QString message; +}; -class JavaScriptEnginePrivate +class Engine { - JavaScript::Lexer *_lexer; - JavaScript::NodePool *_nodePool; - JavaScript::AST::Node *_ast; - QSet<JavaScriptNameIdImpl> _literals; + Lexer *_lexer; + NodePool *_nodePool; + QSet<NameId> _literals; public: - JavaScriptEnginePrivate() - : _lexer(0), _nodePool(0), _ast(0) - { } - - QSet<JavaScriptNameIdImpl> literals() const - { return _literals; } + Engine(); + ~Engine(); - JavaScriptNameIdImpl *intern(const QChar *u, int s) - { return const_cast<JavaScriptNameIdImpl *>(&*_literals.insert(JavaScriptNameIdImpl(u, s))); } + QSet<NameId> literals() const; - static QString toString(JavaScriptNameIdImpl *id) - { return id->asString(); } + NameId *intern(const QChar *u, int s); - JavaScript::Lexer *lexer() const - { return _lexer; } + static QString toString(NameId *id); - void setLexer(JavaScript::Lexer *lexer) - { _lexer = lexer; } + Lexer *lexer() const; + void setLexer(Lexer *lexer); - JavaScript::NodePool *nodePool() const - { return _nodePool; } - - void setNodePool(JavaScript::NodePool *nodePool) - { _nodePool = nodePool; } - - JavaScript::AST::Node *ast() const - { return _ast; } - - JavaScript::AST::Node *changeAbstractSyntaxTree(JavaScript::AST::Node *node) - { - JavaScript::AST::Node *previousAST = _ast; - _ast = node; - return previousAST; - } + NodePool *nodePool() const; + void setNodePool(NodePool *nodePool); }; +} // end of namespace JavaScript + QT_END_NAMESPACE #endif // JAVASCRIPTENGINE_P_H diff --git a/src/declarative/qml/parser/javascriptgrammar.cpp b/src/declarative/qml/parser/javascriptgrammar.cpp index abe3f1c..a879bfe 100644 --- a/src/declarative/qml/parser/javascriptgrammar.cpp +++ b/src/declarative/qml/parser/javascriptgrammar.cpp @@ -56,527 +56,585 @@ const char *const JavaScriptGrammar::spell [] = { const int JavaScriptGrammar::lhs [] = { 91, 92, 92, 95, 95, 96, 96, 94, 93, 98, - 98, 100, 100, 101, 101, 99, 97, 99, 99, 103, - 104, 104, 99, 99, 106, 106, 106, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 102, 102, - 110, 110, 110, 102, 102, 111, 111, 111, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 113, 113, 117, 117, 112, 112, 115, 115, 118, 118, - 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 120, 120, 121, 121, 121, - 121, 121, 124, 124, 125, 125, 125, 125, 123, 123, - 126, 126, 127, 127, 128, 128, 128, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 130, 130, 130, - 130, 131, 131, 131, 132, 132, 132, 132, 133, 133, - 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, - 134, 135, 135, 135, 135, 135, 136, 136, 136, 136, - 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, + 98, 100, 100, 101, 101, 97, 99, 99, 103, 104, + 104, 99, 99, 99, 99, 99, 99, 99, 111, 111, + 111, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 102, 102, 114, 114, 114, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 115, 115, 115, 102, 102, 117, 117, 117, 117, + 116, 116, 119, 119, 121, 121, 121, 121, 121, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 123, 123, 124, 124, 124, 124, 124, 127, 127, + 128, 128, 128, 128, 126, 126, 129, 129, 130, 130, + 131, 131, 131, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, + 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, + 136, 137, 137, 137, 137, 137, 137, 138, 138, 138, + 138, 138, 139, 139, 139, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143, 144, 144, 145, 145, 146, - 146, 147, 147, 148, 148, 116, 116, 149, 149, 150, - 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 150, 107, 107, 151, 151, 152, 152, 153, 153, 105, - 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 154, 169, 169, 168, 168, 109, - 109, 170, 170, 171, 171, 173, 173, 172, 174, 177, - 175, 175, 178, 176, 176, 155, 156, 156, 157, 157, - 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, - 159, 160, 160, 160, 160, 161, 161, 162, 164, 179, - 179, 182, 182, 180, 180, 183, 181, 163, 163, 163, - 165, 165, 166, 166, 166, 184, 185, 167, 167, 108, - 122, 189, 189, 186, 186, 187, 187, 190, 191, 191, - 192, 192, 188, 188, 114, 114, 193}; + 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, + 151, 120, 120, 152, 152, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 105, 105, 154, + 154, 155, 155, 156, 156, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 106, 168, 168, 167, 167, 113, 113, 169, 169, 170, + 170, 172, 172, 171, 173, 176, 174, 174, 177, 175, + 175, 107, 108, 108, 110, 110, 158, 158, 158, 158, + 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, + 160, 161, 161, 162, 164, 178, 178, 181, 181, 179, + 179, 182, 180, 163, 163, 163, 165, 165, 166, 166, + 166, 183, 184, 109, 109, 112, 125, 188, 188, 185, + 185, 186, 186, 189, 190, 190, 191, 191, 187, 187, + 118, 118, 192}; const int JavaScriptGrammar:: rhs[] = { 2, 1, 1, 1, 2, 3, 3, 0, 1, 1, - 2, 1, 3, 2, 3, 4, 2, 1, 5, 1, - 2, 2, 3, 3, 1, 1, 1, 2, 4, 4, - 5, 5, 6, 6, 7, 7, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 5, 3, 4, 3, - 2, 4, 1, 2, 0, 1, 3, 5, 1, 1, + 2, 1, 3, 2, 3, 2, 1, 5, 1, 2, + 2, 4, 3, 3, 3, 3, 3, 3, 1, 1, + 1, 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, 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, 3, 3, 3, 3, - 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, 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, 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, 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, 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, - 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, 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 JavaScriptGrammar::action_default [] = { 8, 2, 0, 4, 3, 0, 0, 0, 6, 7, - 5, 0, 9, 1, 0, 17, 37, 44, 242, 0, - 0, 41, 42, 14, 39, 40, 43, 243, 18, 10, - 0, 0, 0, 38, 0, 27, 26, 25, 0, 0, - 31, 0, 32, 145, 212, 176, 184, 180, 124, 196, - 172, 0, 109, 47, 125, 188, 192, 113, 142, 123, - 128, 108, 162, 149, 0, 53, 54, 50, 313, 41, - 315, 65, 0, 0, 0, 0, 0, 48, 51, 0, - 0, 42, 43, 52, 46, 0, 49, 0, 0, 138, - 0, 0, 125, 144, 127, 126, 0, 0, 0, 140, - 141, 139, 143, 0, 173, 0, 0, 0, 0, 163, - 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, - 147, 148, 146, 151, 155, 154, 152, 150, 165, 164, - 166, 0, 181, 0, 177, 0, 0, 119, 106, 118, - 107, 75, 76, 77, 102, 78, 103, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 104, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 105, 0, 0, 117, 213, 120, 0, 121, 0, - 122, 116, 35, 36, 0, 209, 202, 200, 207, 208, - 206, 205, 211, 204, 203, 201, 210, 197, 0, 185, - 0, 0, 189, 0, 0, 193, 0, 0, 119, 111, - 0, 110, 0, 115, 129, 0, 314, 304, 305, 0, - 302, 0, 303, 0, 306, 220, 227, 226, 234, 222, - 0, 223, 307, 0, 312, 224, 225, 230, 228, 309, - 308, 311, 231, 0, 0, 0, 0, 0, 313, 41, - 0, 315, 42, 214, 256, 43, 0, 0, 0, 0, - 0, 232, 233, 221, 229, 257, 258, 301, 310, 0, - 272, 273, 274, 275, 0, 268, 269, 270, 271, 298, - 299, 0, 0, 0, 0, 0, 261, 262, 218, 216, - 178, 186, 182, 198, 174, 219, 0, 125, 190, 194, - 167, 156, 0, 0, 175, 0, 0, 0, 0, 168, - 0, 0, 0, 0, 0, 160, 158, 161, 159, 157, - 170, 169, 171, 0, 183, 0, 179, 0, 217, 125, - 0, 199, 214, 215, 0, 214, 0, 0, 264, 0, - 0, 0, 266, 0, 187, 0, 0, 191, 0, 0, - 195, 254, 0, 246, 255, 249, 0, 253, 0, 214, - 247, 0, 214, 0, 0, 265, 0, 0, 0, 267, - 314, 304, 0, 0, 306, 0, 300, 0, 290, 0, - 0, 0, 260, 0, 259, 0, 316, 0, 74, 236, - 239, 0, 75, 242, 78, 103, 80, 81, 50, 85, - 86, 41, 87, 90, 48, 51, 42, 214, 43, 52, - 93, 46, 95, 49, 97, 98, 243, 100, 101, 105, - 0, 67, 0, 0, 69, 73, 71, 59, 70, 72, - 0, 68, 58, 237, 235, 113, 114, 119, 0, 112, - 0, 289, 0, 276, 277, 0, 288, 0, 0, 0, - 279, 284, 282, 285, 0, 0, 283, 284, 0, 280, - 0, 281, 238, 287, 0, 238, 286, 0, 291, 292, - 0, 238, 293, 294, 0, 0, 295, 0, 0, 0, - 296, 297, 131, 130, 0, 0, 0, 263, 0, 0, - 0, 278, 0, 66, 0, 63, 65, 56, 0, 62, - 57, 64, 61, 55, 0, 60, 135, 133, 137, 134, - 132, 136, 0, 0, 0, 29, 0, 30, 0, 33, - 34, 28, 15, 11, 0, 0, 24, 41, 65, 20, - 0, 23, 16, 0, 12, 0, 19, 13, 21, 22, - 45, 251, 244, 0, 252, 248, 0, 250, 240, 0, - 241, 245, 317}; + 5, 65, 45, 46, 43, 44, 47, 9, 0, 1, + 0, 0, 16, 66, 41, 248, 0, 0, 46, 14, + 47, 249, 17, 10, 0, 0, 0, 42, 0, 31, + 30, 29, 0, 0, 35, 0, 36, 151, 218, 182, + 190, 186, 130, 202, 178, 0, 115, 49, 131, 194, + 198, 119, 148, 129, 134, 114, 168, 155, 0, 55, + 56, 52, 319, 321, 0, 0, 0, 0, 0, 0, + 50, 53, 0, 0, 54, 48, 0, 51, 0, 0, + 144, 0, 0, 131, 150, 133, 132, 0, 0, 0, + 146, 147, 145, 149, 0, 179, 0, 0, 0, 0, + 169, 0, 0, 0, 0, 0, 0, 159, 0, 0, + 0, 153, 154, 152, 157, 161, 160, 158, 156, 171, + 170, 172, 0, 187, 0, 183, 0, 0, 125, 112, + 124, 113, 81, 82, 83, 108, 84, 109, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 110, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 111, 0, 0, 123, 219, 126, 0, 127, + 0, 128, 122, 39, 40, 0, 215, 208, 206, 213, + 214, 212, 211, 217, 210, 209, 207, 216, 203, 0, + 191, 0, 0, 195, 0, 0, 199, 0, 0, 125, + 117, 0, 116, 0, 121, 135, 0, 320, 310, 311, + 0, 308, 0, 309, 0, 312, 226, 233, 232, 240, + 228, 0, 229, 313, 0, 318, 230, 231, 236, 234, + 315, 314, 317, 237, 0, 0, 0, 0, 0, 319, + 45, 0, 321, 46, 220, 262, 47, 0, 0, 0, + 0, 0, 238, 239, 227, 235, 263, 264, 307, 316, + 0, 278, 279, 280, 281, 0, 274, 275, 276, 277, + 304, 305, 0, 0, 0, 0, 0, 267, 268, 224, + 222, 184, 192, 188, 204, 180, 225, 0, 131, 196, + 200, 173, 162, 0, 0, 181, 0, 0, 0, 0, + 174, 0, 0, 0, 0, 0, 166, 164, 167, 165, + 163, 176, 175, 177, 0, 189, 0, 185, 0, 223, + 131, 0, 205, 220, 221, 0, 220, 0, 0, 270, + 0, 0, 0, 272, 0, 193, 0, 0, 197, 0, + 0, 201, 260, 0, 252, 261, 255, 0, 259, 0, + 220, 253, 0, 220, 0, 0, 271, 0, 0, 0, + 273, 320, 310, 0, 0, 312, 0, 306, 0, 296, + 0, 0, 0, 266, 0, 265, 0, 322, 0, 80, + 242, 245, 0, 81, 248, 84, 109, 86, 87, 52, + 91, 92, 45, 93, 96, 50, 53, 46, 220, 47, + 54, 99, 48, 101, 51, 103, 104, 249, 106, 107, + 111, 0, 73, 0, 0, 75, 79, 77, 63, 76, + 78, 0, 74, 62, 243, 241, 119, 120, 125, 0, + 118, 0, 295, 0, 282, 283, 0, 294, 0, 0, + 0, 285, 290, 288, 291, 0, 0, 289, 290, 0, + 286, 0, 287, 244, 293, 0, 244, 292, 0, 297, + 298, 0, 244, 299, 300, 0, 0, 301, 0, 0, + 0, 302, 303, 137, 136, 0, 0, 0, 269, 0, + 0, 0, 284, 67, 0, 0, 71, 57, 0, 59, + 69, 0, 60, 70, 72, 61, 68, 58, 0, 64, + 141, 139, 143, 140, 138, 142, 0, 0, 0, 33, + 0, 34, 0, 37, 38, 32, 15, 11, 0, 23, + 26, 24, 0, 25, 28, 244, 0, 19, 0, 27, + 22, 81, 248, 84, 109, 86, 87, 52, 91, 92, + 45, 93, 96, 50, 53, 46, 220, 47, 54, 99, + 48, 101, 51, 103, 104, 249, 106, 107, 111, 49, + 0, 12, 0, 18, 13, 20, 21, 257, 250, 0, + 258, 254, 0, 256, 246, 0, 247, 251, 323}; const int JavaScriptGrammar::goto_default [] = { - 6, 5, 13, 1, 4, 3, 28, 30, 29, 533, - 15, 31, 530, 531, 389, 513, 230, 234, 263, 53, - 61, 494, 492, 387, 386, 44, 493, 385, 388, 139, - 57, 52, 177, 59, 48, 176, 54, 60, 89, 58, - 43, 63, 62, 300, 50, 294, 45, 290, 47, 292, - 46, 291, 55, 298, 56, 299, 49, 293, 289, 330, - 442, 295, 296, 225, 229, 231, 235, 236, 227, 226, - 238, 264, 237, 242, 261, 262, 228, 391, 390, 32, - 543, 542, 352, 353, 545, 355, 544, 354, 450, 454, - 457, 453, 452, 472, 473, 219, 233, 215, 218, 232, - 240, 239, 0}; + 6, 5, 19, 1, 4, 3, 32, 34, 33, 570, + 22, 18, 538, 539, 231, 226, 230, 232, 229, 236, + 517, 235, 264, 57, 65, 495, 494, 388, 387, 48, + 386, 389, 140, 61, 56, 178, 63, 52, 177, 58, + 64, 90, 62, 47, 67, 66, 301, 54, 295, 49, + 291, 51, 293, 50, 292, 59, 299, 60, 300, 53, + 294, 290, 331, 443, 296, 297, 390, 237, 228, 227, + 239, 265, 238, 243, 262, 263, 392, 391, 36, 579, + 578, 353, 354, 581, 356, 580, 355, 451, 455, 458, + 454, 453, 473, 474, 220, 234, 216, 219, 233, 241, + 240, 0}; const int JavaScriptGrammar::action_index [] = { - -23, -91, 10, -91, -19, 50, 77, 56, -91, -91, - -91, 67, -91, -91, 383, -91, -91, -91, -91, -4, - 213, 20, 186, -91, -91, -91, -18, -91, -91, -91, - 370, 129, 203, -91, 204, -91, -91, -91, -17, 192, - -91, 693, -91, 87, -91, 42, 9, -20, 191, -91, - 310, 140, -91, -91, 534, 17, 114, 160, 125, -91, - -91, -91, 344, 162, 693, -91, -91, -91, 157, -91, - 1191, 34, 693, 693, 693, 613, 693, -91, -91, 693, - 693, -91, -91, -91, -91, 693, -91, 693, 693, -91, - 693, 693, 119, 227, -91, -91, 693, 693, 693, -91, - -91, -91, 193, 693, 310, 693, 693, 693, 693, 446, - 693, 693, 693, 693, 693, 693, 237, 693, 693, 693, - 88, 106, 107, 237, 237, 166, 237, 237, 354, 372, - 334, 693, -11, 693, 19, 1104, 693, 693, -91, -91, + 8, -91, 14, -91, -15, 296, 67, 94, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, 109, -91, + 184, 408, -91, -91, -91, -91, 45, 125, 170, -91, + 46, -91, -91, -91, 429, 171, 130, -91, 120, -91, + -91, -91, -19, 169, -91, 733, -91, 72, -91, 22, + -26, -59, 173, -91, 278, 174, -91, -91, 574, 51, + 112, 183, 177, -91, -91, -91, 412, 214, 733, -91, + -91, -91, 161, 1566, 980, 733, 733, 733, 653, 733, + -91, -91, 733, 733, -91, -91, 733, -91, 733, 733, + -91, 733, 733, 98, 235, -91, -91, 733, 733, 733, + -91, -91, -91, 230, 733, 276, 733, 733, 733, 733, + 396, 733, 733, 733, 733, 733, 733, 288, 733, 733, + 733, 88, 87, 74, 288, 288, 288, 218, 221, 486, + 372, 362, 733, 4, 733, 76, 1479, 733, 733, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, -91, 98, 693, -91, -91, 0, -43, -91, 693, - -91, -91, -91, -91, 693, -91, -91, -91, -91, -91, - -91, -91, -91, -91, -91, -91, -91, -91, 693, 6, - 693, 693, -2, 82, 693, -91, 1104, 693, 693, -91, - 96, -91, 8, -91, -91, 61, -91, 147, 80, 33, - -91, 154, -91, 63, 1452, -91, -91, -91, -91, -91, - 169, -91, -91, 23, -91, -91, -91, -91, -91, -91, - 1452, -91, -91, 285, 287, 68, 1365, 55, 112, 79, - 46, 1626, 66, 693, -91, 65, 47, 693, 52, 58, - 59, -91, -91, -91, -91, -91, -91, -91, -91, 64, - -91, -91, -91, -91, 73, -91, -91, -91, -91, -91, - -91, -5, 45, 693, 137, 81, -91, -91, 1017, -91, - 69, 28, 14, -91, 240, 76, 53, 476, 171, 120, - 308, 237, 180, 693, 264, 693, 693, 693, 693, 298, - 693, 693, 693, 693, 693, 230, 237, 237, 237, 237, - 288, 268, 378, 693, -68, 693, 12, 693, -91, 445, - 693, -91, 693, 7, -47, 693, -44, 1365, -91, 693, - 100, 1365, -91, 693, -25, 693, 693, 22, 15, 693, - -91, -8, 108, -13, -91, -91, 693, -91, 178, 693, - -91, -60, 693, -58, 1365, -91, 693, 99, 1365, -91, - -33, 199, -53, -27, 1452, -26, -91, 1365, -91, 693, - 95, 1365, 32, 1365, -91, 43, 41, 4, -91, -91, - 1365, 5, 232, 54, 275, 70, 693, 1365, 49, 27, - 252, 48, 30, 613, 40, 39, -91, 777, -91, 25, - -1, 26, 693, 24, -3, 693, 21, 693, 1, 2, - 693, -91, 1278, 37, -91, -91, -91, -91, -91, -91, - 693, -91, -91, -91, -91, 156, -91, 693, -21, -91, - 1365, -91, 60, -91, -91, 1365, -91, 693, 102, 3, - -91, 29, -91, 35, 101, 693, -91, 36, 38, -91, - -30, -91, 1365, -91, 94, 1365, -91, 176, -91, -91, - 143, 1365, 44, -91, 16, -6, -91, 207, -9, -29, - -91, -91, -91, -91, 693, 90, 1365, -91, 693, 91, - 1365, -91, 111, 13, 857, -91, 18, -91, 937, -91, - -91, -91, -91, -91, 105, -91, -91, -91, -91, -91, - -91, -91, -33, -24, 215, -91, 693, -91, 187, -91, - -91, -91, -91, -91, 1539, 174, -91, 133, 104, -91, - 62, -91, -91, 97, -91, 51, -91, -91, -91, -91, - -91, 57, -91, 173, -91, -91, 693, -91, -91, 151, - -91, -91, -91, + -91, -91, -91, 102, 733, -91, -91, 60, 3, -91, + 733, -91, -91, -91, -91, 733, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91, -91, -91, -91, 733, + -6, 733, 733, 30, 32, 733, -91, 1479, 733, 733, + -91, 107, -91, -14, -91, -91, 69, -91, 191, 49, + 18, -91, 233, -91, 47, 1827, -91, -91, -91, -91, + -91, 204, -91, -91, 39, -91, -91, -91, -91, -91, + -91, 1827, -91, -91, 322, 281, 103, 1740, 50, 203, + 77, 40, 2001, 53, 733, -91, 52, 29, 733, 25, + 28, 35, -91, -91, -91, -91, -91, -91, -91, -91, + 113, -91, -91, -91, -91, 106, -91, -91, -91, -91, + -91, -91, 15, 68, 733, 135, 119, -91, -91, 897, + -91, 82, 58, 17, -91, 261, 84, 42, 494, 91, + 79, 304, 288, 208, 733, 245, 733, 733, 733, 733, + 418, 733, 733, 733, 733, 733, 288, 288, 288, 288, + 288, 343, 336, 279, 733, -57, 733, 19, 733, -91, + 574, 733, -91, 733, -7, -30, 733, -60, 1740, -91, + 733, 111, 1740, -91, 733, 2, 733, 733, 43, 37, + 733, -91, 34, 118, 23, -91, -91, 733, -91, 238, + 733, -91, -5, 733, -17, 1740, -91, 733, 133, 1740, + -91, -9, 194, -32, -8, 1827, -25, -91, 1740, -91, + 733, 100, 1740, 21, 1740, -91, 31, 26, -20, -91, + -91, 1740, -38, 283, 41, 291, 85, 733, 1740, -1, + -34, 252, 54, -27, 653, 9, 5, -91, 817, -91, + 6, -21, 7, 733, 11, -28, 733, 1, 733, -33, + -10, 733, -91, 1653, 33, -91, -91, -91, -91, -91, + -91, 733, -91, -91, -91, -91, 172, -91, 733, -24, + -91, 1740, -91, 73, -91, -91, 1740, -91, 733, 93, + 0, -91, 24, -91, 36, 122, 733, -91, 44, 48, + -91, -3, -91, 1740, -91, 110, 1740, -91, 192, -91, + -91, 124, 1740, 27, -91, -12, -29, -91, 155, -53, + -22, -91, -91, -91, -91, 733, 123, 1740, -91, 733, + 92, 1740, -91, -91, 105, 1229, -91, -91, 1146, -91, + -91, 1063, -91, -91, -91, -91, -91, -91, 90, -91, + -91, -91, -91, -91, -91, -91, 71, 70, 222, -91, + 733, -91, 164, -91, -91, -91, -91, -91, 1392, -91, + -91, -91, 268, -91, -91, 1914, 1312, -91, 75, -91, + -91, 350, 55, 303, 108, 733, 1740, 59, 38, 242, + 62, 40, 527, 63, 81, -91, 817, -91, 138, 29, + 65, 733, 78, 56, 733, 80, 733, 61, 66, 57, + 101, -91, 347, -91, -91, -91, -91, 64, -91, 140, + -91, -91, 733, -91, -91, 144, -91, -91, -91, - -103, -103, -103, -103, 15, 16, -103, -103, -103, -103, - -103, -103, -103, -103, 208, -103, -103, -103, -103, -103, - -1, -103, -103, -103, -103, -103, -103, -103, -103, -103, - 237, -103, 26, -103, 31, -103, -103, -103, -103, -103, - -103, 28, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -46, -103, -103, -103, -103, -103, - -103, -103, -103, -103, 98, -103, -103, -103, 7, -103, - -103, -103, -10, 118, 111, 67, 112, -103, -103, 119, - 123, -103, -103, -103, -103, 124, -103, 115, 97, -103, - 32, 106, -103, -103, -103, -103, 128, 171, 101, -103, - -103, -103, -103, 156, -103, 157, 159, 81, 131, -103, - 127, 136, 145, 139, 102, 91, -103, 59, 50, 72, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, 70, -103, 80, -103, 85, 61, 51, -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, 54, -103, -103, -103, -103, -103, -24, - -103, -103, -103, -103, -23, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, -103, -103, 134, -103, - 138, 17, -103, -103, 23, -103, 255, -4, 73, -103, - -103, -103, -103, -103, -103, -103, -103, 11, -103, -103, - -103, 8, -103, -103, 9, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - 77, -103, -103, 10, 2, -103, 5, -103, -3, -103, - -103, -103, -103, 19, -103, -103, -103, 27, -31, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -5, -103, -103, -103, -103, 105, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, 34, 205, -103, 193, 169, 181, 201, -103, - 147, 66, 78, 79, 89, -103, -103, -103, -103, -103, - -103, -103, -103, 202, -103, 192, -103, 212, -103, -103, - 182, -103, 68, -103, -103, 62, -103, 56, -103, 33, - -103, 55, -103, 170, -103, 161, 162, -103, -103, 172, - -103, -103, -103, -103, -103, -103, 211, -103, 69, 71, - -103, -103, 64, -103, 60, -103, 41, -103, 42, -103, - -103, 74, -103, -103, 75, -103, -103, 38, -103, 35, - -103, 36, -103, 44, -103, -103, -103, -103, -103, -103, - 52, -103, 45, -103, 43, -103, 65, 46, -103, -103, - 40, -103, -103, 146, -103, -103, -103, 49, -103, -103, - -103, -103, 47, -103, -22, 149, -103, 153, -103, -103, - 30, -103, 48, -103, -103, -103, -103, -103, -103, -103, - 29, -103, -103, -103, -103, -103, -103, 133, -103, -103, - 53, -103, -103, -103, -103, 58, -103, 57, -103, -103, - -103, -103, -103, -56, -103, -6, -103, -82, -103, -103, - -103, -103, -77, -103, -103, -68, -103, -103, -103, -103, - -103, -103, -90, -103, -103, -58, -103, -11, -103, -60, - -103, -103, -103, -103, 21, -103, 25, -103, 22, -103, - 20, -103, -103, -103, 6, -103, 12, -103, 3, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, 24, -103, -103, -103, - -103, -103, -103, -103, 1, -2, -103, 4, 104, -103, - -103, -103, -103, -103, -103, 18, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, 0, -103, -103, 63, - -103, -103, -103}; + -102, -102, -102, -102, 19, 103, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -4, 249, -102, -102, -102, -102, -102, -7, -102, -102, + -102, -102, -102, -102, 257, -102, -13, -102, -11, -102, + -102, -102, -102, -102, -102, -3, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -44, -102, + -102, -102, -102, -102, -102, -102, -102, -102, 141, -102, + -102, -102, -8, -102, 0, 16, 116, 122, 129, 119, + -102, -102, 90, 64, -102, -102, 94, -102, 91, 86, + -102, 71, 79, -102, -102, -102, -102, 159, 81, 76, + -102, -102, -102, -102, 98, -102, 67, 63, 47, 163, + -102, 160, 115, 104, 105, 127, 133, -102, 151, 144, + 130, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, 145, -102, 152, -102, 162, 31, 21, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, 23, -102, -102, -102, -102, -102, + 29, -102, -102, -102, -102, 34, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, 89, + -102, 68, 36, -102, -102, 42, -102, 235, 46, 49, + -102, -102, -102, -102, -102, -102, -102, -102, 33, -102, + -102, -102, 26, -102, -102, -18, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, 53, -102, -102, 8, 20, -102, -5, -102, 32, + -102, -102, -102, -102, 39, -102, -102, -102, 37, 73, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, 40, -102, -102, -102, -102, 97, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, 41, 213, -102, 186, 199, 203, 209, + -102, 50, 51, 38, 57, 60, -102, -102, -102, -102, + -102, -102, -102, -102, 212, -102, 174, -102, 166, -102, + -102, 168, -102, 125, -102, -102, 61, -102, 1, -102, + 45, -102, -9, -102, 172, -102, 184, 176, -102, -102, + 170, -102, -102, -102, -102, -102, -102, 215, -102, 124, + 132, -102, -102, 178, -102, -29, -102, 25, -102, 2, + -102, -102, 62, -102, -102, 102, -102, -102, -28, -102, + 22, -102, -31, -102, -33, -102, -102, -102, -102, -102, + -102, -34, -102, 17, -102, 18, -102, 111, -20, -102, + -102, 24, -102, -102, 153, -102, -102, -102, 30, -102, + -102, -102, -102, 28, -102, 73, 140, -102, 205, -102, + -102, 5, -102, 44, -102, -102, -102, -102, -102, -102, + -102, 43, -102, -102, -102, -102, -102, -102, 135, -102, + -102, 7, -102, -102, -102, -102, 4, -102, 55, -102, + -102, -102, -102, -102, -25, -102, 48, -102, 9, -102, + -102, -102, -102, -69, -102, -102, -70, -102, -102, -102, + -102, -102, -102, -92, -102, -102, -12, -102, -10, -102, + -1, -102, -102, -102, -102, 11, -102, -40, -102, 14, + -102, -39, -102, -102, -102, -17, -102, -102, 54, -102, + -102, -24, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + 3, -102, -102, -102, -102, -102, -102, -102, 267, -102, + -102, -102, 12, -102, -102, -102, 301, -102, -102, -102, + -102, -19, -102, -15, -102, 59, -64, -102, -102, -2, + -102, -102, 142, -102, -102, -102, -14, -102, -102, -102, + -102, 6, -102, 73, 52, -102, 75, -102, -102, -102, + -102, -102, 128, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -6, -102, -102, 58, -102, -102, -102}; const int JavaScriptGrammar::action_info [] = { - 198, 362, 364, 371, 471, 514, 374, 373, 179, 356, - 325, 521, 39, 303, 335, 173, 337, 181, 366, 198, - 103, 501, 349, 323, 343, 461, 495, 471, -99, 376, - 471, -96, -72, -94, 455, 447, 451, 484, 488, 439, - 455, 455, 495, 103, 430, 462, -73, -91, 383, 422, - 420, 479, 477, 14, 131, -69, -83, 131, 133, 432, - 434, -102, 34, 288, 475, 2, 379, 133, 213, 2, - 303, 282, 445, 440, 546, 7, 323, 552, 267, 11, - 11, 283, 379, 447, 327, 471, 377, 0, 221, 204, - 0, 288, 325, 223, 484, 488, 224, 217, 173, 173, - 14, 465, 173, 173, 173, 535, 173, 173, 173, 0, - 173, 458, 495, 173, 332, 0, 358, 9, 8, 496, - 0, 444, 443, 539, 538, 273, 272, 90, 90, 280, - 279, 280, 279, 11, 278, 277, 524, 96, 91, 91, - 377, 69, 287, 286, 525, 173, 90, 90, 173, 474, - 486, 490, 211, 536, 174, 381, 459, 91, 91, 368, - 341, 94, 449, 475, 200, 505, 14, 497, 201, 359, - 345, 206, 95, 343, 346, 206, 69, 173, 81, 82, - 69, 549, 97, 69, 173, 0, 69, 117, 98, 118, - 207, 117, 437, 118, 207, 173, 208, 285, 0, 41, - 119, 183, 182, 69, 119, 96, 135, 69, 0, 69, - 0, 0, 0, 81, 82, 35, 0, 81, 82, 0, - 81, 82, 516, 81, 82, 136, 0, 137, 69, 0, - 266, 265, 69, 35, 550, 548, 69, 469, 468, 96, - 81, 82, 69, 0, 81, 82, 81, 82, 520, 519, - 97, 0, 0, 42, 40, 117, 98, 118, 305, 306, - 37, 69, 117, 0, 118, 81, 82, 0, 119, 81, - 82, 36, 0, 81, 82, 119, 517, 515, 37, 81, - 82, 69, 305, 306, 97, 307, 308, 0, -313, 36, - 98, 310, 311, 271, 270, 0, 0, 0, 81, 82, - 312, 0, 0, 313, 69, 314, 0, 0, 0, 307, - 308, 310, 311, 0, 69, 0, 69, 0, 81, 82, - 312, 310, 311, 313, 0, 314, 0, 0, 105, 106, - 312, 310, 311, 313, 0, 314, 276, 275, 0, 0, - 312, 81, 82, 313, 0, 314, 271, 270, 276, 275, - 0, 81, 82, 81, 82, 107, 108, 110, 111, 0, - 0, 0, 0, 0, 0, 112, 113, 110, 111, 114, - 0, 115, 0, 0, 0, 112, 113, 110, 111, 114, - 19, 115, 0, 0, 0, 112, 113, 0, 0, 114, - 0, 115, 20, 19, 0, 110, 111, 0, 0, 21, - 0, 310, 311, 112, 113, 20, 0, 114, 0, 115, - 312, 0, 21, 313, 0, 314, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 522, 0, 0, 0, 25, - 0, 0, 0, 0, 0, 0, 22, 26, 23, 0, - 0, 0, 25, 0, 27, 0, 0, 0, 185, 22, - 26, 0, 0, 18, 0, 24, 0, 27, 186, 0, - 0, 0, 187, 0, 0, 0, 18, 0, 24, 110, - 111, 188, 0, 189, 0, 0, 0, 112, 113, 185, - 0, 114, 0, 115, 190, 0, 191, 94, 0, 186, - 0, 0, 0, 187, 192, 0, 0, 193, 95, 0, - 0, 0, 188, 194, 189, 0, 0, 339, 0, 195, - 0, 0, 0, 0, 0, 190, 0, 191, 94, 0, - 0, 0, 0, 0, 196, 192, 0, 0, 193, 95, - 0, 0, 0, 0, 194, 0, 0, 185, 0, 0, - 195, 0, 0, 0, 0, 0, 0, 186, 0, 0, - 0, 187, 0, 0, 0, 196, 0, 0, 0, 0, - 188, 0, 189, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 190, 0, 191, 94, 0, 0, 0, - 0, 0, 0, 192, 0, 0, 193, 95, 0, 0, - 0, 0, 194, 0, 0, 0, 0, 0, 195, 0, + 338, 174, 289, 485, 472, 472, -89, 480, -105, 380, + 43, 472, -79, -78, -100, 448, -97, 435, -102, 134, + 304, 326, 132, 104, 478, 375, 489, 372, 374, 456, + 377, 336, 199, 452, 423, 433, 440, 384, 421, 205, + 431, 456, 132, 365, 350, 344, 214, 476, -108, 456, + 324, 357, 462, 199, 367, 463, 363, 222, 472, 446, + 441, -75, -108, 182, 485, 448, -89, 588, 180, -75, + -97, 489, -100, 2, 289, 525, 380, 104, 224, 7, + 225, 582, 134, 304, 378, -102, 289, -105, -79, 472, + -65, 283, 328, 344, 268, 326, 2, 485, 174, 518, + 174, 174, 489, 333, 284, 218, 324, 372, 174, 572, + 174, 38, 91, 498, 91, 174, 0, 466, 174, 174, + 0, 0, 0, 92, 20, 92, 359, 91, 91, 346, + 475, 174, 459, 347, 445, 444, 576, 575, 92, 92, + 95, 174, 21, 174, 476, -78, 281, 280, 585, 39, + 509, 96, 491, 450, 12, 9, 8, 573, 175, 12, + 382, 499, 201, 212, 281, 280, 202, 279, 278, 281, + 280, 342, 174, 12, 274, 273, 45, 460, 528, 360, + 288, 287, 174, 487, 12, 0, 20, 207, 136, 97, + 12, 13, 16, 369, 41, 286, 13, 16, 207, 39, + 174, 586, 584, 0, 21, 40, 208, 137, 438, 138, + 13, 16, 174, 12, 0, 0, 0, 208, 0, 209, + 12, 13, 16, 12, 0, 524, 523, 13, 16, 520, + 46, 44, 12, 0, 98, 184, 183, 12, 0, 118, + 99, 119, 97, 118, 41, 119, 118, 97, 119, 0, + 13, 16, 120, 470, 469, 40, 120, 13, 16, 120, + 13, 16, 12, 306, 307, 267, 266, 12, 0, 13, + 16, 12, 0, 0, 13, 16, 174, 0, -319, 306, + 307, 12, 0, 521, 519, 0, 0, 98, -319, 0, + 308, 309, 98, 99, 106, 107, 106, 107, 99, 13, + 16, 21, 311, 312, 13, 16, 308, 309, 13, 16, + 12, 313, 12, 118, 314, 119, 315, 0, 13, 16, + 12, 108, 109, 108, 109, 12, 120, 311, 312, 267, + 266, 0, 12, 0, 0, 0, 313, 0, 0, 314, + 0, 315, 277, 276, 272, 271, 0, 13, 16, 13, + 16, 12, 277, 276, 0, 15, 0, 13, 16, 311, + 312, 0, 13, 16, 277, 276, 311, 312, 313, 13, + 16, 314, 0, 315, 0, 313, 12, 0, 314, 12, + 315, 14, 0, 272, 271, 111, 112, 0, 13, 16, + 0, 0, 0, 113, 114, 111, 112, 115, 0, 116, + 0, 0, 0, 113, 114, 0, 15, 115, 0, 116, + 0, 272, 271, 13, 16, 0, 13, 16, 26, 111, + 112, 0, 0, 0, 0, 0, 0, 113, 114, 0, + 27, 115, 14, 116, 0, 111, 112, 12, 0, 26, + 0, 311, 312, 113, 114, 0, 0, 115, 0, 116, + 313, 27, 0, 314, 0, 315, 0, 0, 12, 0, + 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, + 0, 0, 0, 0, 28, 30, 0, 0, 0, 0, + 0, 0, 31, 0, 526, 0, 0, 0, 15, 0, + 0, 25, 0, 14, 0, 28, 30, 186, 0, 0, + 0, 0, 0, 31, 0, 0, 0, 187, 0, 111, + 112, 188, 25, 0, 14, 0, 0, 113, 114, 0, + 189, 115, 190, 116, 0, 340, 0, 0, 0, 0, + 0, 0, 0, 191, 0, 192, 95, 0, 0, 69, + 70, 0, 0, 193, 0, 0, 194, 96, 0, 72, + 0, 0, 195, 0, 0, 0, 12, 0, 196, 0, + 73, 74, 0, 75, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 197, 81, 0, 0, 186, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, + 0, 188, 84, 13, 16, 0, 85, 0, 0, 0, + 189, 0, 190, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 191, 0, 192, 95, 0, 0, 0, + 0, 0, 0, 193, 0, 0, 194, 96, 0, 0, + 0, 0, 195, 0, 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 196, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 65, 66, 0, 0, 0, - 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, - 0, 0, 69, 0, 0, 0, 70, 71, 0, 72, - 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, - 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 81, - 82, 0, 84, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 77, 86, 67, 0, 0, 0, 0, - 0, 0, 0, 0, 64, 65, 66, 0, 0, 0, - 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, - 0, 0, 69, 0, 0, 0, 70, 71, 0, 72, - 0, 0, 0, 73, 0, 74, 75, 76, 0, 0, - 78, 0, 0, 0, 79, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 81, - 82, 0, 84, 0, 85, 0, 87, 0, 88, 0, - 0, 0, 0, 77, 86, 67, 0, 0, 0, 0, - 0, 0, 0, 0, -92, 0, 0, 0, 64, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, - 70, 71, 0, 72, 0, 0, 0, 73, 0, 74, - 75, 76, 0, 0, 78, 0, 0, 0, 79, 0, - 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 81, 82, 0, 84, 0, 85, 0, - 87, 0, 88, 0, 0, 0, 0, 77, 86, 67, - 0, 0, 0, 0, 0, 0, 0, 0, 64, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, - 70, 71, 0, 72, 0, 0, 0, 73, 0, 74, - 75, 76, 0, 0, 78, 0, 0, 0, 79, 0, - 80, 0, 0, 503, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 81, 82, 0, 84, 0, 85, 0, - 87, 0, 88, 0, 0, 0, 0, 77, 86, 67, - 0, 0, 0, 0, 0, 0, 0, 0, 64, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, - 70, 71, 0, 72, 0, 0, 0, 73, 0, 74, - 75, 76, 0, 0, 78, 0, 0, 0, 79, 0, - 80, 0, 0, 500, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 81, 82, 0, 84, 0, 85, 0, - 87, 0, 88, 0, 0, 0, 0, 77, 86, 67, - 0, 0, 0, 0, 0, 0, 0, 0, 64, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 68, - 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, - 70, 71, 0, 72, 0, 0, 0, 73, 0, 74, - 75, 76, 0, 0, 78, 0, 0, 0, 79, 0, - 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 83, 81, 82, 0, 84, 0, 85, 0, - 87, 302, 88, 0, 0, 0, 0, 77, 86, 67, - 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, - 143, 0, 0, 145, 147, 148, 0, 0, 149, 0, - 150, 0, 0, 0, 152, 153, 154, 0, 0, 0, - 0, 0, 0, 69, 155, 156, 157, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 158, 0, 0, + 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, + 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, + 81, 0, 0, 0, 82, 0, 83, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, -98, 0, 0, 0, 68, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, + 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, + 88, 0, 89, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, + 70, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, + 73, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 13, 16, 0, 85, 0, 86, 0, + 88, 303, 89, 0, 0, 0, 0, 80, 87, 71, + 0, 0, 0, 0, 0, 0, 0, 0, 496, 0, + 0, 68, 69, 70, 0, 0, 0, 0, 0, 0, + 0, 0, 72, 0, 0, 0, 0, 0, 0, 12, + 0, 0, 0, 73, 74, 0, 75, 0, 0, 0, + 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, + 0, 82, 0, 83, 0, 0, 497, 0, 0, 0, + 0, 0, 0, 0, 0, 84, 13, 16, 0, 85, + 0, 86, 0, 88, 0, 89, 0, 0, 0, 0, + 80, 87, 71, 0, 0, 0, 0, 0, 0, 0, + 0, 504, 0, 0, 68, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 73, 74, 0, 75, + 0, 0, 0, 76, 0, 77, 78, 79, 0, 0, + 81, 0, 0, 0, 82, 0, 83, 0, 0, 505, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 13, + 16, 0, 85, 0, 86, 0, 88, 0, 89, 0, + 0, 0, 0, 80, 87, 71, 0, 0, 0, 0, + 0, 0, 0, 0, 496, 0, 0, 68, 69, 70, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 73, + 74, 0, 75, 0, 0, 0, 76, 0, 77, 78, + 79, 0, 0, 81, 0, 0, 0, 82, 0, 83, + 0, 0, 502, 0, 0, 0, 0, 0, 0, 0, + 0, 84, 13, 16, 0, 85, 0, 86, 0, 88, + 0, 89, 0, 0, 0, 0, 80, 87, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, + 68, 69, 70, 0, 0, 0, 0, 0, 0, 0, + 0, 72, 0, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 73, 74, 0, 75, 0, 0, 0, 76, + 0, 77, 78, 79, 0, 0, 81, 0, 0, 0, + 82, 0, 83, 0, 0, 507, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 13, 16, 0, 85, 0, + 86, 0, 88, 0, 89, 0, 0, 0, 0, 80, + 87, 71, 0, 0, 0, 0, 0, 0, 0, 0, + 496, 0, 0, 68, 69, 70, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 73, 74, 0, 75, 0, + 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, + 0, 0, 0, 82, 0, 83, 0, 0, 497, 0, + 0, 15, 0, 0, 0, 0, 0, 84, 13, 16, + 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, + 0, 0, 80, 87, 71, 0, 0, 14, 0, 0, + 0, 0, 0, 68, 69, 70, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, + 0, 12, 251, 0, 0, 535, 536, 0, 75, 0, + 0, 0, 76, 0, 77, 78, 79, 0, 0, 81, + 0, 0, 0, 82, 0, 83, 0, 0, 0, 0, + 0, 0, 0, 255, 0, 0, 0, 84, 13, 16, + 0, 85, 0, 86, 0, 88, 0, 89, 0, 0, + 0, 0, 80, 87, 71, 0, 246, 0, 537, 0, + 0, 0, 0, 142, 143, 144, 0, 0, 146, 148, + 149, 0, 0, 150, 0, 151, 0, 0, 0, 153, + 154, 155, 0, 0, 0, 0, 0, 0, 12, 156, + 157, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, + 0, 0, 0, 0, 0, 13, 16, 163, 164, 165, + 0, 167, 168, 169, 170, 171, 172, 0, 0, 160, + 166, 152, 145, 147, 161, 0, 0, 0, 0, 0, + 142, 143, 144, 0, 0, 146, 148, 149, 0, 0, + 150, 0, 151, 0, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 425, 156, 157, 158, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, + 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, + 0, 430, 427, 429, 163, 164, 165, 0, 167, 168, + 169, 170, 171, 172, 0, 0, 160, 166, 152, 145, + 147, 161, 0, 0, 0, 0, 0, 142, 143, 144, + 0, 0, 146, 148, 149, 0, 0, 150, 0, 151, + 0, 0, 0, 153, 154, 155, 0, 0, 0, 0, + 0, 0, 425, 156, 157, 158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, + 426, 0, 0, 0, 0, 0, 0, 0, 428, 0, + 0, 0, 162, 0, 0, 0, 0, 0, 430, 427, + 429, 163, 164, 165, 0, 167, 168, 169, 170, 171, + 172, 0, 0, 160, 166, 152, 145, 147, 161, 0, + 0, 0, 0, 0, 244, 0, 0, 0, 0, 245, + 0, 68, 69, 70, 247, 0, 0, 0, 0, 0, + 0, 248, 72, 0, 0, 0, 0, 0, 0, 250, + 251, 0, 0, 252, 74, 0, 75, 0, 0, 0, + 76, 0, 77, 78, 79, 0, 0, 81, 0, 0, + 0, 82, 0, 83, 0, 0, 0, 0, 0, 254, + 0, 255, 0, 0, 0, 84, 253, 256, 257, 85, + 258, 86, 259, 88, 31, 89, 260, 261, 0, 0, + 80, 87, 71, 25, 246, 0, 0, 0, 0, 0, + 0, 244, 0, 0, 0, 0, 245, 0, 68, 69, + 70, 247, 0, 0, 0, 0, 0, 0, 248, 249, + 0, 0, 0, 0, 0, 0, 250, 251, 0, 0, + 252, 74, 0, 75, 0, 0, 0, 76, 0, 77, + 78, 79, 0, 0, 81, 0, 0, 0, 82, 0, + 83, 0, 0, 0, 0, 0, 254, 0, 255, 0, + 0, 0, 84, 253, 256, 257, 85, 258, 86, 259, + 88, 31, 89, 260, 261, 0, 0, 80, 87, 71, + 25, 246, 0, 0, 0, 0, 0, 0, 541, 143, + 144, 0, 0, 543, 148, 545, 69, 70, 546, 0, + 151, 0, 0, 0, 153, 548, 549, 0, 0, 0, + 0, 0, 0, 550, 551, 157, 158, 252, 74, 0, + 75, 0, 0, 0, 76, 0, 77, 552, 79, 0, + 0, 554, 0, 0, 0, 82, 0, 83, 0, 0, + 0, 0, 0, 556, 0, 255, 0, 0, 0, 558, + 555, 557, 559, 560, 561, 86, 563, 564, 565, 566, + 567, 568, 0, 0, 553, 562, 547, 542, 544, 161, + 0, 0, 0, 0, 0, 393, 143, 144, 0, 0, + 395, 148, 397, 69, 70, 398, 0, 151, 0, 0, + 0, 153, 400, 401, 0, 0, 0, 0, 0, 0, + 402, 403, 157, 158, 252, 74, 0, 75, 0, 0, + 0, 76, 0, 77, 404, 79, 0, 0, 406, 0, + 0, 0, 82, 0, 83, 0, -244, 0, 0, 0, + 408, 0, 255, 0, 0, 0, 410, 407, 409, 411, + 412, 413, 86, 415, 416, 417, 418, 419, 420, 0, + 0, 405, 414, 399, 394, 396, 161, 0, 0, 0, + 0, 0, + + 334, 477, 282, 482, 270, 503, 467, 464, 275, 42, + 577, 55, 506, 479, 481, 217, 516, 522, 185, 23, + 468, 217, 540, 583, 10, 486, 488, 492, 490, 493, + 508, 270, 434, 385, 422, 383, 381, 366, 379, 368, + 270, 275, 468, 275, 334, 173, 282, 217, 242, 223, + 179, 468, 176, 334, 285, 371, 221, 343, 181, 341, + 211, 282, 465, 198, 352, 204, 457, 339, 370, 449, + 447, 206, 432, 442, 424, 334, 0, 93, 179, 501, + 0, 577, 318, 500, 213, 221, 93, 0, 471, 93, + 93, 93, 130, 483, 316, 317, 93, 461, 93, 93, + 215, 319, 93, 93, 320, 514, 93, 93, 129, 17, + 93, 0, 110, 94, 93, 93, 484, 102, 93, 242, + 93, 103, 101, 203, 337, 93, 11, 484, 93, 93, + 93, 513, 483, 93, 574, 515, 298, 93, 587, 334, + 0, 302, 200, 93, 93, 105, 334, 352, 125, 126, + 93, 11, 215, 269, 93, 93, 373, 510, 93, 124, + 512, 93, 436, 511, 179, 437, 93, 0, 242, 93, + 439, 127, 93, 123, 0, 436, 0, 128, 437, 93, + 93, 483, 215, 93, 93, 139, 436, 122, 335, 437, + 93, 93, 334, 141, 121, 362, 133, 376, 93, 93, + 100, 135, 93, 0, 117, 330, 361, 330, 131, 330, + 302, 93, 302, 93, 302, 330, 302, 0, 302, 0, + 302, 0, 0, 93, 327, 93, 345, 329, 302, 332, + 302, 351, 310, 0, 0, 0, 0, 349, 93, 0, + 348, 364, 93, 302, 93, 321, 484, 302, 93, 322, + 0, 93, 93, 302, 330, 323, 302, 302, 139, 302, + 35, 305, 0, 0, 325, 527, 141, 210, 35, 0, + 24, 37, 11, 0, 0, 0, 358, 0, 24, 37, + 11, 532, 529, 531, 533, 530, 534, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 161, 0, 0, 0, 0, 0, 0, - 81, 82, 162, 163, 164, 0, 166, 167, 168, 169, - 170, 171, 0, 0, 159, 165, 151, 144, 146, 160, - 0, 0, 0, 0, 0, 141, 142, 143, 0, 0, - 145, 147, 148, 0, 0, 149, 0, 150, 0, 0, - 0, 152, 153, 154, 0, 0, 0, 0, 0, 0, - 424, 155, 156, 157, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 158, 0, 0, 0, 425, 0, + 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 161, 0, 0, 0, 0, 0, 429, 426, 428, 162, - 163, 164, 0, 166, 167, 168, 169, 170, 171, 0, - 0, 159, 165, 151, 144, 146, 160, 0, 0, 0, - 0, 0, 141, 142, 143, 0, 0, 145, 147, 148, - 0, 0, 149, 0, 150, 0, 0, 0, 152, 153, - 154, 0, 0, 0, 0, 0, 0, 424, 155, 156, - 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 158, 0, 0, 0, 425, 0, 0, 0, 0, - 0, 0, 0, 427, 0, 0, 0, 161, 0, 0, - 0, 0, 0, 429, 426, 428, 162, 163, 164, 0, - 166, 167, 168, 169, 170, 171, 0, 0, 159, 165, - 151, 144, 146, 160, 0, 0, 0, 0, 0, 243, - 0, 0, 0, 0, 244, 0, 64, 65, 66, 246, - 0, 0, 0, 0, 0, 0, 247, 68, 0, 0, - 0, 0, 0, 0, 249, 250, 0, 0, 251, 71, - 0, 72, 0, 0, 0, 73, 0, 74, 75, 76, - 0, 0, 78, 0, 0, 0, 79, 0, 80, 0, - 0, 0, 0, 0, 253, 0, 254, 0, 0, 0, - 83, 252, 255, 256, 84, 257, 85, 258, 87, 27, - 88, 259, 260, 0, 0, 77, 86, 67, 18, 245, - 0, 0, 0, 0, 0, 0, 243, 0, 0, 0, - 0, 244, 0, 64, 65, 66, 246, 0, 0, 0, - 0, 0, 0, 247, 248, 0, 0, 0, 0, 0, - 0, 249, 250, 0, 0, 251, 71, 0, 72, 0, - 0, 0, 73, 0, 74, 75, 76, 0, 0, 78, - 0, 0, 0, 79, 0, 80, 0, 0, 0, 0, - 0, 253, 0, 254, 0, 0, 0, 83, 252, 255, - 256, 84, 257, 85, 258, 87, 27, 88, 259, 260, - 0, 0, 77, 86, 67, 18, 245, 0, 0, 0, - 0, 0, 0, 243, 0, 0, 0, 0, 244, 0, - 64, 65, 66, 246, 0, 0, 0, 0, 0, 0, - 247, 68, 0, 0, 0, 0, 0, 0, 527, 250, - 0, 0, 251, 528, 0, 72, 0, 0, 0, 73, - 0, 74, 75, 76, 0, 0, 78, 0, 0, 0, - 79, 0, 80, 0, 0, 0, 0, 0, 253, 0, - 254, 0, 0, 0, 83, 252, 255, 256, 84, 257, - 85, 258, 87, 27, 88, 259, 260, 0, 0, 77, - 86, 67, 18, 245, 0, 529, 0, 0, 0, 0, - 392, 142, 143, 0, 0, 394, 147, 396, 65, 66, - 397, 0, 150, 0, 0, 0, 152, 399, 400, 0, - 0, 0, 0, 0, 0, 401, 402, 156, 157, 251, - 71, 0, 72, 0, 0, 0, 73, 0, 74, 403, - 76, 0, 0, 405, 0, 0, 0, 79, 0, 80, - 0, -238, 0, 0, 0, 407, 0, 254, 0, 0, - 0, 409, 406, 408, 410, 411, 412, 85, 414, 415, - 416, 417, 418, 419, 0, 0, 404, 413, 398, 393, - 395, 160, 0, 0, 0, 0, 0, - - 463, 180, 197, 480, 476, 481, 504, 460, 478, 466, - 464, 284, 210, 184, 532, 526, 370, 540, 512, 281, - 10, 274, 12, 241, 537, 547, 216, 222, 499, 269, - 220, 502, 470, 498, 491, 333, 456, 485, 489, 487, - 518, 470, 203, 467, 51, 541, 38, 0, 205, 340, - 382, 380, 378, 351, 431, 421, 369, 367, 384, 216, - 281, 0, 274, 467, 269, 333, 433, 441, 92, 342, - 338, 93, 446, 448, 365, 423, 178, 172, 333, 175, - 333, 0, 541, 0, 333, 0, 92, 333, 351, 241, - 121, 241, 0, 220, 0, 92, 0, 435, 178, 120, - 436, 92, 92, 214, 138, 212, 92, 316, 92, 0, - 534, 0, 122, 140, 92, 92, 92, 92, 132, 317, - 318, 0, 336, 129, 363, 92, 134, 92, 334, 0, - 319, 361, 127, 92, 92, 483, 214, 92, 92, 101, - 0, 297, 92, 126, 551, 102, 301, 92, 92, 507, - 508, 92, 360, 482, 92, 92, 506, 509, 178, 92, - 92, 510, 511, 92, 92, 438, 99, 92, 116, 372, - 92, 375, 92, 130, 92, 92, 435, 123, 268, 436, - 125, 92, 0, 92, 199, 92, 124, 482, 315, 92, - 202, 483, 92, 92, 0, 92, 0, 92, 329, 109, - 104, 128, 301, 301, 0, 92, 92, 92, 329, 100, - 301, 301, 320, 301, 347, 0, 0, 92, 329, 0, - 348, 344, 301, 301, 321, 16, 33, 17, 92, 92, - 350, 0, 0, 301, 301, 0, 309, 92, 92, 326, - 331, 92, 301, 301, 322, 523, 301, 329, 329, 0, - 304, 324, 301, 301, 16, 33, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 357, - 328, 0, 0, 0, 138, 0, 0, 0, 0, 0, - 0, 0, 0, 140, 209, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 569, 0, 0, 0, 0, 0, + 493, 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, 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, 0, 0}; const int JavaScriptGrammar::action_check [] = { - 2, 61, 60, 36, 33, 29, 33, 60, 8, 17, - 78, 29, 29, 1, 61, 8, 60, 60, 31, 2, - 1, 8, 7, 48, 2, 55, 8, 33, 7, 55, - 33, 7, 7, 7, 5, 36, 33, 36, 36, 60, - 5, 5, 8, 1, 7, 7, 7, 7, 16, 8, - 7, 60, 36, 33, 48, 7, 7, 48, 78, 55, - 55, 7, 66, 36, 20, 88, 36, 78, 60, 88, - 1, 76, 7, 7, 17, 65, 48, 0, 55, 29, - 29, 36, 36, 36, 8, 33, 7, -1, 8, 7, - -1, 36, 78, 60, 36, 36, 33, 36, 8, 8, - 33, 7, 8, 8, 8, 8, 8, 8, 8, -1, - 8, 10, 8, 8, 61, -1, 8, 61, 62, 8, - -1, 61, 62, 61, 62, 61, 62, 40, 40, 61, - 62, 61, 62, 29, 61, 62, 7, 12, 51, 51, - 7, 29, 61, 62, 15, 8, 40, 40, 8, 6, - 60, 60, 56, 56, 56, 60, 55, 51, 51, 60, - 60, 42, 60, 20, 50, 60, 33, 56, 54, 61, - 50, 15, 53, 2, 54, 15, 29, 8, 66, 67, - 29, 8, 57, 29, 8, -1, 29, 25, 63, 27, - 34, 25, 36, 27, 34, 8, 36, 60, -1, 7, - 38, 61, 62, 29, 38, 12, 15, 29, -1, 29, - -1, -1, -1, 66, 67, 29, -1, 66, 67, -1, - 66, 67, 7, 66, 67, 34, -1, 36, 29, -1, - 61, 62, 29, 29, 61, 62, 29, 61, 62, 12, - 66, 67, 29, -1, 66, 67, 66, 67, 61, 62, - 57, -1, -1, 61, 62, 25, 63, 27, 18, 19, - 74, 29, 25, -1, 27, 66, 67, -1, 38, 66, - 67, 85, -1, 66, 67, 38, 61, 62, 74, 66, - 67, 29, 18, 19, 57, 45, 46, -1, 36, 85, - 63, 23, 24, 61, 62, -1, -1, -1, 66, 67, - 32, -1, -1, 35, 29, 37, -1, -1, -1, 45, - 46, 23, 24, -1, 29, -1, 29, -1, 66, 67, - 32, 23, 24, 35, -1, 37, -1, -1, 18, 19, - 32, 23, 24, 35, -1, 37, 61, 62, -1, -1, - 32, 66, 67, 35, -1, 37, 61, 62, 61, 62, - -1, 66, 67, 66, 67, 45, 46, 23, 24, -1, - -1, -1, -1, -1, -1, 31, 32, 23, 24, 35, - -1, 37, -1, -1, -1, 31, 32, 23, 24, 35, - 10, 37, -1, -1, -1, 31, 32, -1, -1, 35, - -1, 37, 22, 10, -1, 23, 24, -1, -1, 29, - -1, 23, 24, 31, 32, 22, -1, 35, -1, 37, - 32, -1, 29, 35, -1, 37, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 55, -1, -1, -1, 59, - -1, -1, -1, -1, -1, -1, 66, 67, 55, -1, - -1, -1, 59, -1, 74, -1, -1, -1, 3, 66, - 67, -1, -1, 83, -1, 85, -1, 74, 13, -1, - -1, -1, 17, -1, -1, -1, 83, -1, 85, 23, - 24, 26, -1, 28, -1, -1, -1, 31, 32, 3, - -1, 35, -1, 37, 39, -1, 41, 42, -1, 13, - -1, -1, -1, 17, 49, -1, -1, 52, 53, -1, - -1, -1, 26, 58, 28, -1, -1, 31, -1, 64, - -1, -1, -1, -1, -1, 39, -1, 41, 42, -1, - -1, -1, -1, -1, 79, 49, -1, -1, 52, 53, - -1, -1, -1, -1, 58, -1, -1, 3, -1, -1, - 64, -1, -1, -1, -1, -1, -1, 13, -1, -1, - -1, 17, -1, -1, -1, 79, -1, -1, -1, -1, - 26, -1, 28, -1, -1, -1, -1, -1, -1, -1, + 60, 8, 36, 36, 33, 33, 7, 60, 7, 36, + 29, 33, 7, 7, 7, 36, 7, 55, 7, 78, + 1, 78, 48, 1, 36, 33, 36, 36, 60, 5, + 55, 61, 2, 33, 8, 55, 60, 16, 7, 7, + 7, 5, 48, 60, 7, 2, 60, 20, 7, 5, + 48, 17, 55, 2, 31, 7, 61, 8, 33, 7, + 7, 7, 7, 60, 36, 36, 7, 0, 8, 7, + 7, 36, 7, 88, 36, 29, 36, 1, 60, 65, + 33, 17, 78, 1, 7, 7, 36, 7, 7, 33, + 33, 76, 8, 2, 55, 78, 88, 36, 8, 29, + 8, 8, 36, 61, 36, 36, 48, 36, 8, 8, + 8, 66, 40, 8, 40, 8, -1, 7, 8, 8, + -1, -1, -1, 51, 15, 51, 8, 40, 40, 50, + 6, 8, 10, 54, 61, 62, 61, 62, 51, 51, + 42, 8, 33, 8, 20, 7, 61, 62, 8, 29, + 60, 53, 60, 60, 29, 61, 62, 56, 56, 29, + 60, 56, 50, 56, 61, 62, 54, 61, 62, 61, + 62, 60, 8, 29, 61, 62, 7, 55, 7, 61, + 61, 62, 8, 60, 29, -1, 15, 15, 15, 12, + 29, 66, 67, 60, 74, 60, 66, 67, 15, 29, + 8, 61, 62, -1, 33, 85, 34, 34, 36, 36, + 66, 67, 8, 29, -1, -1, -1, 34, -1, 36, + 29, 66, 67, 29, -1, 61, 62, 66, 67, 7, + 61, 62, 29, -1, 57, 61, 62, 29, -1, 25, + 63, 27, 12, 25, 74, 27, 25, 12, 27, -1, + 66, 67, 38, 61, 62, 85, 38, 66, 67, 38, + 66, 67, 29, 18, 19, 61, 62, 29, -1, 66, + 67, 29, -1, -1, 66, 67, 8, -1, 36, 18, + 19, 29, -1, 61, 62, -1, -1, 57, 36, -1, + 45, 46, 57, 63, 18, 19, 18, 19, 63, 66, + 67, 33, 23, 24, 66, 67, 45, 46, 66, 67, + 29, 32, 29, 25, 35, 27, 37, -1, 66, 67, + 29, 45, 46, 45, 46, 29, 38, 23, 24, 61, + 62, -1, 29, -1, -1, -1, 32, -1, -1, 35, + -1, 37, 61, 62, 61, 62, -1, 66, 67, 66, + 67, 29, 61, 62, -1, 59, -1, 66, 67, 23, + 24, -1, 66, 67, 61, 62, 23, 24, 32, 66, + 67, 35, -1, 37, -1, 32, 29, -1, 35, 29, + 37, 85, -1, 61, 62, 23, 24, -1, 66, 67, + -1, -1, -1, 31, 32, 23, 24, 35, -1, 37, + -1, -1, -1, 31, 32, -1, 59, 35, -1, 37, + -1, 61, 62, 66, 67, -1, 66, 67, 10, 23, + 24, -1, -1, -1, -1, -1, -1, 31, 32, -1, + 22, 35, 85, 37, -1, 23, 24, 29, -1, 10, + -1, 23, 24, 31, 32, -1, -1, 35, -1, 37, + 32, 22, -1, 35, -1, 37, -1, -1, 29, -1, + -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, 66, 67, -1, -1, -1, -1, + -1, -1, 74, -1, 55, -1, -1, -1, 59, -1, + -1, 83, -1, 85, -1, 66, 67, 3, -1, -1, + -1, -1, -1, 74, -1, -1, -1, 13, -1, 23, + 24, 17, 83, -1, 85, -1, -1, 31, 32, -1, + 26, 35, 28, 37, -1, 31, -1, -1, -1, -1, + -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, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, + -1, 17, 65, 66, 67, -1, 69, -1, -1, -1, + 26, -1, 28, -1, -1, -1, -1, 80, 81, 82, -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, @@ -611,122 +669,161 @@ const int JavaScriptGrammar::action_check [] = { -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, 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, 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, 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, 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, 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, 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, -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, -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, 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, 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, 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, + 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, 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, -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, 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, 4, -1, -1, -1, -1, 9, -1, - 11, 12, 13, 14, -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, 84, -1, 86, -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, - -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, - 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, + 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, + 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, 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, + -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, + 84, 85, -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, 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, + -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, -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, + -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, -1, -1, -1, + -1, -1, - 77, 25, 25, 63, 94, 63, 16, 89, 19, 77, - 16, 16, 16, 59, 10, 14, 19, 19, 19, 14, - 5, 19, 6, 14, 6, 25, 19, 19, 25, 19, - 19, 25, 63, 21, 14, 16, 92, 16, 16, 14, - 16, 63, 25, 16, 16, 19, 15, -1, 25, 16, - 14, 16, 14, 19, 25, 25, 14, 16, 14, 19, - 14, -1, 19, 16, 19, 16, 14, 14, 36, 14, - 14, 39, 14, 16, 14, 27, 25, 16, 16, 25, - 16, -1, 19, -1, 16, -1, 36, 16, 19, 14, - 40, 14, -1, 19, -1, 36, -1, 30, 25, 40, - 33, 36, 36, 38, 19, 32, 36, 41, 36, -1, - 6, -1, 40, 28, 36, 36, 36, 36, 48, 41, - 41, -1, 60, 42, 60, 36, 46, 36, 60, -1, - 41, 60, 41, 36, 36, 38, 38, 36, 36, 38, - -1, 36, 36, 41, 81, 39, 41, 36, 36, 38, - 38, 36, 83, 38, 36, 36, 38, 38, 25, 36, - 36, 38, 38, 36, 36, 32, 38, 36, 41, 95, - 36, 96, 36, 42, 36, 36, 30, 41, 101, 33, - 41, 36, -1, 36, 50, 36, 41, 38, 41, 36, - 52, 38, 36, 36, -1, 36, -1, 36, 36, 42, - 44, 42, 41, 41, -1, 36, 36, 36, 36, 38, - 41, 41, 43, 41, 53, -1, -1, 36, 36, -1, - 58, 51, 41, 41, 43, 17, 18, 19, 36, 36, - 58, -1, -1, 41, 41, -1, 43, 36, 36, 47, - 58, 36, 41, 41, 43, 8, 41, 36, 36, -1, - 45, 49, 41, 41, 17, 18, 19, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, - 58, -1, -1, -1, 19, -1, -1, -1, -1, -1, - -1, -1, -1, 28, 29, -1, -1, -1, -1, -1, + 14, 93, 66, 15, 23, 29, 76, 76, 23, 20, + 23, 14, 29, 23, 15, 23, 23, 14, 62, 23, + 14, 23, 10, 29, 5, 14, 66, 66, 14, 29, + 14, 23, 66, 66, 29, 66, 14, 66, 66, 14, + 23, 23, 14, 23, 14, 14, 66, 23, 66, 23, + 29, 14, 29, 14, 14, 23, 23, 66, 29, 14, + 14, 66, 14, 29, 23, 29, 91, 66, 66, 14, + 66, 29, 29, 66, 30, 14, -1, 39, 29, 25, + -1, 23, 44, 29, 35, 23, 39, -1, 15, 39, + 39, 39, 45, 41, 44, 44, 39, 88, 39, 39, + 41, 44, 39, 39, 44, 41, 39, 39, 45, 6, + 39, -1, 45, 42, 39, 39, 41, 41, 39, 66, + 39, 42, 41, 55, 63, 39, 23, 41, 39, 39, + 39, 41, 41, 39, 6, 41, 39, 39, 80, 14, + -1, 44, 53, 39, 39, 47, 14, 23, 44, 44, + 39, 23, 41, 100, 39, 39, 94, 41, 39, 44, + 41, 39, 33, 41, 29, 36, 39, -1, 66, 39, + 35, 44, 39, 43, -1, 33, -1, 44, 36, 39, + 39, 41, 41, 39, 39, 23, 33, 43, 63, 36, + 39, 39, 14, 31, 43, 63, 51, 95, 39, 39, + 41, 49, 39, -1, 44, 39, 82, 39, 45, 39, + 44, 39, 44, 39, 44, 39, 44, -1, 44, -1, + 44, -1, -1, 39, 50, 39, 54, 61, 44, 61, + 44, 61, 46, -1, -1, -1, -1, 61, 39, -1, + 56, 63, 39, 44, 39, 46, 41, 44, 39, 46, + -1, 39, 39, 44, 39, 46, 44, 44, 23, 44, + 11, 48, -1, -1, 52, 8, 31, 32, 11, -1, + 21, 22, 23, -1, -1, -1, 61, -1, 21, 22, + 23, 14, 15, 16, 17, 18, 19, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, + 29, -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, -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, -1, -1}; diff --git a/src/declarative/qml/parser/javascriptgrammar_p.h b/src/declarative/qml/parser/javascriptgrammar_p.h index 70c9766..830f533 100644 --- a/src/declarative/qml/parser/javascriptgrammar_p.h +++ b/src/declarative/qml/parser/javascriptgrammar_p.h @@ -150,15 +150,15 @@ public: T_XOR = 78, T_XOR_EQ = 79, - ACCEPT_STATE = 552, - RULE_COUNT = 317, - STATE_COUNT = 553, + ACCEPT_STATE = 588, + RULE_COUNT = 323, + STATE_COUNT = 589, TERMINAL_COUNT = 91, - NON_TERMINAL_COUNT = 103, + NON_TERMINAL_COUNT = 102, - GOTO_INDEX_OFFSET = 553, - GOTO_INFO_OFFSET = 1717, - GOTO_CHECK_OFFSET = 1717 + GOTO_INDEX_OFFSET = 589, + GOTO_INFO_OFFSET = 2092, + GOTO_CHECK_OFFSET = 2092 }; static const char *const spell []; diff --git a/src/declarative/qml/parser/javascriptlexer.cpp b/src/declarative/qml/parser/javascriptlexer.cpp index c0a4b63..7455b87 100644 --- a/src/declarative/qml/parser/javascriptlexer.cpp +++ b/src/declarative/qml/parser/javascriptlexer.cpp @@ -44,13 +44,6 @@ #endif #include "javascriptengine_p.h" - - - - - - - #include "javascriptlexer_p.h" #include "javascriptgrammar_p.h" @@ -73,10 +66,12 @@ extern double qstrtod(const char *s00, char const **se, bool *ok); while (0) namespace JavaScript { -extern qjsreal integerFromString(const char *buf, int size, int radix); +extern double integerFromString(const char *buf, int size, int radix); } -JavaScript::Lexer::Lexer(JavaScriptEnginePrivate *eng) +using namespace JavaScript; + +Lexer::Lexer(Engine *eng) : driver(eng), yylineno(0), done(false), @@ -101,6 +96,7 @@ JavaScript::Lexer::Lexer(JavaScriptEnginePrivate *eng) parenthesesCount(0), prohibitAutomaticSemicolon(false) { + driver->setLexer(this); // allocate space for read buffers buffer8 = new char[size8]; buffer16 = new QChar[size16]; @@ -109,13 +105,13 @@ JavaScript::Lexer::Lexer(JavaScriptEnginePrivate *eng) } -JavaScript::Lexer::~Lexer() +Lexer::~Lexer() { delete [] buffer8; delete [] buffer16; } -void JavaScript::Lexer::setCode(const QString &c, int lineno) +void Lexer::setCode(const QString &c, int lineno) { errmsg = QString(); yylineno = lineno; @@ -135,7 +131,7 @@ void JavaScript::Lexer::setCode(const QString &c, int lineno) next3 = (length > 3) ? code[3].unicode() : 0; } -void JavaScript::Lexer::shift(uint p) +void Lexer::shift(uint p) { while (p--) { ++pos; @@ -147,13 +143,13 @@ void JavaScript::Lexer::shift(uint p) } } -void JavaScript::Lexer::setDone(State s) +void Lexer::setDone(State s) { state = s; done = true; } -int JavaScript::Lexer::findReservedWord(const QChar *c, int size) const +int Lexer::findReservedWord(const QChar *c, int size) const { switch (size) { case 2: { @@ -454,7 +450,7 @@ int JavaScript::Lexer::findReservedWord(const QChar *c, int size) const return -1; } -int JavaScript::Lexer::lex() +int Lexer::lex() { int token = 0; state = Start; @@ -772,10 +768,10 @@ int JavaScript::Lexer::lex() if (state == Number) { dval = qstrtod(buffer8, 0, 0); } else if (state == Hex) { // scan hex numbers - dval = JavaScript::integerFromString(buffer8, pos8, 16); + dval = integerFromString(buffer8, pos8, 16); state = Number; } else if (state == Octal) { // scan octal number - dval = JavaScript::integerFromString(buffer8, pos8, 8); + dval = integerFromString(buffer8, pos8, 8); state = Number; } @@ -843,18 +839,18 @@ int JavaScript::Lexer::lex() } } -bool JavaScript::Lexer::isWhiteSpace() const +bool Lexer::isWhiteSpace() const { return (current == ' ' || current == '\t' || current == 0x0b || current == 0x0c); } -bool JavaScript::Lexer::isLineTerminator() const +bool Lexer::isLineTerminator() const { return (current == '\n' || current == '\r'); } -bool JavaScript::Lexer::isIdentLetter(ushort c) +bool Lexer::isIdentLetter(ushort c) { /* TODO: allow other legitimate unicode chars */ return ((c >= 'a' && c <= 'z') @@ -863,24 +859,24 @@ bool JavaScript::Lexer::isIdentLetter(ushort c) || c == '_'); } -bool JavaScript::Lexer::isDecimalDigit(ushort c) +bool Lexer::isDecimalDigit(ushort c) { return (c >= '0' && c <= '9'); } -bool JavaScript::Lexer::isHexDigit(ushort c) const +bool Lexer::isHexDigit(ushort c) const { return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } -bool JavaScript::Lexer::isOctalDigit(ushort c) const +bool Lexer::isOctalDigit(ushort c) const { return (c >= '0' && c <= '7'); } -int JavaScript::Lexer::matchPunctuator(ushort c1, ushort c2, +int Lexer::matchPunctuator(ushort c1, ushort c2, ushort c3, ushort c4) { if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { @@ -987,7 +983,7 @@ int JavaScript::Lexer::matchPunctuator(ushort c1, ushort c2, } } -ushort JavaScript::Lexer::singleEscape(ushort c) const +ushort Lexer::singleEscape(ushort c) const { switch(c) { case 'b': @@ -1013,13 +1009,13 @@ ushort JavaScript::Lexer::singleEscape(ushort c) const } } -ushort JavaScript::Lexer::convertOctal(ushort c1, ushort c2, +ushort Lexer::convertOctal(ushort c1, ushort c2, ushort c3) const { return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); } -unsigned char JavaScript::Lexer::convertHex(ushort c) +unsigned char Lexer::convertHex(ushort c) { if (c >= '0' && c <= '9') return (c - '0'); @@ -1029,19 +1025,19 @@ unsigned char JavaScript::Lexer::convertHex(ushort c) return (c - 'A' + 10); } -unsigned char JavaScript::Lexer::convertHex(ushort c1, ushort c2) +unsigned char Lexer::convertHex(ushort c1, ushort c2) { return ((convertHex(c1) << 4) + convertHex(c2)); } -QChar JavaScript::Lexer::convertUnicode(ushort c1, ushort c2, +QChar Lexer::convertUnicode(ushort c1, ushort c2, ushort c3, ushort c4) { return QChar((convertHex(c3) << 4) + convertHex(c4), (convertHex(c1) << 4) + convertHex(c2)); } -void JavaScript::Lexer::record8(ushort c) +void Lexer::record8(ushort c) { Q_ASSERT(c <= 0xff); @@ -1057,7 +1053,7 @@ void JavaScript::Lexer::record8(ushort c) buffer8[pos8++] = (char) c; } -void JavaScript::Lexer::record16(QChar c) +void Lexer::record16(QChar c) { // enlarge buffer if full if (pos16 >= size16 - 1) { @@ -1071,14 +1067,14 @@ void JavaScript::Lexer::record16(QChar c) buffer16[pos16++] = c; } -void JavaScript::Lexer::recordStartPos() +void Lexer::recordStartPos() { startpos = pos; startlineno = yylineno; startcolumn = yycolumn; } -bool JavaScript::Lexer::scanRegExp(RegExpBodyPrefix prefix) +bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { pos16 = 0; bool lastWasEscape = false; @@ -1110,7 +1106,7 @@ bool JavaScript::Lexer::scanRegExp(RegExpBodyPrefix prefix) flags = 0; while (isIdentLetter(current)) { - int flag = JavaScript::Ecma::RegExp::flagFromChar(current); + int flag = Ecma::RegExp::flagFromChar(current); if (flag == 0) { errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") .arg(QChar(current)); @@ -1124,7 +1120,7 @@ bool JavaScript::Lexer::scanRegExp(RegExpBodyPrefix prefix) return true; } -void JavaScript::Lexer::syncProhibitAutomaticSemicolon() +void Lexer::syncProhibitAutomaticSemicolon() { if (parenthesesState == BalancedParentheses) { // we have seen something like "if (foo)", which means we should diff --git a/src/declarative/qml/parser/javascriptlexer_p.h b/src/declarative/qml/parser/javascriptlexer_p.h index e71c10c..092609c 100644 --- a/src/declarative/qml/parser/javascriptlexer_p.h +++ b/src/declarative/qml/parser/javascriptlexer_p.h @@ -59,15 +59,15 @@ QT_BEGIN_NAMESPACE -class JavaScriptEnginePrivate; -class JavaScriptNameIdImpl; - namespace JavaScript { +class Engine; +class NameId; + class Lexer { public: - Lexer(JavaScriptEnginePrivate *eng); + Lexer(Engine *eng); ~Lexer(); void setCode(const QString &c, int lineno); @@ -136,7 +136,7 @@ public: bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); - JavaScriptNameIdImpl *pattern; + NameId *pattern; int flags; State lexerState() const @@ -155,7 +155,7 @@ public: { err = NoError; } private: - JavaScriptEnginePrivate *driver; + Engine *driver; int yylineno; bool done; char *buffer8; @@ -194,7 +194,7 @@ public: inline int ival() const { return qsyylval.ival; } inline double dval() const { return qsyylval.dval; } - inline JavaScriptNameIdImpl *ustr() const { return qsyylval.ustr; } + inline NameId *ustr() const { return qsyylval.ustr; } const QChar *characterBuffer() const { return buffer16; } int characterCount() const { return pos16; } @@ -219,7 +219,7 @@ private: union { int ival; double dval; - JavaScriptNameIdImpl *ustr; + NameId *ustr; } qsyylval; // current and following unicode characters diff --git a/src/declarative/qml/parser/javascriptnodepool_p.h b/src/declarative/qml/parser/javascriptnodepool_p.h index 3f59123..cb56fbb 100644 --- a/src/declarative/qml/parser/javascriptnodepool_p.h +++ b/src/declarative/qml/parser/javascriptnodepool_p.h @@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE -class JavaScriptEnginePrivate; - namespace JavaScript { namespace AST { @@ -70,6 +68,7 @@ class Node; class Code; class CompilationUnit; +class Engine; template <typename NodeType> inline NodeType *makeAstNode(MemoryPool *storage) @@ -109,13 +108,13 @@ inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg class NodePool : public MemoryPool { public: - NodePool(const QString &fileName, JavaScriptEnginePrivate *engine); + NodePool(const QString &fileName, Engine *engine); virtual ~NodePool(); Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); inline QString fileName() const { return m_fileName; } - inline JavaScriptEnginePrivate *engine() const { return m_engine; } + inline Engine *engine() const { return m_engine; } #ifndef J_SCRIPT_NO_EVENT_NOTIFY inline qint64 id() const { return m_id; } #endif @@ -123,7 +122,7 @@ public: private: QHash<AST::Node*, Code*> m_codeCache; QString m_fileName; - JavaScriptEnginePrivate *m_engine; + Engine *m_engine; #ifndef J_SCRIPT_NO_EVENT_NOTIFY qint64 m_id; #endif diff --git a/src/declarative/qml/parser/javascriptparser.cpp b/src/declarative/qml/parser/javascriptparser.cpp index ed791c8..7ff438e 100644 --- a/src/declarative/qml/parser/javascriptparser.cpp +++ b/src/declarative/qml/parser/javascriptparser.cpp @@ -53,6 +53,7 @@ #include "javascriptparser_p.h" +#include <QVarLengthArray> // // This file is automatically generated from javascript.g. @@ -63,7 +64,7 @@ using namespace JavaScript; QT_BEGIN_NAMESPACE -void JavaScriptParser::reallocateStack() +void Parser::reallocateStack() { if (! stack_size) stack_size = 128; @@ -75,7 +76,7 @@ void JavaScriptParser::reallocateStack() location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); } -inline static bool automatic(JavaScriptEnginePrivate *driver, int token) +inline static bool automatic(Engine *driver, int token) { return token == JavaScriptGrammar::T_RBRACE || token == 0 @@ -83,7 +84,8 @@ inline static bool automatic(JavaScriptEnginePrivate *driver, int token) } -JavaScriptParser::JavaScriptParser(): +Parser::Parser(Engine *engine): + driver(engine), tos(0), stack_size(0), sym_stack(0), @@ -94,7 +96,7 @@ JavaScriptParser::JavaScriptParser(): { } -JavaScriptParser::~JavaScriptParser() +Parser::~Parser() { if (stack_size) { qFree(sym_stack); @@ -113,7 +115,35 @@ static inline AST::SourceLocation location(Lexer *lexer) return loc; } -bool JavaScriptParser::parse(JavaScriptEnginePrivate *driver) +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<AST::SourceLocation, 4> locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { + AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse() { Lexer *lexer = driver->lexer(); bool hadErrors = false; @@ -166,7 +196,7 @@ bool JavaScriptParser::parse(JavaScriptEnginePrivate *driver) case 0: { program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); - sym(1).UiProgram = program; + sym(1).UiProgram = program; } break; case 2: { @@ -233,21 +263,12 @@ case 14: { } break; case 15: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(), - sym(3).sval, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 16: { - AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).sval, + AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(2).UiObjectInitializer); - node->identifierToken = loc(1); sym(1).Node = node; } break; -case 18: { +case 17: { AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(4).UiObjectMemberList->finish()); node->colonToken = loc(2); @@ -256,34 +277,50 @@ case 18: { sym(1).Node = node; } break; -case 19: { +case 18: { AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 21: { +case 20: { AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; - case 22: -case 23: { + +case 21: { + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(3).Expression)) { + AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + sym(1).UiQualifiedId->finish(), qualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; + } else { + sym(1).Node = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(2), + QLatin1String("Expected a type name after token `:'"))); + + return false; // ### recover + } +} break; +case 22:case 23:case 24:case 25:case 26:case 27: +{ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(), sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; -case 24: +case 28: -case 25: { +case 29: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); break; } -case 27: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (JavaScriptNameIdImpl *)0, sym(2).sval); +case 31: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -291,7 +328,7 @@ case 27: { sym(1).Node = node; } break; -case 29: { +case 33: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -300,7 +337,7 @@ case 29: { sym(1).Node = node; } break; -case 31: { +case 35: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -311,7 +348,7 @@ case 31: { sym(1).Node = node; } break; -case 33: { +case 37: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, sym(5).Expression); node->propertyToken = loc(1); @@ -322,7 +359,7 @@ case 33: { sym(1).Node = node; } break; -case 35: { +case 39: { AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, sym(6).Expression); node->isDefaultMember = true; @@ -335,88 +372,76 @@ case 35: { sym(1).Node = node; } break; -case 36: { +case 40: { sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 37: { +case 41: { sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); } break; -case 38: -case 39: +case 42: +case 43: { AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 41: { +case 45: { QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 42: { +case 46: { QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]); sym(1).sval = driver->intern(s.constData(), s.length()); break; } -case 43: { - AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 44: { - AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 45: { +case 47: { AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); node->thisToken = loc(1); sym(1).Node = node; } break; -case 46: { +case 48: { AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 47: { +case 49: { AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); node->nullToken = loc(1); sym(1).Node = node; } break; -case 48: { +case 50: { AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); node->trueToken = loc(1); sym(1).Node = node; } break; -case 49: { +case 51: { AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); node->falseToken = loc(1); sym(1).Node = node; } break; -case 50: { +case 52: { AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 51: { +case 53: { AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 52: { +case 54: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -427,7 +452,7 @@ case 52: { sym(1).Node = node; } break; -case 53: { +case 55: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -438,29 +463,46 @@ case 53: { sym(1).Node = node; } break; -case 54: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision); +case 56: { + 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 57: { + 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 55: { +case 58: { 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 56: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision); +case 59: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 60: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; -case 57: { +case 61: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), @@ -472,7 +514,7 @@ case 57: { sym(1).Node = node; } break; -case 58: { +case 62: { AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); @@ -480,100 +522,104 @@ case 58: { sym(1).Node = node; } break; -case 59: { +case 63: { 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 60: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision, sym(2).Expression); +case 64: { + AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 65: { + AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 66: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); } break; -case 61: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision, sym(4).Expression); +case 67: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); +} break; + +case 68: { + 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 62: { +case 69: { + 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 70: { AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); node->commaToken = loc(1); sym(1).Node = node; } break; -case 63: { +case 71: { AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 64: { - sym(1).Node = 0; -} break; - -case 65: { - sym(1).Elision = sym(1).Elision->finish (); -} break; - -case 66: { +case 72: { AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 67: { +case 73: { AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); - sym(1).Node = node; + sym(1).Node = node; } break; -case 68: { +case 74: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; -case 69: -case 70: { +case 75: +case 76: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; -case 71: { +case 77: { AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; -case 72: { +case 78: { AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; -case 73: { +case 79: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1).Node = node; } break; -case 74: - -case 75: - -case 76: - -case 77: - -case 78: - -case 79: - case 80: case 81: @@ -623,25 +669,37 @@ case 102: case 103: case 104: + +case 105: + +case 106: + +case 107: + +case 108: + +case 109: + +case 110: { sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); } break; -case 109: { +case 115: { 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 110: { +case 116: { 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 111: { +case 117: { AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -649,384 +707,384 @@ case 111: { sym(1).Node = node; } break; -case 113: { +case 119: { AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 114: { +case 120: { 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 115: { +case 121: { 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 116: { +case 122: { 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 117: { +case 123: { 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 118: { +case 124: { sym(1).Node = 0; } break; -case 119: { +case 125: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 120: { +case 126: { sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); } break; -case 121: { +case 127: { AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 125: { +case 131: { AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 126: { +case 132: { AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 128: { +case 134: { AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 129: { +case 135: { AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 130: { +case 136: { AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 131: { +case 137: { AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 132: { +case 138: { AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 133: { +case 139: { AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 134: { +case 140: { AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 135: { +case 141: { AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 136: { +case 142: { AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 138: { +case 144: { 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 139: { +case 145: { 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 140: { +case 146: { 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 142: { +case 148: { 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 143: { +case 149: { 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 145: { +case 151: { 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 146: { +case 152: { 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 147: { +case 153: { 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 149: { +case 155: { 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 150: { +case 156: { 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 151: { +case 157: { 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 152: { +case 158: { 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 153: { +case 159: { 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 154: { +case 160: { 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 156: { +case 162: { 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 157: { +case 163: { 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 158: { +case 164: { 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 159: { +case 165: { 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 160: { +case 166: { 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 162: { +case 168: { 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 163: { +case 169: { 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 164: { +case 170: { 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 165: { +case 171: { 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 167: { +case 173: { 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 168: { +case 174: { 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 169: { +case 175: { 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 170: { +case 176: { 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 172: { +case 178: { 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 174: { +case 180: { 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 176: { +case 182: { 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 178: { +case 184: { 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 180: { +case 186: { 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 182: { +case 188: { 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 184: { +case 190: { 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 186: { +case 192: { 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 188: { +case 194: { 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 190: { +case 196: { 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 192: { +case 198: { AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1034,7 +1092,7 @@ case 192: { sym(1).Node = node; } break; -case 194: { +case 200: { AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1042,112 +1100,112 @@ case 194: { sym(1).Node = node; } break; -case 196: { +case 202: { 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 198: { +case 204: { 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 199: { +case 205: { sym(1).ival = QSOperator::Assign; } break; -case 200: { +case 206: { sym(1).ival = QSOperator::InplaceMul; } break; -case 201: { +case 207: { sym(1).ival = QSOperator::InplaceDiv; } break; -case 202: { +case 208: { sym(1).ival = QSOperator::InplaceMod; } break; -case 203: { +case 209: { sym(1).ival = QSOperator::InplaceAdd; } break; -case 204: { +case 210: { sym(1).ival = QSOperator::InplaceSub; } break; -case 205: { +case 211: { sym(1).ival = QSOperator::InplaceLeftShift; } break; -case 206: { +case 212: { sym(1).ival = QSOperator::InplaceRightShift; } break; -case 207: { +case 213: { sym(1).ival = QSOperator::InplaceURightShift; } break; -case 208: { +case 214: { sym(1).ival = QSOperator::InplaceAnd; } break; -case 209: { +case 215: { sym(1).ival = QSOperator::InplaceXor; } break; -case 210: { +case 216: { sym(1).ival = QSOperator::InplaceOr; } break; -case 212: { +case 218: { AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 213: { +case 219: { sym(1).Node = 0; } break; -case 216: { +case 222: { AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 217: { +case 223: { sym(1).Node = 0; } break; -case 234: { +case 240: { 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 235: { +case 241: { sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); } break; -case 236: { +case 242: { sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); } break; -case 237: { +case 243: { sym(1).Node = 0; } break; -case 238: { +case 244: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 240: { +case 246: { AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1155,76 +1213,76 @@ case 240: { sym(1).Node = node; } break; -case 241: { +case 247: { sym(1).ival = T_CONST; } break; -case 242: { +case 248: { sym(1).ival = T_VAR; } break; -case 243: { +case 249: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 244: { +case 250: { AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 245: { +case 251: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); } break; -case 246: { +case 252: { sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 247: { +case 253: { AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 248: { +case 254: { AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 249: { +case 255: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 250: { +case 256: { sym(1).Node = 0; } break; -case 252: { +case 258: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 253: { +case 259: { sym(1).Node = 0; } break; -case 255: { +case 261: { AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 257: { +case 263: { AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 258: { +case 264: { 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); @@ -1233,7 +1291,7 @@ case 258: { sym(1).Node = node; } break; -case 259: { +case 265: { AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1241,7 +1299,7 @@ case 259: { sym(1).Node = node; } break; -case 261: { +case 267: { AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1251,7 +1309,7 @@ case 261: { sym(1).Node = node; } break; -case 262: { +case 268: { AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1259,7 +1317,7 @@ case 262: { sym(1).Node = node; } break; -case 263: { +case 269: { AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1270,7 +1328,7 @@ case 263: { sym(1).Node = node; } break; -case 264: { +case 270: { AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1283,7 +1341,7 @@ case 264: { sym(1).Node = node; } break; -case 265: { +case 271: { AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1293,7 +1351,7 @@ case 265: { sym(1).Node = node; } break; -case 266: { +case 272: { AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1304,14 +1362,14 @@ case 266: { sym(1).Node = node; } break; -case 268: { +case 274: { AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 270: { +case 276: { AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1319,14 +1377,14 @@ case 270: { sym(1).Node = node; } break; -case 272: { +case 278: { AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 274: { +case 280: { AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1334,14 +1392,14 @@ case 274: { sym(1).Node = node; } break; -case 276: { +case 282: { 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 277: { +case 283: { AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1349,7 +1407,7 @@ case 277: { sym(1).Node = node; } break; -case 278: { +case 284: { AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1357,90 +1415,90 @@ case 278: { sym(1).Node = node; } break; -case 279: { +case 285: { 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 280: { +case 286: { 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 281: { +case 287: { sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); } break; -case 282: { +case 288: { sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); } break; -case 283: { +case 289: { sym(1).Node = 0; } break; -case 284: { +case 290: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 285: { +case 291: { 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 286: { +case 292: { 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 287: -case 288: { +case 293: +case 294: { 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 289: { +case 295: { 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 291: { +case 297: { 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 292: { +case 298: { AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 293: { +case 299: { AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 294: { +case 300: { 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 295: { +case 301: { AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1449,20 +1507,20 @@ case 295: { sym(1).Node = node; } break; -case 296: { +case 302: { AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 298: { +case 304: { AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 299: { +case 305: { 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); @@ -1473,7 +1531,7 @@ case 299: { sym(1).Node = node; } break; -case 300: { +case 306: { 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) @@ -1485,56 +1543,56 @@ case 300: { sym(1).Node = node; } break; -case 301: { +case 307: { AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 302: { +case 308: { 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 303: { +case 309: { sym(1).Node = 0; } break; -case 304: { +case 310: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 305: { +case 311: { sym(1).Node = 0; } break; -case 307: { +case 313: { sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); } break; -case 308: { +case 314: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); } break; -case 309: { +case 315: { sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); } break; -case 310: { +case 316: { sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); } break; -case 311: { +case 317: { sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); } break; -case 312: { +case 318: { sym(1).sval = 0; } break; -case 314: { +case 320: { sym(1).Node = 0; } break; diff --git a/src/declarative/qml/parser/javascriptparser_p.h b/src/declarative/qml/parser/javascriptparser_p.h index 5e68fe7..2ae4c34 100644 --- a/src/declarative/qml/parser/javascriptparser_p.h +++ b/src/declarative/qml/parser/javascriptparser_p.h @@ -62,86 +62,71 @@ #include "javascriptgrammar_p.h" #include "javascriptast_p.h" +#include "javascriptengine_p.h" + #include <QtCore/QList> QT_BEGIN_NAMESPACE class QString; -class JavaScriptEnginePrivate; -class JavaScriptNameIdImpl; -class JavaScriptParser: protected JavaScriptGrammar +namespace JavaScript { + +class Engine; +class NameId; + +class Parser: protected JavaScriptGrammar { public: union Value { int ival; double dval; - JavaScriptNameIdImpl *sval; - JavaScript::AST::ArgumentList *ArgumentList; - JavaScript::AST::CaseBlock *CaseBlock; - JavaScript::AST::CaseClause *CaseClause; - JavaScript::AST::CaseClauses *CaseClauses; - JavaScript::AST::Catch *Catch; - JavaScript::AST::DefaultClause *DefaultClause; - JavaScript::AST::ElementList *ElementList; - JavaScript::AST::Elision *Elision; - JavaScript::AST::ExpressionNode *Expression; - JavaScript::AST::Finally *Finally; - JavaScript::AST::FormalParameterList *FormalParameterList; - JavaScript::AST::FunctionBody *FunctionBody; - JavaScript::AST::FunctionDeclaration *FunctionDeclaration; - JavaScript::AST::Node *Node; - JavaScript::AST::PropertyName *PropertyName; - JavaScript::AST::PropertyNameAndValueList *PropertyNameAndValueList; - JavaScript::AST::SourceElement *SourceElement; - JavaScript::AST::SourceElements *SourceElements; - JavaScript::AST::Statement *Statement; - JavaScript::AST::StatementList *StatementList; - JavaScript::AST::Block *Block; - JavaScript::AST::VariableDeclaration *VariableDeclaration; - JavaScript::AST::VariableDeclarationList *VariableDeclarationList; - - JavaScript::AST::UiProgram *UiProgram; - JavaScript::AST::UiImportList *UiImportList; - JavaScript::AST::UiImport *UiImport; - JavaScript::AST::UiPublicMember *UiPublicMember; - JavaScript::AST::UiObjectDefinition *UiObjectDefinition; - JavaScript::AST::UiObjectInitializer *UiObjectInitializer; - JavaScript::AST::UiObjectBinding *UiObjectBinding; - JavaScript::AST::UiScriptBinding *UiScriptBinding; - JavaScript::AST::UiArrayBinding *UiArrayBinding; - JavaScript::AST::UiObjectMember *UiObjectMember; - JavaScript::AST::UiObjectMemberList *UiObjectMemberList; - JavaScript::AST::UiQualifiedId *UiQualifiedId; - }; - - struct DiagnosticMessage { - enum Kind { Warning, Error }; - - DiagnosticMessage() - : kind(Error) {} - - DiagnosticMessage(Kind kind, const JavaScript::AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} - - bool isWarning() const - { return kind == Warning; } - - bool isError() const - { return kind == Error; } - - Kind kind; - JavaScript::AST::SourceLocation loc; - QString message; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiQualifiedId *UiQualifiedId; }; public: - JavaScriptParser(); - ~JavaScriptParser(); + Parser(Engine *engine); + ~Parser(); - bool parse(JavaScriptEnginePrivate *driver); + bool parse(); - JavaScript::AST::UiProgram *ast() + AST::UiProgram *ast() { return program; } QList<DiagnosticMessage> diagnosticMessages() const @@ -172,17 +157,20 @@ protected: inline Value &sym(int index) { return sym_stack [tos + index - 1]; } - inline JavaScript::AST::SourceLocation &loc(int index) + inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + protected: + Engine *driver; int tos; int stack_size; Value *sym_stack; int *state_stack; - JavaScript::AST::SourceLocation *location_stack; + AST::SourceLocation *location_stack; - JavaScript::AST::UiProgram *program; + AST::UiProgram *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; @@ -190,12 +178,12 @@ protected: struct SavedToken { int token; double dval; - JavaScript::AST::SourceLocation loc; + AST::SourceLocation loc; }; double yylval; - JavaScript::AST::SourceLocation yylloc; - JavaScript::AST::SourceLocation yyprevlloc; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; @@ -204,10 +192,13 @@ protected: QList<DiagnosticMessage> diagnostic_messages; }; +} // end of namespace JavaScript + + -#define J_SCRIPT_REGEXPLITERAL_RULE1 52 +#define J_SCRIPT_REGEXPLITERAL_RULE1 54 -#define J_SCRIPT_REGEXPLITERAL_RULE2 53 +#define J_SCRIPT_REGEXPLITERAL_RULE2 55 QT_END_NAMESPACE diff --git a/src/declarative/qml/parser/javascriptprettypretty.cpp b/src/declarative/qml/parser/javascriptprettypretty.cpp index 6e632b7..0342b39 100644 --- a/src/declarative/qml/parser/javascriptprettypretty.cpp +++ b/src/declarative/qml/parser/javascriptprettypretty.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE namespace JavaScript { -QString numberToString(qjsreal value); +QString numberToString(double value); } using namespace JavaScript; @@ -182,7 +182,7 @@ void PrettyPretty::endVisit(AST::ThisExpression *node) bool PrettyPretty::visit(AST::IdentifierExpression *node) { - out << JavaScriptEnginePrivate::toString(node->name); + out << Engine::toString(node->name); return true; } @@ -229,7 +229,7 @@ void PrettyPretty::endVisit(AST::FalseLiteral *node) bool PrettyPretty::visit(AST::StringLiteral *node) { - QString lit = JavaScriptEnginePrivate::toString(node->value); + QString lit = Engine::toString(node->value); lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); out << "\"" << lit << "\""; return false; @@ -253,7 +253,7 @@ void PrettyPretty::endVisit(AST::NumericLiteral *node) bool PrettyPretty::visit(AST::RegExpLiteral *node) { - out << "/" << JavaScriptEnginePrivate::toString(node->pattern) << "/"; + out << "/" << Engine::toString(node->pattern) << "/"; if (node->flags) out << JavaScript::Ecma::RegExp::flagsToString(node->flags); @@ -348,7 +348,7 @@ void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node) bool PrettyPretty::visit(AST::IdentifierPropertyName *node) { - out << JavaScriptEnginePrivate::toString(node->id); + out << Engine::toString(node->id); return false; } @@ -359,7 +359,7 @@ void PrettyPretty::endVisit(AST::IdentifierPropertyName *node) bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) { - QString lit = JavaScriptEnginePrivate::toString(node->id); + QString lit = Engine::toString(node->id); lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); out << lit; return false; @@ -398,7 +398,7 @@ void PrettyPretty::endVisit(AST::ArrayMemberExpression *node) bool PrettyPretty::visit(AST::FieldMemberExpression *node) { accept(node->base); - out << "." << JavaScriptEnginePrivate::toString(node->name); + out << "." << Engine::toString(node->name); return false; } @@ -803,7 +803,7 @@ void PrettyPretty::endVisit(AST::VariableStatement *node) bool PrettyPretty::visit(AST::VariableDeclaration *node) { - out << JavaScriptEnginePrivate::toString(node->name); + out << Engine::toString(node->name); if (node->expression) { out << " = "; accept(node->expression); @@ -959,7 +959,7 @@ bool PrettyPretty::visit(AST::ContinueStatement *node) { out << "continue"; if (node->label) { - out << " " << JavaScriptEnginePrivate::toString(node->label); + out << " " << Engine::toString(node->label); } out << ";"; return false; @@ -974,7 +974,7 @@ bool PrettyPretty::visit(AST::BreakStatement *node) { out << "break"; if (node->label) { - out << " " << JavaScriptEnginePrivate::toString(node->label); + out << " " << Engine::toString(node->label); } out << ";"; return false; @@ -1095,7 +1095,7 @@ void PrettyPretty::endVisit(AST::DefaultClause *node) bool PrettyPretty::visit(AST::LabelledStatement *node) { - out << JavaScriptEnginePrivate::toString(node->label) << ": "; + out << Engine::toString(node->label) << ": "; return true; } @@ -1123,7 +1123,7 @@ bool PrettyPretty::visit(AST::TryStatement *node) out << "try "; acceptAsBlock(node->statement); if (node->catchExpression) { - out << " catch (" << JavaScriptEnginePrivate::toString(node->catchExpression->name) << ") "; + out << " catch (" << Engine::toString(node->catchExpression->name) << ") "; acceptAsBlock(node->catchExpression->statement); } if (node->finallyExpression) { @@ -1166,13 +1166,13 @@ bool PrettyPretty::visit(AST::FunctionDeclaration *node) out << "function"; if (node->name) - out << " " << JavaScriptEnginePrivate::toString(node->name); + out << " " << Engine::toString(node->name); // the arguments out << "("; for (AST::FormalParameterList *it = node->formals; it; it = it->next) { if (it->name) - out << JavaScriptEnginePrivate::toString(it->name); + out << Engine::toString(it->name); if (it->next) out << ", "; @@ -1205,13 +1205,13 @@ bool PrettyPretty::visit(AST::FunctionExpression *node) out << "function"; if (node->name) - out << " " << JavaScriptEnginePrivate::toString(node->name); + out << " " << Engine::toString(node->name); // the arguments out << "("; for (AST::FormalParameterList *it = node->formals; it; it = it->next) { if (it->name) - out << JavaScriptEnginePrivate::toString(it->name); + out << Engine::toString(it->name); if (it->next) out << ", "; diff --git a/src/declarative/qml/parser/javascriptvalue.h b/src/declarative/qml/parser/javascriptvalue.h deleted file mode 100644 index c68b817..0000000 --- a/src/declarative/qml/parser/javascriptvalue.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef JAVASCRIPTVALUE_H -#define JAVASCRIPTVALUE_H - -typedef double qjsreal; - -#endif // JAVASCRIPTVALUE_H diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri index 130aeaf..b4d226a 100644 --- a/src/declarative/qml/parser/parser.pri +++ b/src/declarative/qml/parser/parser.pri @@ -8,8 +8,7 @@ HEADERS += $$PWD/javascriptast_p.h \ $$PWD/javascriptmemorypool_p.h \ $$PWD/javascriptnodepool_p.h \ $$PWD/javascriptparser_p.h \ - $$PWD/javascriptprettypretty_p.h \ - $$PWD/javascriptvalue.h \ + $$PWD/javascriptprettypretty_p.h SOURCES += $$PWD/javascriptast.cpp \ $$PWD/javascriptastvisitor.cpp \ diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbindablevalue.h index c4ef64a..7831177 100644 --- a/src/declarative/qml/qmlbindablevalue.h +++ b/src/declarative/qml/qmlbindablevalue.h @@ -42,10 +42,10 @@ #ifndef QMLBINDABLEVALUE_H #define QMLBINDABLEVALUE_H -#include <QObject> -#include <qfxglobal.h> -#include <qml.h> -#include <qmlpropertyvaluesource.h> +#include <QtCore/QObject> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlpropertyvaluesource.h> #include <QtDeclarative/qmlexpression.h> diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbindablevalue_p.h index d9af0ef..9973bdc 100644 --- a/src/declarative/qml/qmlbindablevalue_p.h +++ b/src/declarative/qml/qmlbindablevalue_p.h @@ -43,8 +43,8 @@ #define QMLBINDABLEVALUE_P_H #include <private/qobject_p.h> -#include <qmlbindablevalue.h> -#include <qmlmetaproperty.h> +#include <QtDeclarative/qmlbindablevalue.h> +#include <QtDeclarative/qmlmetaproperty.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h index e84f0c1..2c05770 100644 --- a/src/declarative/qml/qmlboundsignal_p.h +++ b/src/declarative/qml/qmlboundsignal_p.h @@ -42,7 +42,7 @@ #ifndef QMLBOUNDSIGNAL_P_H #define QMLBOUNDSIGNAL_P_H -#include <qmlexpression.h> +#include <QtDeclarative/qmlexpression.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmlcompiledcomponent_p.h b/src/declarative/qml/qmlcompiledcomponent_p.h index c5e1226..2201423 100644 --- a/src/declarative/qml/qmlcompiledcomponent_p.h +++ b/src/declarative/qml/qmlcompiledcomponent_p.h @@ -42,7 +42,7 @@ #ifndef QMLCOMPILEDCOMPONENT_P_H #define QMLCOMPILEDCOMPONENT_P_H -#include <qml.h> +#include <QtDeclarative/qml.h> #include <private/qmlinstruction_p.h> #include <private/qmlcompiler_p.h> #include <private/qmlrefcount_p.h> diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index b205efb..8990732 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1050,8 +1050,9 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, COMPILE_EXCEPTION("Can only assign one binding to lists"); assignedBinding = true; - compileBinding(v->value.asScript(), prop, ctxt, - obj->metaObject(), v->location.start.line); + COMPILE_CHECK(compileBinding(v->value.asScript(), prop, ctxt, + obj->metaObject(), + v->location.start.line)); v->type = Value::PropertyBinding; } else { COMPILE_EXCEPTION("Cannot assign primitives to lists"); @@ -1204,8 +1205,9 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, { if (v->value.isScript()) { - compileBinding(v->value.asScript(), prop, ctxt, obj->metaObject(), - v->location.start.line); + COMPILE_CHECK(compileBinding(v->value.asScript(), prop, ctxt, + obj->metaObject(), + v->location.start.line)); v->type = Value::PropertyBinding; @@ -1214,37 +1216,24 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, QmlInstruction assign; assign.line = v->location.start.line; - bool doassign = true; if (prop->index != -1) { QString value = v->primitive(); StoreInstructionResult r = generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &value); if (r == Ok) { - doassign = false; } else if (r == InvalidData) { //### we are restricted to a rather generic message here. If we can find a way to move // the exception into generateStoreInstruction we could potentially have better messages. // (the problem is that both compile and run exceptions can be generated, though) COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to property" << obj->metaObject()->property(prop->index).name()); - doassign = false; } else if (r == ReadOnly) { COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to the read-only property" << obj->metaObject()->property(prop->index).name()); } else { - doassign = true; + COMPILE_EXCEPTION2(prop, "Cannot assign value to property" << obj->metaObject()->property(prop->index).name() << "of unknown type"); } - } - - if (doassign) { - assign.type = QmlInstruction::AssignConstant; - if (prop->isDefault) { - assign.assignConstant.property = -1; - } else { - assign.assignConstant.property = - output->indexForByteArray(prop->name); - } - assign.assignConstant.constant = - output->indexForString(v->primitive()); + } else { + COMPILE_EXCEPTION2(prop, "Cannot assign value to non-existant property" << prop->name); } output->bytecode << assign; @@ -1342,7 +1331,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) return true; } -void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, +bool QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, int ctxt, const QMetaObject *mo, qint64 line) { QmlBasicScript bs; @@ -1355,10 +1344,12 @@ void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, bref = output->indexForString(bind); } - QmlInstruction assign; - assign.assignBinding.context = ctxt; - assign.line = line; if (prop->index != -1) { + + QmlInstruction assign; + assign.assignBinding.context = ctxt; + assign.line = line; + if (bs.isValid()) assign.type = QmlInstruction::StoreCompiledBinding; else @@ -1368,20 +1359,18 @@ void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, assign.assignBinding.value = bref; assign.assignBinding.category = QmlMetaProperty::Unknown; if (mo) { - //XXX we should generate an exception if the property is read-only + // ### we should generate an exception if the property is read-only QMetaProperty mp = mo->property(assign.assignBinding.property); assign.assignBinding.category = QmlMetaProperty::propertyCategory(mp); } + + output->bytecode << assign; + } else { - if (bs.isValid()) - assign.type = QmlInstruction::AssignCompiledBinding; - else - assign.type = QmlInstruction::AssignBinding; - assign.assignBinding.property = output->indexForByteArray(prop->name); - assign.assignBinding.value = bref; - assign.assignBinding.category = QmlMetaProperty::Unknown; + COMPILE_EXCEPTION2(prop, "Cannot assign binding to non-existant property" << prop->name); } - output->bytecode << assign; + + return true; } int QmlCompiler::optimizeExpressions(int start, int end, int patch) @@ -1414,9 +1403,7 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch) continue; } - if (instr.type == QmlInstruction::AssignBinding || - instr.type == QmlInstruction::AssignCompiledBinding || - instr.type == QmlInstruction::StoreBinding || + if (instr.type == QmlInstruction::StoreBinding || instr.type == QmlInstruction::StoreCompiledBinding) { ++bindingsCount; } else if (instr.type == QmlInstruction::TryBeginObject || diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 64400c5..bc04cfa 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -44,8 +44,8 @@ #include <QtCore/qbytearray.h> #include <QtCore/qset.h> -#include <qml.h> -#include <qmlerror.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlerror.h> #include <private/qmlinstruction_p.h> #include <private/qmlcompositetypemanager_p.h> #include <private/qmlparser_p.h> @@ -164,7 +164,7 @@ private: int ctxt); bool compileDynamicMeta(QmlParser::Object *obj); - void compileBinding(const QString &, QmlParser::Property *prop, + bool compileBinding(const QString &, QmlParser::Property *prop, int ctxt, const QMetaObject *, qint64); int optimizeExpressions(int start, int end, int patch = -1); diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index 4de47c6..254d9ba 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -42,21 +42,21 @@ #ifndef QMLCOMPONENT_P_H #define QMLCOMPONENT_P_H -#include <QString> -#include <QStringList> -#include <QList> -#include "private/qobject_p.h" -#include "private/qmlengine_p.h" -#include "private/qmlcompositetypemanager_p.h" -#include <qmlerror.h> -#include "qmlcomponent.h" +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QList> +#include <private/qobject_p.h> +#include <private/qmlengine_p.h> +#include <private/qmlcompositetypemanager_p.h> +#include <QtDeclarative/qmlerror.h> +#include <QtDeclarative/qmlcomponent.h> +#include <QtDeclarative/qml.h> + +QT_BEGIN_NAMESPACE + class QmlComponent; class QmlEngine; class QmlCompiledComponent; -#include "qml.h" - - -QT_BEGIN_NAMESPACE class QmlComponentPrivate : public QObjectPrivate { diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h index f03b2cb..9312819 100644 --- a/src/declarative/qml/qmlcompositetypemanager_p.h +++ b/src/declarative/qml/qmlcompositetypemanager_p.h @@ -42,10 +42,10 @@ #ifndef QMLCOMPOSITETYPEMANAGER_P_H #define QMLCOMPOSITETYPEMANAGER_P_H -#include <qglobal.h> +#include <QtCore/qglobal.h> #include <private/qmlscriptparser_p.h> #include <private/qmlrefcount_p.h> -#include <qmlerror.h> +#include <QtDeclarative/qmlerror.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index fa36eb1..ea72ebf 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -149,7 +149,7 @@ void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) QmlContext context(engine.rootContext()); context.setContextProperty("myModel", modelData); - QmlComponent component("ListView { model=myModel }"); + QmlComponent component(&engine, "ListView { model=myModel }"); component.create(&context); \endcode @@ -176,7 +176,7 @@ void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) QmlContext context(engine.rootContext()); context.addDefaultObject(&myDataSet); - QmlComponent component("ListView { model=myModel }"); + QmlComponent component(&engine, "ListView { model=myModel }"); component.create(&context); \endcode diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 6f1e486..4d88fc2 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -42,11 +42,11 @@ #ifndef QMLCONTEXT_P_H #define QMLCONTEXT_P_H -#include <qmlcontext.h> +#include <QtDeclarative/qmlcontext.h> #include <private/qobject_p.h> #include <private/qmldeclarativedata_p.h> -#include <qhash.h> -#include <qscriptvalue.h> +#include <QtCore/qhash.h> +#include <QtScript/qscriptvalue.h> #include <QtCore/qset.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp index e864df9..a60f783 100644 --- a/src/declarative/qml/qmlcustomparser.cpp +++ b/src/declarative/qml/qmlcustomparser.cpp @@ -120,6 +120,7 @@ QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root) return rootNode; } +#include <QtCore/qdebug.h> QmlCustomParserProperty QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) { @@ -127,20 +128,23 @@ QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) prop.d->name = p->name; prop.d->isList = (p->values.count() > 1); - for(int ii = 0; ii < p->values.count(); ++ii) { - Value *v = p->values.at(ii); + if (p->value) { + QmlCustomParserNode node = fromObject(p->value); + QList<QmlCustomParserProperty> props = node.properties(); + for (int ii = 0; ii < props.count(); ++ii) + prop.d->values << QVariant::fromValue(props.at(ii)); + } else { + for(int ii = 0; ii < p->values.count(); ++ii) { + Value *v = p->values.at(ii); + + if(v->object) { + QmlCustomParserNode node = fromObject(v->object); + prop.d->values << QVariant::fromValue(node); + } else { + prop.d->values << QVariant::fromValue(v->value); + } - // We skip fetched properties for now - if(v->object && v->object->type == -1) - continue; - - if(v->object) { - QmlCustomParserNode node = fromObject(v->object); - prop.d->values << QVariant::fromValue(node); - } else { - prop.d->values << QVariant::fromValue(v->primitive()); } - } return prop; diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h index e4e6089..fd780d6 100644 --- a/src/declarative/qml/qmlcustomparser_p.h +++ b/src/declarative/qml/qmlcustomparser_p.h @@ -65,6 +65,8 @@ public: QByteArray name() const; bool isList() const; + // Will be one of QmlParser::Variant, QmlCustomParserProperty or + // QmlCustomParserNode QList<QVariant> assignedValues() const; private: diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index 673520e..9871fcb 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -477,12 +477,7 @@ QmlDomObjectPrivate::properties(QmlParser::Property *property) const iter->second.prepend(name); } else { - - // We don't display "id" sets as a property in the dom - if (property->values.count() != 1 || - property->values.at(0)->type != QmlParser::Value::Id) - rv << qMakePair(property, property->name); - + rv << qMakePair(property, property->name); } return rv; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 227aeb0..c0ea463 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -193,6 +193,7 @@ void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss) void QmlEnginePrivate::init() { + scriptEngine.installTranslatorFunctions(); contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); rootContext = new QmlContext(q); @@ -424,8 +425,8 @@ bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString & \code QmlEngine engine; - QmlComponent component("Text { text: \"Hello world!\" }"); - QFxItem *item = qobject_cast<QFxItem *>(component.create(&engine)); + QmlComponent component(&engine, "Text { text: \"Hello world!\" }"); + QFxItem *item = qobject_cast<QFxItem *>(component.create()); //add item to view, etc ... @@ -614,6 +615,35 @@ QUrl QmlEngine::componentUrl(const QUrl& src, const QUrl& baseUrl) const } /*! + Returns the list of base urls the engine browses to find sub-components. + + The search path consists of the base of the \a url, and, in the case of local files, + the directories imported using the "import" statement in \a qml. + */ +QList<QUrl> QmlEngine::componentSearchPath(const QByteArray &qml, const QUrl &url) const +{ + QList<QUrl> searchPath; + + searchPath << url.resolved(QUrl(QLatin1String("."))); + + if (QFileInfo(url.toLocalFile()).exists()) { + QmlScriptParser parser; + if (parser.parse(qml, url)) { + for (int i = 0; i < parser.imports().size(); ++i) { + QUrl importUrl = QUrl(parser.imports().at(i).uri); + if (importUrl.isRelative()) { + searchPath << url.resolved(importUrl); + } else { + searchPath << importUrl; + } + } + } + } + + return searchPath; +} + +/*! Sets the common QNetworkAccessManager, \a network, used by all QML elements instantiated by this engine. @@ -781,17 +811,17 @@ QmlEngine *QmlEngine::activeEngine() QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b) -: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), id(0), log(0) +: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), line(-1), id(0), log(0) { } QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc) -: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0) +: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0) { } QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile) -: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0) +: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), line(-1), id(0), log(0) { if (ssecompile) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -996,7 +1026,7 @@ QVariant QmlExpression::value() for (int i = context()->d_func()->scopeChain.size() - 1; i > -1; --i) { scriptEngine->currentContext()->pushScope(context()->d_func()->scopeChain.at(i)); } - QScriptValue svalue = scriptEngine->evaluate(expression()); + QScriptValue svalue = scriptEngine->evaluate(expression(), d->fileName, d->line); if (scriptEngine->hasUncaughtException()) { if (scriptEngine->uncaughtException().isError()){ QScriptValue exception = scriptEngine->uncaughtException(); @@ -1027,9 +1057,7 @@ QVariant QmlExpression::value() } rv = QVariant::fromValue(list); } - } /*else if (svalue.isVariant()) { - rv = svalue.toVariant(); - }*/ else if (svalue.isObject()) { + } else if (svalue.isObject()) { QScriptValue objValue = svalue.data(); if (objValue.isValid()) rv = objValue.toVariant(); @@ -1153,6 +1181,16 @@ void QmlExpression::setTrackChange(bool trackChange) } /*! + Set the location of this expression to \a line of \a fileName. This information + is used by the script engine. +*/ +void QmlExpression::setSourceLocation(const QString &fileName, int line) +{ + d->fileName = fileName; + d->line = line; +} + +/*! Returns the expression's scope object, if provided, otherwise 0. In addition to data provided by the expression's QmlContext, the scope diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index fde84d4..9382389 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -78,6 +78,8 @@ public: QMap<QString,QString> nameSpacePaths() const; QUrl componentUrl(const QUrl& src, const QUrl& baseUrl) const; + QList<QUrl> componentSearchPath(const QByteArray &qml, const QUrl &url) const; + void setNetworkAccessManager(QNetworkAccessManager *); QNetworkAccessManager *networkAccessManager() const; diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 7578fdf..0dc4736 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -42,9 +42,9 @@ #ifndef QMLENGINE_P_H #define QMLENGINE_P_H -#include <QScriptClass> -#include <QScriptValue> -#include <QScriptString> +#include <QtScript/QScriptClass> +#include <QtScript/QScriptValue> +#include <QtScript/QScriptString> #include <QtCore/qstring.h> #include <QtCore/qlist.h> #include <QtCore/qpair.h> @@ -52,11 +52,11 @@ #include <private/qobject_p.h> #include <private/qmlclassfactory_p.h> #include <private/qmlcompositetypemanager_p.h> -#include <qml.h> -#include <qmlbasicscript.h> -#include <qmlcontext.h> -#include <qmlengine.h> -#include <qmlexpression.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlbasicscript.h> +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlexpression.h> #include <QtScript/qscriptengine.h> QT_BEGIN_NAMESPACE @@ -277,6 +277,8 @@ public: BindExpressionProxy *proxy; QObject *me; bool trackChange; + QString fileName; + int line; quint32 id; diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index 2c6b1ad..ea3b093 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -78,6 +78,8 @@ public: bool trackChange() const; void setTrackChange(bool); + void setSourceLocation(const QString &fileName, int line); + QObject *scopeObject() const; quint32 id() const; diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 6b49359..923d36f 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -124,18 +124,9 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreSignal: qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value); break; - case QmlInstruction::AssignConstant: - qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CONSTANT\t" << instr->assignConstant.property << "\t" << instr->assignConstant.constant << "\t\t" << datas.at(instr->assignConstant.property) << primitives.at(instr->assignConstant.constant); - break; case QmlInstruction::AssignSignalObject: qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal); break; - case QmlInstruction::AssignBinding: - qWarning() << idx << "\t" << line << "\t" << "ASSIGN_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property) << primitives.at(instr->assignBinding.value); - break; - case QmlInstruction::AssignCompiledBinding: - qWarning() << idx << "\t" << line << "\t" << "ASSIGN_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property); - break; case QmlInstruction::AssignValueSource: qWarning() << idx << "\t" << line << "\t" << "ASSIGN_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t\t\t" << datas.at(instr->assignValueSource.property); break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index f06f0e6..a21ccee 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -42,7 +42,7 @@ #ifndef QMLINSTRUCTION_P_H #define QMLINSTRUCTION_P_H -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> QT_BEGIN_NAMESPACE @@ -110,14 +110,9 @@ public: // // Unresolved single assignment // - // AssignConstant - Store a value in a property. Will resolve into - // a Store* instruction. - AssignConstant, /* assignConstant */ AssignSignalObject, /* assignSignalObject */ AssignCustomType, /* assignCustomType */ - AssignBinding, /* assignBinding */ - AssignCompiledBinding, /* assignBinding */ AssignValueSource, /* assignValueSource */ StoreBinding, /* assignBinding */ StoreCompiledBinding, /* assignBinding */ @@ -187,10 +182,6 @@ public: } setId; struct { int property; - int constant; - } assignConstant; - struct { - int property; int castValue; } assignObject; struct { diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 59d6b38..e3e9ff5 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -100,9 +100,16 @@ QmlMetaProperty::~QmlMetaProperty() delete d; d = 0; } -// ### not thread safe -static QHash<const QMetaObject *, QMetaPropertyEx> qmlCacheDefProp; +struct CachedPropertyData { + CachedPropertyData(const QString &n, int pt, int ci) + : name(n), propType(pt), coreIdx(ci) {} + QString name; + int propType; + int coreIdx; +}; +// ### not thread safe +static QHash<const QMetaObject *, CachedPropertyData> qmlCacheDefProp; /*! Creates a QmlMetaProperty for the default property of \a obj. If there is no @@ -131,23 +138,22 @@ void QmlMetaProperty::initDefault(QObject *obj) return; d->object = obj; - QHash<const QMetaObject *, QMetaPropertyEx>::ConstIterator iter = + QHash<const QMetaObject *, CachedPropertyData>::ConstIterator iter = qmlCacheDefProp.find(obj->metaObject()); if (iter != qmlCacheDefProp.end()) { - d->prop = *iter; - d->propType = iter->propertyType; - d->coreIdx = iter->propertyType; + d->name = iter->name; + d->propType = iter->propType; + d->coreIdx = iter->coreIdx; } else { QMetaPropertyEx p(QmlMetaType::defaultProperty(obj)); - d->prop = p; + d->name = QLatin1String(p.name()); d->propType = p.propertyType; - d->coreIdx = d->prop.propertyIndex(); + d->coreIdx = p.propertyIndex(); if (!QObjectPrivate::get(obj)->metaObject) - qmlCacheDefProp.insert(obj->metaObject(), d->prop); + qmlCacheDefProp.insert(obj->metaObject(), CachedPropertyData(d->name, d->propType, d->coreIdx)); } - if (d->prop.name() != 0) { + if (!d->name.isEmpty()) { d->type = Property | Default; - d->name = QLatin1String(d->prop.name()); } } @@ -166,15 +172,14 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, PropertyCategory cat, Qm d->type = Property; d->category = cat; QMetaPropertyEx p(obj->metaObject()->property(idx)); - d->prop = p; d->propType = p.propertyType; d->coreIdx = idx; - if (d->prop.name() != 0) - d->name = QLatin1String(d->prop.name()); + if (p.name() != 0) + d->name = QLatin1String(p.name()); } // ### Not thread safe!!!! -static QHash<const QMetaObject *, QHash<QString, QMetaPropertyEx> > qmlCacheProps; +static QHash<const QMetaObject *, QHash<QString, CachedPropertyData> > qmlCacheProps; /*! Creates a QmlMetaProperty for the property \a name of \a obj. */ @@ -225,21 +230,21 @@ void QmlMetaProperty::initProperty(QObject *obj, const QString &name) } // Property - QHash<QString, QMetaPropertyEx> &props = qmlCacheProps[obj->metaObject()]; - QHash<QString, QMetaPropertyEx>::ConstIterator iter = props.find(name); + QHash<QString, CachedPropertyData> &props = qmlCacheProps[obj->metaObject()]; + QHash<QString, CachedPropertyData>::ConstIterator iter = props.find(name); if (iter != props.end()) { - d->prop = *iter; - d->propType = iter->propertyType; - d->coreIdx = iter->propertyIndex(); + d->name = iter->name; + d->propType = iter->propType; + d->coreIdx = iter->coreIdx; } else { QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData()); - d->prop = p; + d->name = QLatin1String(p.name()); d->propType = p.propertyType; d->coreIdx = p.propertyIndex(); if (!QObjectPrivate::get(obj)->metaObject) - props.insert(name, p); + props.insert(name, CachedPropertyData(d->name, d->propType, d->coreIdx)); } - if (d->prop.name() != 0) + if (!d->name.isEmpty()) d->type = Property; if (d->type == Invalid) { @@ -352,8 +357,8 @@ QmlMetaProperty::propertyCategory(const QMetaProperty &prop) */ const char *QmlMetaProperty::propertyTypeName() const { - if (d->prop.name()) { - return d->prop.typeName(); + if (!d->name.isEmpty()) { + return d->object->metaObject()->property(d->coreIdx).typeName(); } else { return 0; } @@ -365,7 +370,7 @@ const char *QmlMetaProperty::propertyTypeName() const */ bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const { - return d->prop.name() == other.d->prop.name() && + return d->name == other.d->name && d->signal.signature() == other.d->signal.signature() && d->type == other.d->type && d->object == other.d->object; @@ -384,7 +389,7 @@ int QmlMetaPropertyPrivate::propertyType() const { int rv = QVariant::Invalid; - if (prop.name()) { + if (!name.isEmpty()) { if (propType == (int)QVariant::LastType) rv = qMetaTypeId<QVariant>(); else @@ -434,7 +439,6 @@ QObject *QmlMetaProperty::object() const QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other) { d->name = other.d->name; - d->prop = other.d->prop; d->propType = other.d->propType; d->type = other.d->type; d->signal = other.d->signal; @@ -452,8 +456,8 @@ bool QmlMetaProperty::isWritable() const { if (propertyCategory() == List || propertyCategory() == QmlList) return true; - else if (d->prop.name() != 0) - return d->prop.isWritable(); + else if (!d->name.isEmpty()) + return d->object->metaObject()->property(d->coreIdx).isWritable(); else if (type() & SignalProperty) return true; else @@ -465,8 +469,8 @@ bool QmlMetaProperty::isWritable() const */ bool QmlMetaProperty::isDesignable() const { - if (d->prop.name() != 0) - return d->prop.isDesignable(); + if (!d->name.isEmpty()) + return d->object->metaObject()->property(d->coreIdx).isDesignable(); else return false; } @@ -510,9 +514,9 @@ QString QmlMetaProperty::name() const Returns the \l{QMetaProperty} {Qt property} associated with this QML property. */ -const QMetaProperty &QmlMetaProperty::property() const +QMetaProperty QmlMetaProperty::property() const { - return d->prop; + return d->object->metaObject()->property(d->coreIdx); } /*! @@ -602,7 +606,7 @@ QVariant QmlMetaProperty::read() const if (type() & Attached) return QVariant::fromValue(d->attachedObject()); else - return d->prop.read(object()); + return d->object->metaObject()->property(d->coreIdx).read(object()); } return QVariant(); } @@ -636,6 +640,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) { + QMetaProperty prop = object->metaObject()->property(coreIdx); if (prop.isEnumType()) { QVariant v = value; if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles @@ -805,13 +810,14 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) */ void QmlMetaProperty::write(const QVariant &value) const { + QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); if (type() & SignalProperty) { d->writeSignalProperty(value); - } else if (d->prop.name()) { + } else if (prop.name()) { - if (d->prop.isEnumType()) { + if (prop.isEnumType()) { QVariant v = value; if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles double integral; @@ -819,7 +825,7 @@ void QmlMetaProperty::write(const QVariant &value) const if (qFuzzyCompare(fractional, (double)0.0)) v.convert(QVariant::Int); } - d->prop.write(object(), v); + prop.write(object(), v); } else { if (!value.isValid()) return; @@ -836,13 +842,13 @@ void QmlMetaProperty::write(const QVariant &value) const } else if (qMetaTypeId<QVariant>() == t) { - d->prop.write(object(), value); + prop.write(object(), value); } else if (propertyCategory() == Object) { QObject *o = QmlMetaType::toQObject(value); if (o) - d->prop.write(object(), QmlMetaType::fromObject(o, propertyType())); + prop.write(object(), QmlMetaType::fromObject(o, propertyType())); } else if (propertyCategory() == List) { @@ -850,7 +856,7 @@ void QmlMetaProperty::write(const QVariant &value) const if (value.userType() == qMetaTypeId<QList<QObject *> >()) { const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value); - QVariant listVar = d->prop.read(object()); + QVariant listVar = prop.read(object()); QmlMetaType::clear(listVar); for (int ii = 0; ii < list.count(); ++ii) { QVariant v = QmlMetaType::fromObject(list.at(ii), listType); @@ -859,14 +865,14 @@ void QmlMetaProperty::write(const QVariant &value) const } else if (vt == listType || value.userType() == listType) { - QVariant listVar = d->prop.read(object()); + QVariant listVar = prop.read(object()); if (!QmlMetaType::append(listVar, value)) { qWarning() << "QmlMetaProperty: Unable to assign object to list"; } } } else if (propertyCategory() == QmlList) { // XXX - optimize! - QVariant list = d->prop.read(object()); + QVariant list = prop.read(object()); QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)list.constData(); @@ -969,7 +975,7 @@ void QmlMetaProperty::write(const QVariant &value) const default: break; } - d->prop.write(object(), value); + prop.write(object(), value); } } @@ -982,7 +988,7 @@ void QmlMetaProperty::write(const QVariant &value) const bool QmlMetaProperty::hasChangedNotifier() const { if (type() & Property && !(type() & Attached)) { - return d->prop.hasNotifySignal(); + return d->object->metaObject()->property(d->coreIdx).hasNotifySignal(); } return false; } @@ -1012,8 +1018,9 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const if (!(type() & Property) || type() & Attached) return false; - if (d->prop.hasNotifySignal()) { - return QMetaObject::connect(d->object, d->prop.notifySignalIndex(), dest, method, Qt::DirectConnection); + QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); + if (prop.hasNotifySignal()) { + return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection); } else { return false; } @@ -1032,8 +1039,9 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const if (!(type() & Property) || type() & Attached) return false; - if (d->prop.hasNotifySignal()) { - QByteArray signal(QByteArray("2") + d->prop.notifySignal().signature()); + QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); + if (prop.hasNotifySignal()) { + QByteArray signal(QByteArray("2") + prop.notifySignal().signature()); return QObject::connect(d->object, signal.constData(), dest, slot); } else { return false; @@ -1098,7 +1106,7 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj) d->attachedFunc = id; } else if (d->type & Property) { QMetaPropertyEx p(obj->metaObject()->property(id)); - d->prop = p; + d->name = QLatin1String(p.name()); d->propType = p.propertyType; d->coreIdx = id; } else if (d->type & SignalProperty || d->type & Signal) { diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 68b06e5..9daef59 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -43,7 +43,7 @@ #define QMLMETAPROPERTY_H #include <QtDeclarative/qfxglobal.h> -#include <QMetaProperty> +#include <QtCore/QMetaProperty> QT_BEGIN_HEADER @@ -121,7 +121,7 @@ public: bool operator==(const QmlMetaProperty &) const; - const QMetaProperty &property() const; + QMetaProperty property() const; QmlBindableValue *binding(); static int findSignal(const QObject *, const char *); diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 1ea38e9..738bfec 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -54,7 +54,7 @@ public: QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other) : name(other.name), signal(other.signal), context(other.context), coreIdx(other.coreIdx), type(other.type), attachedFunc(other.attachedFunc), - object(other.object), prop(other.prop), propType(other.propType), + object(other.object), propType(other.propType), category(other.category) {} QString name; @@ -64,7 +64,6 @@ public: uint type; int attachedFunc; QObject *object; - QMetaProperty prop; int propType; mutable QmlMetaProperty::PropertyCategory category; diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 7825e5c..2e490a4 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -95,8 +95,8 @@ struct QmlMetaTypeData QBitArray qmllists; QBitArray lists; }; -Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData); -Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock); +Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData) +Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) class QmlTypePrivate { @@ -388,7 +388,8 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, data->idToType.insert(type->typeId(), type); data->idToType.insert(type->qListTypeId(), type); data->idToType.insert(type->qmlListTypeId(), type); - data->nameToType.insert(type->qmlTypeName(), type); + if (!type->qmlTypeName().isEmpty()) + data->nameToType.insert(type->qmlTypeName(), type); if (data->interfaces.size() < id.typeId) data->interfaces.resize(id.typeId + 16); @@ -864,6 +865,14 @@ QmlType *QmlMetaType::qmlType(const QByteArray &name) return data->nameToType.value(name); } +QmlType *QmlMetaType::qmlType(const QMetaObject *metaObject) +{ + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + + return data->metaObjectToType.value(metaObject); +} + QList<QByteArray> QmlMetaType::qmlTypeNames() { QReadLocker lock(metaTypeDataLock()); diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 7ab01a5..cc3887c 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -64,9 +64,11 @@ public: static bool copy(int type, void *data, const void *copy = 0); - static QmlType *qmlType(const QByteArray &); static QList<QByteArray> qmlTypeNames(); + static QmlType *qmlType(const QByteArray &); + static QmlType *qmlType(const QMetaObject *); + static QMetaProperty defaultProperty(const QMetaObject *); static QMetaProperty defaultProperty(QObject *); static QMetaMethod defaultMethod(const QMetaObject *); @@ -108,7 +110,7 @@ public: }; class QmlTypePrivate; -class QmlType +class Q_DECLARATIVE_EXPORT QmlType { public: QByteArray typeName() const; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index d4f279b..add5773 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -42,10 +42,10 @@ #ifndef QMLPARSER_P_H #define QMLPARSER_P_H -#include <QByteArray> -#include <QList> +#include <QtCore/QByteArray> +#include <QtCore/QList> #include <QtCore/qstring.h> -#include <qml.h> +#include <QtDeclarative/qml.h> #include <private/qmlrefcount_p.h> #include <private/qobject_p.h> @@ -272,10 +272,10 @@ namespace QmlParser void dump(int = 0) const; }; } - -#endif // QMLPARSER_P_H - +Q_DECLARE_METATYPE(QmlParser::Variant); QT_END_NAMESPACE QT_END_HEADER + +#endif // QMLPARSER_P_H diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h index 6ef2e38..736b25f 100644 --- a/src/declarative/qml/qmlpropertyvaluesource.h +++ b/src/declarative/qml/qmlpropertyvaluesource.h @@ -42,9 +42,9 @@ #ifndef QMLPROPERTYVALUESOURCE_H #define QMLPROPERTYVALUESOURCE_H -#include <qfxglobal.h> -#include <qml.h> -#include <QObject> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> +#include <QtCore/QObject> QT_BEGIN_HEADER diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h index 594e7a3..0ffa365 100644 --- a/src/declarative/qml/qmlproxymetaobject_p.h +++ b/src/declarative/qml/qmlproxymetaobject_p.h @@ -42,11 +42,11 @@ #ifndef QMLPROXYMETAOBJECT_P_H #define QMLPROXYMETAOBJECT_P_H -#include <QMetaObject> +#include <QtCore/QMetaObject> +#include <QtCore/QObject> #include <private/qmetaobjectbuilder_p.h> #include <private/qobject_p.h> -#include <QObject> -#include <qml.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h index 90b50a8..1355c86 100644 --- a/src/declarative/qml/qmlrefcount_p.h +++ b/src/declarative/qml/qmlrefcount_p.h @@ -42,7 +42,7 @@ #ifndef QMLREFCOUNT_P_H #define QMLREFCOUNT_P_H -#include <qglobal.h> +#include <QtCore/qglobal.h> QT_BEGIN_HEADER diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index ff19d25..ead7ee5 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -62,18 +62,16 @@ public: void operator()(const QString &code, AST::Node *node); protected: - Object *defineObjectBinding(int line, - AST::UiQualifiedId *propertyName, - const QString &objectType, - AST::SourceLocation typeLocation, - LocationSpan location, - AST::UiObjectInitializer *initializer = 0); - Object *defineObjectBinding_helper(int line, - AST::UiQualifiedId *propertyName, - const QString &objectType, - AST::SourceLocation typeLocation, - LocationSpan location, - AST::UiObjectInitializer *initializer = 0); + Object *defineObjectBinding(AST::UiQualifiedId *propertyName, + AST::UiQualifiedId *objectTypeName, + LocationSpan location, + AST::UiObjectInitializer *initializer = 0); + + Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName, + const QString &objectType, + AST::SourceLocation typeLocation, + LocationSpan location, + AST::UiObjectInitializer *initializer = 0); QmlParser::Variant getVariant(AST::ExpressionNode *expr); @@ -199,8 +197,7 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const } Object * -ProcessAST::defineObjectBinding_helper(int line, - AST::UiQualifiedId *propertyName, +ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, const QString &objectType, AST::SourceLocation typeLocation, LocationSpan location, @@ -283,16 +280,17 @@ ProcessAST::defineObjectBinding_helper(int line, } } -Object *ProcessAST::defineObjectBinding(int line, - AST::UiQualifiedId *qualifiedId, - const QString &objectType, - AST::SourceLocation typeLocation, - LocationSpan location, - AST::UiObjectInitializer *initializer) +Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId, + AST::UiQualifiedId *objectTypeName, + LocationSpan location, + AST::UiObjectInitializer *initializer) { + const QString objectType = asString(objectTypeName); + const AST::SourceLocation typeLocation = objectTypeName->identifierToken; + if (objectType == QLatin1String("Connection")) { - Object *obj = defineObjectBinding_helper(line, 0, objectType, typeLocation, location); + Object *obj = defineObjectBinding_helper(/*propertyName = */0, objectType, typeLocation, location); _stateStack.pushObject(obj); @@ -331,7 +329,7 @@ Object *ProcessAST::defineObjectBinding(int line, return obj; } - return defineObjectBinding_helper(line, qualifiedId, objectType, typeLocation, location, initializer); + return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer); } LocationSpan ProcessAST::location(AST::UiQualifiedId *id) @@ -446,16 +444,14 @@ bool ProcessAST::visit(AST::UiPublicMember *node) } -// UiObjectMember: T_IDENTIFIER UiObjectInitializer ; +// UiObjectMember: UiQualifiedId UiObjectInitializer ; bool ProcessAST::visit(AST::UiObjectDefinition *node) { LocationSpan l = location(node->firstSourceLocation(), - node->lastSourceLocation());; + node->lastSourceLocation()); - defineObjectBinding(node->identifierToken.startLine, - 0, - node->name->asString(), - node->identifierToken, + defineObjectBinding(/*propertyName = */ 0, + node->qualifiedTypeNameId, l, node->initializer); @@ -463,16 +459,14 @@ bool ProcessAST::visit(AST::UiObjectDefinition *node) } -// UiObjectMember: UiQualifiedId T_COLON T_IDENTIFIER UiObjectInitializer ; +// UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; bool ProcessAST::visit(AST::UiObjectBinding *node) { - LocationSpan l; - l = location(node->identifierToken, node->initializer->rbraceToken); + LocationSpan l = location(node->qualifiedTypeNameId->identifierToken, + node->initializer->rbraceToken); - defineObjectBinding(node->identifierToken.startLine, - node->qualifiedId, - node->name->asString(), - node->identifierToken, + defineObjectBinding(node->qualifiedId, + node->qualifiedTypeNameId, l, node->initializer); @@ -632,20 +626,19 @@ bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url) QTextStream stream(data, QIODevice::ReadOnly); const QString code = stream.readAll(); - JavaScriptParser parser; - JavaScriptEnginePrivate driver; + Engine engine; - NodePool nodePool(fileName, &driver); - driver.setNodePool(&nodePool); + NodePool nodePool(fileName, &engine); - Lexer lexer(&driver); + Lexer lexer(&engine); lexer.setCode(code, /*line = */ 1); - driver.setLexer(&lexer); - if (! parser.parse(&driver) || !_errors.isEmpty()) { + Parser parser(&engine); + + if (! parser.parse() || !_errors.isEmpty()) { // Extract errors from the parser - foreach (const JavaScriptParser::DiagnosticMessage &m, parser.diagnosticMessages()) { + foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) { if (m.isWarning()) continue; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 51534e7..1552cb5 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -87,10 +87,7 @@ Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) { Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList); - Q_DECLARE_PERFORMANCE_METRIC(InstrAssignConstant); Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject); - Q_DECLARE_PERFORMANCE_METRIC(InstrAssignBinding); - Q_DECLARE_PERFORMANCE_METRIC(InstrAssignCompiledBinding); Q_DECLARE_PERFORMANCE_METRIC(InstrAssignValueSource); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding); Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding); @@ -136,10 +133,7 @@ Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") { Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList"); - Q_DEFINE_PERFORMANCE_METRIC(InstrAssignConstant, "AssignConstant"); Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject"); - Q_DEFINE_PERFORMANCE_METRIC(InstrAssignBinding, "AssignBinding"); - Q_DEFINE_PERFORMANCE_METRIC(InstrAssignCompiledBinding, "AssignCompiledBinding"); Q_DEFINE_PERFORMANCE_METRIC(InstrAssignValueSource, "AssignValueSource"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding"); Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding"); @@ -409,64 +403,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in } break; - case QmlInstruction::AssignConstant: - { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer<QFxCompiler::InstrAssignConstant> cc; -#endif - // Fixup instruction - QObject *target = stack.top(); - int propIdx = instr.assignConstant.property; - int idx = instr.assignConstant.constant; - QByteArray pr; - if (propIdx == -1) { - pr = QmlMetaType::defaultProperty(target).name(); - if (pr.isEmpty()) - VME_EXCEPTION("Cannot resolve defalt property on type" << target->metaObject()->className()); - } else { - pr = datas.at(propIdx); - } - - int coreIdx = qIndexOfProperty(target, pr); - - if (coreIdx != -1) { - QMetaProperty prop = - target->metaObject()->property(coreIdx); - bool replace = !prop.isDynamic(); - - QmlInstruction *writeInstr = 0; - QmlInstruction dummy; - if (replace) { - writeInstr = &instr; - } else { - writeInstr = &dummy; - dummy = instr; - } - - QmlCompiler::StoreInstructionResult r = QmlCompiler::generateStoreInstruction(*comp, *writeInstr, prop, - coreIdx, idx, &primitives.at(idx)); - if (r != QmlCompiler::Ok) { - if (prop.isEnumType()){ - VME_EXCEPTION(primitives.at(idx) << "is not a valid enumeration value"); - } else if (r == QmlCompiler::UnknownType) { - VME_EXCEPTION("Property" << prop.name() << "is of an unknown type"); - } else if (r == QmlCompiler::InvalidData) { - VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to property" << prop.name()); - } else if (r == QmlCompiler::ReadOnly) { - VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to read-only property" << prop.name()); - } else { - VME_EXCEPTION("Invalid property assignment for property" << prop.name()); - } - } else { - runStoreInstruction(stack, *writeInstr, comp); - } - - } else { - VME_EXCEPTION("Unknown property" << pr); - } - } - break; - case QmlInstruction::TryBeginObject: { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -530,31 +466,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in } break; - case QmlInstruction::AssignCompiledBinding: - case QmlInstruction::AssignBinding: - { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer<QFxCompiler::InstrAssignBinding> cc; -#endif - QObject *target = stack.top(); - const QByteArray &pr = datas.at(instr.fetch.property); - int idx = qIndexOfProperty(target, pr); - - // XXX - need to check if the type is QmlBindableValue* - if (idx == -1) { - VME_EXCEPTION("Unknown property" << pr); - } else { - if (QmlInstruction::AssignCompiledBinding == instr.type) - instr.type = QmlInstruction::StoreCompiledBinding; - else - instr.type = QmlInstruction::StoreBinding; - instr.assignBinding.property = idx; - instr.assignBinding.category = QmlMetaProperty::Unknown; - } - ii--; - } - break; - case QmlInstruction::AssignValueSource: { QObject *target = stack.at(stack.count() - 2); @@ -613,6 +524,7 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in QFx_setParent_noEvent(bind, target); bind->setTarget(mp); + bind->setSourceLocation(comp->url.toString(), instr.line); } break; @@ -638,6 +550,7 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in QFx_setParent_noEvent(bind, target); bind->setTarget(mp); + bind->setSourceLocation(comp->url.toString(), instr.line); } break; diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h index f7e13d6..4e5c6c1 100644 --- a/src/declarative/qml/qmlvme_p.h +++ b/src/declarative/qml/qmlvme_p.h @@ -42,12 +42,12 @@ #ifndef QMLVME_P_H #define QMLVME_P_H -#include <QString> -#include <QStack> -#include <qmlerror.h> -class QObject; +#include <QtCore/QString> +#include <QtCore/QStack> +#include <QtDeclarative/qmlerror.h> QT_BEGIN_NAMESPACE +class QObject; class QmlInstruction; class QmlCompiledComponent; class QmlCompiledData; diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index d8ed242..6f1e31b 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -42,9 +42,9 @@ #ifndef QMLVMEMETAOBJECT_P_H #define QMLVMEMETAOBJECT_P_H -#include <qml.h> -#include <QMetaObject> -#include <QBitArray> +#include <QtDeclarative/qml.h> +#include <QtCore/QMetaObject> +#include <QtCore/QBitArray> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/script/lexer.h b/src/declarative/qml/script/lexer.h index 7781ee8..9de4afd 100644 --- a/src/declarative/qml/script/lexer.h +++ b/src/declarative/qml/script/lexer.h @@ -11,7 +11,7 @@ #ifndef LEXER_H #define LEXER_H -#include <QList> +#include <QtCore/QList> #include "tokens.h" diff --git a/src/declarative/qml/script/qmlbasicscript.h b/src/declarative/qml/script/qmlbasicscript.h index d465f04..5ef2148 100644 --- a/src/declarative/qml/script/qmlbasicscript.h +++ b/src/declarative/qml/script/qmlbasicscript.h @@ -13,10 +13,10 @@ #define QMLBASICSCRIPT_H #include "instructions.h" -#include <QList> -#include <QByteArray> +#include <QtCore/QList> +#include <QtCore/QByteArray> #include "lexer.h" -#include <QVariant> +#include <QtCore/QVariant> QT_BEGIN_HEADER diff --git a/src/declarative/test/qfxtestengine.h b/src/declarative/test/qfxtestengine.h index 6698645..44a140f 100644 --- a/src/declarative/test/qfxtestengine.h +++ b/src/declarative/test/qfxtestengine.h @@ -42,8 +42,7 @@ #ifndef _QFXTESTENGINE_H_ #define _QFXTESTENGINE_H_ -#include <QObject> -class QSimpleCanvas; +#include <QtCore/QObject> QT_BEGIN_HEADER @@ -51,6 +50,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QSimpleCanvas; class QFxTestEnginePrivate; class Q_DECLARATIVE_EXPORT QFxTestEngine : public QObject { diff --git a/src/declarative/test/qfxtestobjects.h b/src/declarative/test/qfxtestobjects.h index 4273d4e..653656e 100644 --- a/src/declarative/test/qfxtestobjects.h +++ b/src/declarative/test/qfxtestobjects.h @@ -42,10 +42,10 @@ #ifndef _QFXTESTOBJECTS_H_ #define _QFXTESTOBJECTS_H_ -#include <QObject> -#include <QPoint> -#include <QList> -#include <QXmlStreamWriter> +#include <QtCore/QObject> +#include <QtCore/QPoint> +#include <QtCore/QList> +#include <QtCore/QXmlStreamWriter> QT_BEGIN_HEADER diff --git a/src/declarative/test/qfxtestview.h b/src/declarative/test/qfxtestview.h index 33275b9..a8f78bf 100644 --- a/src/declarative/test/qfxtestview.h +++ b/src/declarative/test/qfxtestview.h @@ -42,7 +42,7 @@ #ifndef _QFXTESTVIEW_H_ #define _QFXTESTVIEW_H_ -#include <QFxView> +#include <QtDeclarative/QFxView> QT_BEGIN_HEADER diff --git a/src/declarative/timeline/qmltimeline.h b/src/declarative/timeline/qmltimeline.h index ce9d1f2..23bdd64 100644 --- a/src/declarative/timeline/qmltimeline.h +++ b/src/declarative/timeline/qmltimeline.h @@ -42,9 +42,9 @@ #ifndef QMLTIMELINE_H #define QMLTIMELINE_H -#include <QObject> -#include <qfxglobal.h> -#include <QAbstractAnimation> +#include <QtCore/QObject> +#include <QtCore/QAbstractAnimation> +#include <QtDeclarative/qfxglobal.h> QT_BEGIN_HEADER diff --git a/src/declarative/timeline/qmltimelinevalueproxy.h b/src/declarative/timeline/qmltimelinevalueproxy.h index 853db4e..9ecdba1 100644 --- a/src/declarative/timeline/qmltimelinevalueproxy.h +++ b/src/declarative/timeline/qmltimelinevalueproxy.h @@ -42,7 +42,7 @@ #ifndef QMLTIMELINEVALUEPROXY_H #define QMLTIMELINEVALUEPROXY_H -#include "qmltimeline.h" +#include <QtDeclarative/qmltimeline.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qbindablemap.h b/src/declarative/util/qbindablemap.h index d617867..c76928d 100644 --- a/src/declarative/util/qbindablemap.h +++ b/src/declarative/util/qbindablemap.h @@ -42,11 +42,11 @@ #ifndef QBINDABLEMAP_H #define QBINDABLEMAP_H -#include <qfxglobal.h> -#include <QObject> -#include <QHash> -#include <QStringList> -#include <QVariant> +#include <QtDeclarative/qfxglobal.h> +#include <QtCore/QObject> +#include <QtCore/QHash> +#include <QtCore/QStringList> +#include <QtCore/QVariant> QT_BEGIN_HEADER diff --git a/src/declarative/util/qfxglobal.h b/src/declarative/util/qfxglobal.h index 887351d..6ba9409 100644 --- a/src/declarative/util/qfxglobal.h +++ b/src/declarative/util/qfxglobal.h @@ -42,8 +42,8 @@ #ifndef QFXGLOBAL_H #define QFXGLOBAL_H -#include <qglobal.h> -#include <QObject> +#include <QtCore/qglobal.h> +#include <QtCore/QObject> QT_BEGIN_HEADER diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index 1c24e28..0d5b796 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -93,7 +93,7 @@ class QFxViewPrivate { public: QFxViewPrivate(QFxView *w) - : q(w), root(0), component(0) {} + : q(w), root(0), component(0), resizable(false) {} QFxView *q; QFxItem *root; @@ -106,6 +106,7 @@ public: QBasicTimer resizetimer; QSize initialSize; + bool resizable; void init(); }; @@ -344,7 +345,18 @@ void QFxView::continueExecute() d->root = item; connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged())); connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged())); - emit sceneResized(QSize(d->root->width(),d->root->height())); + if (d->initialSize.height() <= 0 && d->root->width() > 0) + d->initialSize.setWidth(d->root->width()); + if (d->initialSize.height() <= 0 && d->root->height() > 0) + d->initialSize.setHeight(d->root->height()); + if (d->resizable) { + d->root->setWidth(width()); + d->root->setHeight(height()); + } else { + QSize sz(d->root->width(),d->root->height()); + emit sceneResized(sz); + resize(sz); + } } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) { window()->setAttribute(Qt::WA_OpaquePaintEvent, false); window()->setAttribute(Qt::WA_NoSystemBackground, false); @@ -381,14 +393,55 @@ void QFxView::sizeChanged() */ void QFxView::timerEvent(QTimerEvent* e) { - if (e->timerId() == d->resizetimer.timerId()) { - if (d->root) - emit sceneResized(QSize(d->root->width(),d->root->height())); + if (!e || e->timerId() == d->resizetimer.timerId()) { + if (d->root) { + QSize sz(d->root->width(),d->root->height()); + emit sceneResized(sz); + //if (!d->resizable) + //resize(sz); + } d->resizetimer.stop(); updateGeometry(); } } +// modelled on QScrollArea::widgetResizable +/*! + \property QFxView::contentResizable + \brief whether the view should resize the canvas contents + + If this property is set to false (the default), the view + resizes with the root item in the QML. + + If this property is set to true, the view will + automatically resize the root item. + + Regardless of this property, the sizeHint of the view + is the initial size of the root item. +*/ + +void QFxView::setContentResizable(bool on) +{ + if (d->resizable != on) { + d->resizable = on; + if (d->root) { + if (on) { + d->root->setWidth(width()); + d->root->setHeight(height()); + } else { + d->root->setWidth(d->initialSize.width()); + d->root->setHeight(d->initialSize.height()); + } + } + } +} + +bool QFxView::contentResizable() const +{ + return d->resizable; +} + + /*! The size hint is the size of the root item. */ @@ -481,7 +534,7 @@ QFxItem *QFxView::root() const */ void QFxView::resizeEvent(QResizeEvent *e) { - if (d->root) { + if (d->resizable && d->root) { d->root->setWidth(width()); d->root->setHeight(height()); } diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h index d6f786c..05bf005 100644 --- a/src/declarative/util/qfxview.h +++ b/src/declarative/util/qfxview.h @@ -42,11 +42,11 @@ #ifndef QFXVIEW_H #define QFXVIEW_H -#include <qfxglobal.h> #include <QtCore/qdatetime.h> #include <QtGui/qgraphicssceneevent.h> #include <QtGui/qwidget.h> -#include <qsimplecanvas.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qsimplecanvas.h> QT_BEGIN_HEADER @@ -82,6 +82,8 @@ public: virtual QFxItem *root() const; + void setContentResizable(bool); + bool contentResizable() const; QSize sizeHint() const; void dumpRoot(); diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index dd4e1eb..24bcac98 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -243,8 +243,12 @@ void QmlAbstractAnimation::setRunning(bool r) d->startOnCompletion = true; emit started(); } else { - if (!d->finishPlaying) + if (d->finishPlaying) { + if (d->repeat) + qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); + } else qtAnimation()->stop(); + emit completed(); } @@ -512,7 +516,11 @@ void QmlAbstractAnimation::transition(QmlStateActions &actions, void QmlAbstractAnimation::timelineComplete() { + Q_D(QmlAbstractAnimation); setRunning(false); + if (d->finishPlaying && d->repeat) { + qtAnimation()->setLoopCount(-1); + } } /*! diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h index 578631c..8bd53e2 100644 --- a/src/declarative/util/qmlanimation.h +++ b/src/declarative/util/qmlanimation.h @@ -43,12 +43,12 @@ #define QMLANIMATION_H #include <QtCore/qvariant.h> +#include <QtCore/QAbstractAnimation> #include <QtGui/qcolor.h> -#include <qmltransition.h> -#include <qmlpropertyvaluesource.h> -#include <qmlstate.h> -#include <qml.h> -#include <QAbstractAnimation> +#include <QtDeclarative/qmltransition.h> +#include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qmlstate.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h index 00937a6..36b826f 100644 --- a/src/declarative/util/qmlanimation_p.h +++ b/src/declarative/util/qmlanimation_p.h @@ -44,15 +44,15 @@ #include <private/qobject_p.h> #include <private/qmlnullablevalue_p.h> -#include <qmlanimation.h> -#include <qml.h> -#include <qmlcontext.h> #include <private/qvariantanimation_p.h> -#include <QPauseAnimation> -#include <QVariantAnimation> -#include <QAnimationGroup> -#include <QColor> -#include <qmltimelinevalueproxy.h> +#include <QtCore/QPauseAnimation> +#include <QtCore/QVariantAnimation> +#include <QtCore/QAnimationGroup> +#include <QtGui/QColor> +#include <QtDeclarative/qmlanimation.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmltimelinevalueproxy.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/util/qmlbehaviour.h b/src/declarative/util/qmlbehaviour.h index 3d25cd8..7a54d63 100644 --- a/src/declarative/util/qmlbehaviour.h +++ b/src/declarative/util/qmlbehaviour.h @@ -42,9 +42,9 @@ #ifndef QMLBEHAVIOUR_H #define QMLBEHAVIOUR_H -#include <qmlpropertyvaluesource.h> -#include <qml.h> -#include <qmlstate.h> +#include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qmlstate.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlbind.h b/src/declarative/util/qmlbind.h index 355edfd..5576957 100644 --- a/src/declarative/util/qmlbind.h +++ b/src/declarative/util/qmlbind.h @@ -42,9 +42,9 @@ #ifndef QMLBIND_H #define QMLBIND_H -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> #include <QtCore/qobject.h> -#include "qml.h" +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h index bd9363a..fa0bff8 100644 --- a/src/declarative/util/qmlfollow.h +++ b/src/declarative/util/qmlfollow.h @@ -42,8 +42,8 @@ #ifndef QMLFOLLOW_H #define QMLFOLLOW_H -#include <qmlpropertyvaluesource.h> -#include <qml.h> +#include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlfont.h b/src/declarative/util/qmlfont.h index b6bce7c..3a21c34 100644 --- a/src/declarative/util/qmlfont.h +++ b/src/declarative/util/qmlfont.h @@ -43,7 +43,7 @@ #define QMLFONT_H #include <QtCore/qobject.h> -#include <qml.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmllistaccessor.h b/src/declarative/util/qmllistaccessor.h index 29f910d..dd766b2 100644 --- a/src/declarative/util/qmllistaccessor.h +++ b/src/declarative/util/qmllistaccessor.h @@ -42,7 +42,7 @@ #ifndef QMLLISTACCESSOR_H #define QMLLISTACCESSOR_H -#include <QVariant> +#include <QtCore/QVariant> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 8184bda..80eb9c3 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -43,6 +43,7 @@ #include <QtCore/qstack.h> #include <QXmlStreamReader> #include <private/qmlcustomparser_p.h> +#include <private/qmlparser_p.h> #include "qmlopenmetaobject.h" #include <qmlcontext.h> #include <qmlbindablevalue.h> @@ -414,8 +415,11 @@ bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList } else { + QmlParser::Variant variant = + qvariant_cast<QmlParser::Variant>(value); + int ref = data.count(); - QByteArray d = value.toString().toLatin1(); + QByteArray d = variant.asScript().toLatin1(); d.append('\0'); data.append(d); diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h index 36aa009..ddf1e13 100644 --- a/src/declarative/util/qmllistmodel.h +++ b/src/declarative/util/qmllistmodel.h @@ -42,14 +42,14 @@ #ifndef QMLLISTMODEL_H #define QMLLISTMODEL_H -#include <QObject> -#include <qfxglobal.h> -#include <QStringList> -#include <QHash> -#include <QList> -#include <QVariant> -#include <qml.h> -#include <qlistmodelinterface.h> +#include <QtCore/QObject> +#include <QtCore/QStringList> +#include <QtCore/QHash> +#include <QtCore/QList> +#include <QtCore/QVariant> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> +#include <QtDeclarative/qlistmodelinterface.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h index f842f96..239276d 100644 --- a/src/declarative/util/qmlopenmetaobject.h +++ b/src/declarative/util/qmlopenmetaobject.h @@ -42,9 +42,9 @@ #ifndef QMLOPENMETAOBJECT_H #define QMLOPENMETAOBJECT_H -#include <QMetaObject> +#include <QtCore/QMetaObject> #include <QtCore/private/qobject_p.h> -#include <QObject> +#include <QtCore/QObject> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlpackage.h b/src/declarative/util/qmlpackage.h index 6652b98..3861890 100644 --- a/src/declarative/util/qmlpackage.h +++ b/src/declarative/util/qmlpackage.h @@ -42,7 +42,7 @@ #ifndef QMLPACKAGE_H #define QMLPACKAGE_H -#include <qml.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h index 8047a88..b739fd7 100644 --- a/src/declarative/util/qmlscript.h +++ b/src/declarative/util/qmlscript.h @@ -42,9 +42,9 @@ #ifndef QMLSCRIPT_H #define QMLSCRIPT_H -#include <qfxglobal.h> +#include <QtDeclarative/qfxglobal.h> #include <QtCore/qobject.h> -#include "qml.h" +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index 9b5a58e..c986864 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -44,61 +44,12 @@ #include "qmlsetproperties.h" #include <QtCore/qdebug.h> #include <QtDeclarative/qmlinfo.h> +#include <private/qmlcustomparser_p.h> +#include <private/qmlparser_p.h> +#include <QtDeclarative/qmlexpression.h> QT_BEGIN_NAMESPACE -class QmlSetPropertiesMetaObject : public QmlOpenMetaObject -{ -public: - QmlSetPropertiesMetaObject(QObject *); - -protected: - virtual void propertyRead(int); - virtual void propertyWrite(int); -}; - -class QmlSetPropertiesProxyObject : public QObject -{ -Q_OBJECT -public: - QmlSetPropertiesProxyObject(QObject *); - - QmlSetPropertiesMetaObject *fxMetaObject() const { return _mo; } -private: - QmlSetPropertiesMetaObject *_mo; -}; - -QmlSetPropertiesProxyObject::QmlSetPropertiesProxyObject(QObject *parent) -: QObject(parent), _mo(new QmlSetPropertiesMetaObject(this)) -{ -} - -QmlSetPropertiesMetaObject::QmlSetPropertiesMetaObject(QObject *obj) -: QmlOpenMetaObject(obj) -{ -} - -void QmlSetPropertiesMetaObject::propertyRead(int id) -{ - if (!value(id).isValid()) - setValue(id, QVariant::fromValue((QObject *)new QmlSetPropertiesProxyObject(object()))); - - QmlOpenMetaObject::propertyRead(id); -} - -void QmlSetPropertiesMetaObject::propertyWrite(int id) -{ - if (value(id).userType() == qMetaTypeId<QObject *>()) { - QObject *val = qvariant_cast<QObject *>(value(id)); - QmlSetPropertiesProxyObject *proxy = qobject_cast<QmlSetPropertiesProxyObject *>(val); - if (proxy) { - setValue(id, QVariant()); - delete proxy; - } - } - QmlOpenMetaObject::propertyWrite(id); -} - /*! \qmlclass SetProperties QmlSetProperties \brief The SetProperties element describes new property values for a state. @@ -149,109 +100,263 @@ void QmlSetPropertiesMetaObject::propertyWrite(int id) \sa QmlSetProperty */ +/*! + \qmlproperty Object SetProperties::target + This property holds the object that the properties to change belong to +*/ + +/*! + \property QmlSetProperties::target + \brief the object that the properties to change belong to +*/ class QmlSetPropertiesPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlSetProperties) public: - QmlSetPropertiesPrivate() : obj(0), mo(0) {} + QmlSetPropertiesPrivate() : object(0), decoded(true), restore(true) {} + + QObject *object; + QByteArray data; + bool decoded; + void decode(); + + bool restore; - QObject *obj; - QmlSetPropertiesMetaObject *mo; + QList<QPair<QByteArray, QVariant> > properties; + QList<QPair<QByteArray, QmlExpression *> > expressions; + + QmlMetaProperty property(const QByteArray &); }; -QML_DEFINE_TYPE(QmlSetProperties,SetProperties); -QmlSetProperties::QmlSetProperties() - : QmlStateOperation(*(new QmlSetPropertiesPrivate)) +class QmlSetPropertiesParser : public QmlCustomParser { - Q_D(QmlSetProperties); - d->mo = new QmlSetPropertiesMetaObject(this); +public: + void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QmlCustomParserProperty &prop); + + virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok); + virtual void setCustomData(QObject *, const QByteArray &); +}; + +void +QmlSetPropertiesParser::compileList(QList<QPair<QByteArray, QVariant> > &list, + const QByteArray &pre, + const QmlCustomParserProperty &prop) +{ + QByteArray propName = pre + prop.name(); + + QList<QVariant> values = prop.assignedValues(); + for (int ii = 0; ii < values.count(); ++ii) { + const QVariant &value = values.at(ii); + + if (value.userType() == qMetaTypeId<QmlCustomParserNode>()) { + continue; + } else if(value.userType() == qMetaTypeId<QmlCustomParserProperty>()) { + + QmlCustomParserProperty prop = + qvariant_cast<QmlCustomParserProperty>(value); + QByteArray pre = propName + "."; + compileList(list, pre, prop); + + } else { + list << qMakePair(propName, value); + } + } } -QmlSetProperties::QmlSetProperties(QObject *parent) - : QmlStateOperation(*(new QmlSetPropertiesPrivate), parent) +QByteArray +QmlSetPropertiesParser::compile(const QList<QmlCustomParserProperty> &props, + bool *ok) { - Q_D(QmlSetProperties); - d->mo = new QmlSetPropertiesMetaObject(this); + *ok = true; + + QList<QPair<QByteArray, QVariant> > data; + for(int ii = 0; ii < props.count(); ++ii) + compileList(data, QByteArray(), props.at(ii)); + + QByteArray rv; + QDataStream ds(&rv, QIODevice::WriteOnly); + + ds << data.count(); + for(int ii = 0; ii < data.count(); ++ii) { + QmlParser::Variant v = qvariant_cast<QmlParser::Variant>(data.at(ii).second); + QVariant var; + bool isScript = v.isScript(); + switch(v.type()) { + case QmlParser::Variant::Boolean: + var = QVariant(v.asBoolean()); + break; + case QmlParser::Variant::Number: + var = QVariant(v.asNumber()); + break; + case QmlParser::Variant::String: + var = QVariant(v.asString()); + break; + case QmlParser::Variant::Invalid: + case QmlParser::Variant::Script: + var = QVariant(v.asScript()); + break; + } + + ds << data.at(ii).first << isScript << var; + } + + return rv; } -QmlSetProperties::~QmlSetProperties() +void QmlSetPropertiesPrivate::decode() { + if (decoded) + return; + + QDataStream ds(&data, QIODevice::ReadOnly); + + int count; + ds >> count; + for (int ii = 0; ii < count; ++ii) { + QByteArray name; + bool isScript; + QVariant data; + ds >> name; + ds >> isScript; + ds >> data; + + if (isScript) { + QmlExpression *expression = new QmlExpression(qmlContext(object), data.toString(), object); + expression->setTrackChange(false); + expressions << qMakePair(name, expression); + } else { + properties << qMakePair(name, data); + } + } + + decoded = true; + data.clear(); } -/*! - \qmlproperty Object SetProperties::target - This property holds the object that the properties to change belong to -*/ +void QmlSetPropertiesParser::setCustomData(QObject *object, + const QByteArray &data) +{ + QmlSetPropertiesPrivate *p = + static_cast<QmlSetPropertiesPrivate *>(QObjectPrivate::get(object)); + p->data = data; + p->decoded = false; +} -/*! - \property QmlSetProperties::target - \brief the object that the properties to change belong to -*/ -QObject *QmlSetProperties::object() +QmlSetProperties::QmlSetProperties() +: QmlStateOperation(*(new QmlSetPropertiesPrivate)) +{ +} + +QmlSetProperties::~QmlSetProperties() { Q_D(QmlSetProperties); - return d->obj; + for(int ii = 0; ii < d->expressions.count(); ++ii) + delete d->expressions.at(ii).second; +} + +QObject *QmlSetProperties::object() const +{ + Q_D(const QmlSetProperties); + return d->object; } void QmlSetProperties::setObject(QObject *o) { Q_D(QmlSetProperties); - d->obj = o; + d->object = o; +} + +bool QmlSetProperties::restoreEntryValues() const +{ + Q_D(const QmlSetProperties); + return d->restore; +} + +void QmlSetProperties::setRestoreEntryValues(bool v) +{ + Q_D(QmlSetProperties); + d->restore = v; +} + +QmlMetaProperty +QmlSetPropertiesPrivate::property(const QByteArray &property) +{ + Q_Q(QmlSetProperties); + QList<QByteArray> path = property.split('.'); + + QObject *obj = this->object; + + for (int jj = 0; jj < path.count() - 1; ++jj) { + const QByteArray &pathName = path.at(jj); + QmlMetaProperty prop(obj, QLatin1String(pathName)); + QObject *objVal = QmlMetaType::toQObject(prop.read()); + if (!objVal) { + qmlInfo(q) << obj->metaObject()->className() + << "has no object property named" << pathName; + return QmlMetaProperty(); + } + obj = objVal; + } + + const QByteArray &name = path.last(); + QmlMetaProperty prop(obj, QLatin1String(name)); + if (!prop.isValid()) { + qmlInfo(q) << obj->metaObject()->className() + << "has no property named" << name; + return QmlMetaProperty(); + } else if (!prop.isWritable()) { + qmlInfo(q) << obj->metaObject()->className() + << name << "is not writable, and cannot be set."; + return QmlMetaProperty(); + } else { + return prop; + } } -QmlSetProperties::ActionList -QmlSetProperties::doAction(QmlSetPropertiesMetaObject *metaObject, - QObject *object) +QmlSetProperties::ActionList QmlSetProperties::actions() { + Q_D(QmlSetProperties); + + d->decode(); + ActionList list; - for (int ii = 0; ii < metaObject->count(); ++ii) { + for (int ii = 0; ii < d->properties.count(); ++ii) { + + QByteArray property = d->properties.at(ii).first; + QmlMetaProperty prop = d->property(property); - QByteArray name = metaObject->name(ii); - QVariant value = metaObject->value(ii); + if (prop.isValid()) { + Action a; + a.restore = restoreEntryValues(); + a.property = prop; + a.fromValue = a.property.read(); + a.toValue = d->properties.at(ii).second; - QmlSetPropertiesProxyObject *po = qobject_cast<QmlSetPropertiesProxyObject *>(qvariant_cast<QObject *>(value)); + list << a; + } + } - QmlMetaProperty prop(object, QLatin1String(name)); + for (int ii = 0; ii < d->expressions.count(); ++ii) { - if (po) { - QObject *objVal = QmlMetaType::toQObject(prop.read()); - if (!objVal) { - qmlInfo(this) << object->metaObject()->className() - << "has no object property named" << name; - continue; - } + QByteArray property = d->expressions.at(ii).first; + QmlMetaProperty prop = d->property(property); - list << doAction(po->fxMetaObject(), objVal); - } else if (!prop.isValid()) { - qmlInfo(this) << object->metaObject()->className() - << "has no property named" << name; - continue; - } else if (!prop.isWritable()) { - qmlInfo(this) << object->metaObject()->className() - << name << "is not writable, and cannot be set."; - continue; - } else { - //append action + if (prop.isValid()) { Action a; + a.restore = restoreEntryValues(); a.property = prop; - a.fromValue = prop.read(); - a.toValue = value; + a.fromValue = a.property.read(); + a.toValue = d->expressions.at(ii).second->value(); list << a; } + } return list; } -QmlSetProperties::ActionList QmlSetProperties::actions() -{ - Q_D(QmlSetProperties); - if (!d->obj) - return ActionList(); - - return doAction(d->mo, d->obj); -} +QML_DEFINE_CUSTOM_TYPE(QmlSetProperties,SetProperties,QmlSetPropertiesParser); QT_END_NAMESPACE -#include "qmlsetproperties.moc" diff --git a/src/declarative/util/qmlsetproperties.h b/src/declarative/util/qmlsetproperties.h index 456b672..24ad99a 100644 --- a/src/declarative/util/qmlsetproperties.h +++ b/src/declarative/util/qmlsetproperties.h @@ -42,7 +42,7 @@ #ifndef QMLSETPROPERTIES_H #define QMLSETPROPERTIES_H -#include <qmlstateoperations.h> +#include <QtDeclarative/qmlstateoperations.h> QT_BEGIN_HEADER @@ -50,7 +50,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QmlSetPropertiesMetaObject; + class QmlSetPropertiesPrivate; class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation { @@ -58,26 +58,23 @@ class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation Q_DECLARE_PRIVATE(QmlSetProperties); Q_PROPERTY(QObject *target READ object WRITE setObject); - + Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues); public: QmlSetProperties(); - QmlSetProperties(QObject *parent); ~QmlSetProperties(); - QObject *object(); + QObject *object() const; void setObject(QObject *); - virtual ActionList actions(); + bool restoreEntryValues() const; + void setRestoreEntryValues(bool); -private: - ActionList doAction(QmlSetPropertiesMetaObject *, QObject *); - //QmlSetProperties::ActionList appendDotActions(const QVariant &, const QVariant &); + virtual ActionList actions(); }; QML_DECLARE_TYPE(QmlSetProperties); -#endif // QMLSETPROPERTIES_H - - QT_END_NAMESPACE QT_END_HEADER + +#endif // QMLSETPROPERTIES_H diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index 194cc1b..6261003 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG); -Action::Action() : bv(0), event(0), actionDone(false) +Action::Action() : restore(true), bv(0), event(0), actionDone(false) { } @@ -344,7 +344,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever for (int ii = 0; ii < applyList.count(); ++ii) { const Action &action = applyList.at(ii); - if (action.event) + if (action.event || !action.restore) continue; bool found = false; diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 68c43fa..aa8871f 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -43,9 +43,9 @@ #define QMLSTATE_H #include <QtCore/qobject.h> -#include <qfxglobal.h> -#include <qml.h> -#include <QSequentialAnimationGroup> +#include <QtCore/QSequentialAnimationGroup> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER @@ -61,6 +61,7 @@ public: Action(); QmlMetaProperty property; + bool restore; QVariant fromValue; QVariant toValue; QString fromBinding; diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index 28e1781..a2f18eb 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -42,9 +42,9 @@ #ifndef QMLSTATE_P_H #define QMLSTATE_P_H -#include <qmlstate.h> -#include "private/qobject_p.h" -#include "private/qmlanimation_p.h" +#include <QtDeclarative/qmlstate.h> +#include <private/qobject_p.h> +#include <private/qmlanimation_p.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/util/qmlstategroup.h b/src/declarative/util/qmlstategroup.h index 55b84eb..cca1015 100644 --- a/src/declarative/util/qmlstategroup.h +++ b/src/declarative/util/qmlstategroup.h @@ -42,7 +42,7 @@ #ifndef QMLSTATEGROUP_H #define QMLSTATEGROUP_H -#include <qmlstate.h> +#include <QtDeclarative/qmlstate.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmlstateoperations.h b/src/declarative/util/qmlstateoperations.h index 8ecdcd2..720c639 100644 --- a/src/declarative/util/qmlstateoperations.h +++ b/src/declarative/util/qmlstateoperations.h @@ -42,7 +42,7 @@ #ifndef QMLSTATEOPERATIONS_H #define QMLSTATEOPERATIONS_H -#include <qmlstate.h> +#include <QtDeclarative/qmlstate.h> QT_BEGIN_HEADER diff --git a/src/declarative/util/qmltransition.h b/src/declarative/util/qmltransition.h index 0b7ea14..646746e 100644 --- a/src/declarative/util/qmltransition.h +++ b/src/declarative/util/qmltransition.h @@ -43,9 +43,9 @@ #define QMLTRANSITION_H #include <QtCore/qobject.h> -#include <qfxglobal.h> -#include <qmlstate.h> -#include <qml.h> +#include <QtDeclarative/qfxglobal.h> +#include <QtDeclarative/qmlstate.h> +#include <QtDeclarative/qml.h> QT_BEGIN_HEADER diff --git a/src/declarative/widgets/graphicslayouts.h b/src/declarative/widgets/graphicslayouts.h index beb4b65..e9930f1 100644 --- a/src/declarative/widgets/graphicslayouts.h +++ b/src/declarative/widgets/graphicslayouts.h @@ -42,9 +42,9 @@ #ifndef GRAPHICSLAYOUTS_H #define GRAPHICSLAYOUTS_H -#include "graphicswidgets.h" -#include <QGraphicsLinearLayout> -#include <QGraphicsGridLayout> +#include <QtDeclarative/graphicswidgets.h> +#include <QtGui/QGraphicsLinearLayout> +#include <QtGui/QGraphicsGridLayout> QT_BEGIN_HEADER diff --git a/src/declarative/widgets/graphicswidgets.h b/src/declarative/widgets/graphicswidgets.h index 47a753a..cec15b6 100644 --- a/src/declarative/widgets/graphicswidgets.h +++ b/src/declarative/widgets/graphicswidgets.h @@ -42,11 +42,11 @@ #ifndef GRAPHICSWIDGETS_H #define GRAPHICSWIDGETS_H -#include <qml.h> -#include <QGraphicsScene> -#include <QGraphicsView> -#include <QGraphicsWidget> -#include <QGraphicsItem> +#include <QtDeclarative/qml.h> +#include <QtGui/QGraphicsScene> +#include <QtGui/QGraphicsView> +#include <QtGui/QGraphicsWidget> +#include <QtGui/QGraphicsItem> QT_BEGIN_NAMESPACE diff --git a/src/gui/dialogs/qsidebar.cpp b/src/gui/dialogs/qsidebar.cpp index 26108d7..000a06b 100644 --- a/src/gui/dialogs/qsidebar.cpp +++ b/src/gui/dialogs/qsidebar.cpp @@ -249,9 +249,9 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move) continue; for (int j = 0; move && j < rowCount(); ++j) { #if defined(Q_OS_WIN) - if (index(j, 0).data(UrlRole).toUrl().toLocalFile().toLower() == url.toLocalFile().toLower()) { + if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()).toLower() == QDir::cleanPath(url.toLocalFile()).toLower()) { #else - if (index(j, 0).data(UrlRole) == url) { + if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()) == QDir::cleanPath(url.toLocalFile())) { #endif removeRow(j); if (j <= row) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ca112d7..e02b3eb 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2640,6 +2640,10 @@ QTransform QGraphicsItem::sceneTransform() const */ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const { + // Ensure we return the standard transform if we're not untransformable. + if (!d_ptr->itemIsUntransformable()) + return sceneTransform() * viewportTransform; + // Find the topmost item that ignores view transformations. const QGraphicsItem *untransformedAncestor = this; QList<const QGraphicsItem *> parents; @@ -2836,7 +2840,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) if (oldTransform == newTransform) return; - // Notify the item that the matrix is changing. + // Notify the item that the transformation matrix is changing. QVariant newTransformVariant(itemChange(ItemMatrixChange, qVariantFromValue<QMatrix>(newTransform.toAffine()))); newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant)); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bc5c091..c421f05 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1330,8 +1330,7 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou bool disabled = !item->isEnabled(); bool isWindow = item->isWindow(); if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick - && item != lastMouseGrabberItem && lastMouseGrabberItem) - { + && item != lastMouseGrabberItem && lastMouseGrabberItem) { // If this item is different from the item that received the last // mouse event, and mouseEvent is a doubleclick event, then the // event is converted to a press. Known limitation: @@ -2326,12 +2325,7 @@ void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRect // Calculate a simple level-of-detail metric. // ### almost identical code in QGraphicsView::paintEvent() // and QGraphicsView::render() - consider refactoring - QTransform itemToDeviceTransform; - if (item->d_ptr->itemIsUntransformable()) { - itemToDeviceTransform = item->deviceTransform(painterTransform); - } else { - itemToDeviceTransform = item->sceneTransform() * painterTransform; - } + QTransform itemToDeviceTransform = item->deviceTransform(painterTransform); option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length()); option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective @@ -5135,11 +5129,7 @@ void QGraphicsScene::drawItems(QPainter *painter, // optimization, but it's hit very rarely. for (int i = clippers.size() - 1; i >= 0; --i) { QGraphicsItem *clipper = clippers[i]; - if (clipper->d_ptr->itemIsUntransformable()) { - painter->setWorldTransform(clipper->deviceTransform(viewTransform), false); - } else { - painter->setWorldTransform(clipper->sceneTransform() * viewTransform, false); - } + painter->setWorldTransform(clipper->deviceTransform(viewTransform), false); childClippers.append(clipper); painter->save(); @@ -5150,12 +5140,8 @@ void QGraphicsScene::drawItems(QPainter *painter, } // Set up the painter transform - if (item->d_ptr->itemIsUntransformable()) { - painter->setWorldTransform(item->deviceTransform(viewTransform), false); - } else { - painter->setWorldTransform(item->sceneTransform() * viewTransform, false); - } - + painter->setWorldTransform(item->deviceTransform(viewTransform), false); + // Save painter bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape)); if (saveState) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 2876016..7181045 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1163,11 +1163,7 @@ void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &it // Calculate a simple level-of-detail metric. // ### almost identical code in QGraphicsScene::render() // and QGraphicsView::render() - consider refactoring - if (item->d_ptr->itemIsUntransformable()) { - itemToViewportTransform = item->deviceTransform(worldTransform); - } else { - itemToViewportTransform = item->sceneTransform() * worldTransform; - } + itemToViewportTransform = item->deviceTransform(worldTransform); if (itemToViewportTransform.type() <= QTransform::TxTranslate) { // Translation and rotation only? The LOD is 1. @@ -1691,6 +1687,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene) disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(updateSceneRect(QRectF))); d->scene->d_func()->views.removeAll(this); + d->connectedToScene = false; } // Assign the new scene and update the contents (scrollbars, etc.)). @@ -2175,12 +2172,7 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect // Calculate a simple level-of-detail metric. // ### almost identical code in QGraphicsScene::render() // and QGraphicsView::paintEvent() - consider refactoring - QTransform itemToViewportTransform; - if (item->d_ptr->itemIsUntransformable()) { - itemToViewportTransform = item->deviceTransform(painterMatrix); - } else { - itemToViewportTransform = item->sceneTransform() * painterMatrix; - } + QTransform itemToViewportTransform = item->deviceTransform(painterMatrix); option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length()); option->matrix = itemToViewportTransform.toAffine(); diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 0514567..b2b8c13 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -856,6 +856,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) QImageWriter::supportedImageFormats() functions to retrieve a complete list of the supported file formats. + Note: When you add a non-empty filename to a QIcon, the icon becomes + non-null, even if the file doesn't exist or points to a corrupt file. + \sa addPixmap() */ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state) diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 20bed02..d4ebef7 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -319,6 +319,7 @@ static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) } else { qWarning("qt_fromWinHBITMAP(), failed to get bitmap bits"); } + qFree(data); return image; } diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index 9f33af3..054f4cf 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -416,26 +416,22 @@ QString QFileIconProvider::type(const QFileInfo &info) const } if (info.isDir()) - return QApplication::translate("QFileDialog", #ifdef Q_WS_WIN - "File Folder", "Match Windows Explorer" + return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer"); #else - "Folder", "All other platforms" + return QApplication::translate("QFileDialog", "Folder", "All other platforms"); #endif - ); // Windows - "File Folder" // OS X - "Folder" // Konqueror - "Folder" // Nautilus - "folder" if (info.isSymLink()) - return QApplication::translate("QFileDialog", #ifdef Q_OS_MAC - "Alias", "Mac OS X Finder" + return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder"); #else - "Shortcut", "All other platforms" + return QApplication::translate("QFileDialog", "Shortcut", "All other platforms"); #endif - ); // OS X - "Alias" // Windows - "Shortcut" // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 3e00cd0..1071c1d 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1608,6 +1608,10 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con if (!selection.at(i).isValid()) continue; QModelIndex parent = selection.at(i).topLeft().parent(); + //we only display the children of the root in a listview + //we're not interested in the other model indexes + if (parent != d->root) + continue; int t = selection.at(i).topLeft().row(); int b = selection.at(i).bottomRight().row(); if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items @@ -1616,8 +1620,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con } else { // in static mode, we can optimize a bit while (t <= b && d->isHidden(t)) ++t; while (b >= t && d->isHidden(b)) --b; - const QModelIndex top = d->model->index(t, c, d->root); - const QModelIndex bottom = d->model->index(b, c, d->root); + const QModelIndex top = d->model->index(t, c, parent); + const QModelIndex bottom = d->model->index(b, c, parent); QRect rect(visualRect(top).topLeft(), visualRect(bottom).bottomRight()); selectionRegion += QRegion(rect); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index f6c5cf0..d742698 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -3086,10 +3086,6 @@ void QTreeViewPrivate::layout(int i) Q_Q(QTreeView); QModelIndex current; QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i); - // modelIndex() will return an index that don't have a parent if column 0 is hidden, - // so we must make sure that parent points to the actual parent that has children. - if (parent != root) - parent = model->index(parent.row(), 0, parent.parent()); if (i>=0 && !parent.isValid()) { //modelIndex() should never return something invalid for the real items. diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 27dfab6..a9424db 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -2028,12 +2028,10 @@ QWidget *QApplication::focusWidget() void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) { - if (focus && focus->window() #ifndef QT_NO_GRAPHICSVIEW - && focus->window()->graphicsProxyWidget() -#endif - ) + if (focus && focus->window()->graphicsProxyWidget()) return; +#endif hidden_focus_widget = 0; diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index ed93b34..9b2305d 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -543,7 +543,7 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data (dm->xdndMimeTransferedPixmapIndex + 1) % 2; } } else { - DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", atomName); + DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName)); } } return data; @@ -624,7 +624,6 @@ QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const if (format == QLatin1String("image/ppm")) { if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { Pixmap xpm = *((Pixmap*)data.data()); - Display *dpy = display; if (!xpm) return QByteArray(); QPixmap qpm = QPixmap::fromX11Pixmap(xpm); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index a77325c..c8d40d8 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -714,12 +714,13 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, The \a type parameter must be QEvent::KeyPress, QEvent::KeyRelease, or QEvent::ShortcutOverride. - If \a key is 0, the event is not a result of - a known key; for example, it may be the result of a compose - sequence or keyboard macro. The \a modifiers holds the keyboard - modifiers, and the given \a text is the Unicode text that the - key generated. If \a autorep is true, isAutoRepeat() will be - true. \a count is the number of keys involved in the event. + Int \a key is the code for the Qt::Key that the event loop should listen + for. If \a key is 0, the event is not a result of a known key; for + example, it may be the result of a compose sequence or keyboard macro. + The \a modifiers holds the keyboard modifiers, and the given \a text + is the Unicode text that the key generated. If \a autorep is true, + isAutoRepeat() will be true. \a count is the number of keys involved + in the event. */ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text, bool autorep, ushort count) diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 0fd73b8..c70ab2d 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, -1); + return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin, + -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin); } inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) @@ -64,7 +65,8 @@ inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, +1); + return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin, + priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin); } inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size) diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index b6703e2..f998bb2 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -751,6 +751,7 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr tw = tw->parentWidget(); return tw == w; } + return false; } // Below is Qt::WindowShortcut context diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index b50eb24..e52a517 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -167,39 +167,48 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p) extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -QWidgetPrivate::QWidgetPrivate(int version) : - QObjectPrivate(version), extra(0), focus_child(0) - ,layout(0), widgetItem(0) - ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0) - ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0) - ,bottomLayoutItemMargin(0) - ,fg_role(QPalette::NoRole) - ,bg_role(QPalette::NoRole) - ,hd(0) - ,dirty(0) - ,needsFlush(0) - ,dirtyOpaqueChildren(1) - ,isOpaque(0) - ,inDirtyList(0) - ,isScrolled(0) - ,isMoved(0) - ,usesDoubleBufferedGLContext(0) -#ifdef Q_WS_WIN - ,noPaintOnScreen(0) -#endif - ,inheritedFontResolveMask(0) - ,inheritedPaletteResolveMask(0) +QWidgetPrivate::QWidgetPrivate(int version) + : QObjectPrivate(version) + , extra(0) + , focus_next(0) + , focus_prev(0) + , focus_child(0) + , layout(0) + , needsFlush(0) + , redirectDev(0) + , widgetItem(0) + , extraPaintEngine(0) + , polished(0) + , inheritedFontResolveMask(0) + , inheritedPaletteResolveMask(0) + , leftmargin(0) + , topmargin(0) + , rightmargin(0) + , bottommargin(0) + , leftLayoutItemMargin(0) + , topLayoutItemMargin(0) + , rightLayoutItemMargin(0) + , bottomLayoutItemMargin(0) + , hd(0) + , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) + , fg_role(QPalette::NoRole) + , bg_role(QPalette::NoRole) + , dirtyOpaqueChildren(1) + , isOpaque(0) + , inDirtyList(0) + , isScrolled(0) + , isMoved(0) + , usesDoubleBufferedGLContext(0) #if defined(Q_WS_X11) - ,picture(0) + , picture(0) +#elif defined(Q_WS_WIN) + , noPaintOnScreen(0) +#elif defined(Q_WS_MAC) + , needWindowChange(0) + , isGLWidget(0) + , window_event(0) + , qd_hd(0) #endif -#ifdef Q_WS_MAC - ,needWindowChange(0) - ,isGLWidget(0) -#endif - ,polished(0) - - , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) - , redirectDev(0) { if (!qApp) { qFatal("QWidget: Must construct a QApplication before a QPaintDevice"); @@ -1345,7 +1354,7 @@ QWidget::~QWidget() d->setDirtyOpaqueRegion(); if (isWindow() && isVisible() && internalWinId()) - hide(); + d->close_helper(QWidgetPrivate::CloseNoEvent); #if defined(Q_WS_WIN) || defined(Q_WS_X11) else if (!internalWinId() && isVisible()) qApp->d_func()->sendSyntheticEnterLeave(this); @@ -1412,36 +1421,26 @@ void QWidgetPrivate::createTLExtra() createExtra(); if (!extra->topextra) { QTLWExtra* x = extra->topextra = new QTLWExtra; + x->icon = 0; + x->iconPixmap = 0; + x->backingStore = 0; x->windowSurface = 0; + x->sharedPainter = 0; + x->incw = x->inch = 0; + x->basew = x->baseh = 0; + x->frameStrut.setCoords(0, 0, 0, 0); + x->normalGeometry = QRect(0,0,-1,-1); + x->savedFlags = 0; x->opacity = 255; x->posFromMove = false; x->sizeAdjusted = false; x->inTopLevelResize = false; x->inRepaint = false; - x->backingStore = 0; - x->icon = 0; - x->iconPixmap = 0; - x->frameStrut.setCoords(0, 0, 0, 0); - x->incw = x->inch = 0; - x->basew = x->baseh = 0; - x->normalGeometry = QRect(0,0,-1,-1); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) x->embedded = 0; -#endif -#if defined(Q_WS_X11) - x->parentWinId = 0; - x->spont_unmapped = 0; - x->dnd = 0; -#endif - x->savedFlags = 0; -#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) - x->qwsManager = 0; -#endif - x->sharedPainter = 0; createTLSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "tlextra" << ++count; + static int count = 0; + qDebug() << "tlextra" << ++count; #endif } } @@ -1455,27 +1454,28 @@ void QWidgetPrivate::createExtra() { if (!extra) { // if not exists extra = new QWExtra; - extra->minw = extra->minh = 0; - extra->maxw = extra->maxh = QWIDGETSIZE_MAX; + extra->glContext = 0; + extra->topextra = 0; + extra->proxyWidget = 0; +#ifndef QT_NO_CURSOR + extra->curs = 0; +#endif + extra->minw = 0; + extra->minh = 0; + extra->maxw = QWIDGETSIZE_MAX; + extra->maxh = QWIDGETSIZE_MAX; + extra->customDpiX = 0; + extra->customDpiY = 0; extra->explicitMinSize = 0; extra->explicitMaxSize = 0; extra->autoFillBackground = 0; extra->nativeChildrenForced = 0; extra->inRenderWithPainter = 0; extra->hasMask = 0; -#ifndef QT_NO_CURSOR - extra->curs = 0; -#endif - extra->style = 0; - extra->topextra = 0; - extra->proxyWidget = 0; - extra->glContext = 0; - extra->customDpiX = 0; - extra->customDpiY = 0; createSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "extra" << ++count; + static int count = 0; + qDebug() << "extra" << ++count; #endif } } @@ -1516,45 +1516,6 @@ void QWidgetPrivate::deleteExtra() } /* - Returns true if the background is inherited; otherwise returns - false. - - Mainly used in the paintOnScreen case. -*/ - -bool QWidgetPrivate::isBackgroundInherited() const -{ - Q_Q(const QWidget); - - // windows do not inherit their background - if (q->isWindow() || q->windowType() == Qt::SubWindow) - return false; - - if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) - return false; - - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush brush = pal.brush(bg); - - // non opaque brushes leaves us no choice, we must inherit - if (!q->autoFillBackground() || !brush.isOpaque()) - return true; - - if (brush.style() == Qt::SolidPattern) { - // the background is just a solid color. If there is no - // propagated contents, then we claim as performance - // optimization that it was not inheritet. This is the normal - // case in standard Windows or Motif style. - const QWidget *w = q->parentWidget(); - if (!w->d_func()->isBackgroundInherited()) - return false; - } - - return true; -} - -/* Returns true if there are widgets above this which overlap with \a rect, which is in parent's coordinate system (same as crect). */ @@ -1900,24 +1861,6 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const } } -bool QWidgetPrivate::hasBackground() const -{ - Q_Q(const QWidget); - if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (q->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush bgBrush = pal.brush(bg); - return (bgBrush.style() != Qt::NoBrush && - ((q->isWindow() || q->windowType() == Qt::SubWindow) - || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg))))); - } - return false; -} - bool QWidgetPrivate::paintOnScreen() const { #if defined(Q_WS_QWS) @@ -6157,14 +6100,6 @@ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r) return dx + dy; } -QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const -{ - QRect r = rect; - r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin, - +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin); - return r; -} - /*! \property QWidget::frameSize \brief the size of the widget including any window frame diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1896b97..cc291e3 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -728,6 +728,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowExpanded }, + { kEventClassWindow, kEventWindowHidden }, { kEventClassWindow, kEventWindowZoomed }, { kEventClassWindow, kEventWindowCollapsed }, { kEventClassWindow, kEventWindowToolbarSwitchMode }, @@ -780,16 +781,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, // By also setting the current modal window back into the event, we // help Carbon determining which window is supposed to be raised. handled_event = qApp->activePopupWidget() ? true : false; - QWidget *top = 0; - if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && top != widget){ - if(!qt_mac_is_macsheet(top) || top->parentWidget() != widget) { - handled_event = true; - WindowPtr topWindowRef = qt_mac_window_for(top); - SetEventParameter(event, kEventParamModalWindow, typeWindowRef, sizeof(topWindowRef), &topWindowRef); - HIModalClickResult clickResult = kHIModalClickIsModal; - SetEventParameter(event, kEventParamModalClickResult, typeModalClickResult, sizeof(clickResult), &clickResult); - } - } #endif } else if(ekind == kEventWindowClose) { widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); @@ -997,6 +988,19 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, } } } + } else if (ekind == kEventWindowHidden) { + // Make sure that we also hide any visible sheets on our window. + // Cocoa does the right thing for us. + const QObjectList children = widget->children(); + const int childCount = children.count(); + for (int i = 0; i < childCount; ++i) { + QObject *obj = children.at(i); + if (obj->isWidgetType()) { + QWidget *widget = static_cast<QWidget *>(obj); + if (qt_mac_is_macsheet(widget) && widget->isVisible()) + widget->hide(); + } + } } else { handled_event = false; } @@ -1599,24 +1603,6 @@ bool QWidgetPrivate::qt_create_root_win() return true; } -bool QWidgetPrivate::qt_recreate_root_win() -{ - if(!qt_root_win) //sanity check - return false; - //store old - OSWindowRef old_root_win = qt_root_win; - //recreate - qt_root_win = 0; - qt_create_root_win(); - //cleanup old window -#ifdef QT_MAC_USE_COCOA - [old_root_win release]; -#else - CFRelease(old_root_win); -#endif - return true; -} - bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false) { bool ret = false; @@ -4438,11 +4424,13 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { + extra->topextra->resizer = 0; + extra->topextra->isSetGeometry = 0; + extra->topextra->isMove = 0; + extra->topextra->wattr = 0; extra->topextra->wclass = 0; extra->topextra->group = 0; extra->topextra->windowIcon = 0; - extra->topextra->resizer = 0; - extra->topextra->isSetGeometry = 0; extra->topextra->savedWindowAttributesFromMaximized = 0; } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 8c6a234..bf4f091 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -99,88 +99,92 @@ class QWidgetItemV2; class QStyle; struct QTLWExtra { + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + QIcon *icon; // widget icon + QPixmap *iconPixmap; + QWidgetBackingStore *backingStore; + QWindowSurface *windowSurface; + QPainter *sharedPainter; + + // Implicit pointers (shared_null). QString caption; // widget caption QString iconText; // widget icon text QString role; // widget role QString filePath; // widget file path - QIcon *icon; // widget icon - QPixmap *iconPixmap; + + // Other variables. short incw, inch; // size increments + short basew, baseh; // base sizes // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead. QRect frameStrut; + QRect normalGeometry; // used by showMin/maximized/FullScreen + Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen + + // *************************** Cross-platform bit fields **************************** uint opacity : 8; uint posFromMove : 1; uint sizeAdjusted : 1; uint inTopLevelResize : 1; uint inRepaint : 1; - QWidgetBackingStore *backingStore; -#if defined(Q_WS_WIN) - ulong savedFlags; // Save window flags while showing fullscreen - uint embedded : 1; // window is embedded in another application -#else - Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen -#endif - short basew, baseh; // base sizes -#if defined(Q_WS_X11) - WId parentWinId; // parent window Id (valid after reparenting) - uint embedded : 1; // window is embedded in another Qt application + uint embedded : 1; + + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 uint spont_unmapped: 1; // window was spontaneously unmapped uint dnd : 1; // DND properties installed uint validWMState : 1; // is WM_STATE valid? uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet + WId parentWinId; // parent window Id (valid after reparenting) WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom QPoint fullScreenOffset; -#endif -#if defined(Q_WS_MAC) +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + HICON winIconBig; // internal big Windows icon + HICON winIconSmall; // internal small Windows icon +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + uint resizer : 4; + uint isSetGeometry : 1; + uint isMove : 1; quint32 wattr; quint32 wclass; WindowGroupRef group; IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() - uint resizer : 4; - uint isSetGeometry : 1; - uint isMove : 1; - uint embedded : 1; -#endif -#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER) +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS +#ifndef QT_NO_QWS_MANAGER QWSManager *qwsManager; #endif -#if defined(Q_WS_WIN) - HICON winIconBig; // internal big Windows icon - HICON winIconSmall; // internal small Windows icon #endif - QRect normalGeometry; // used by showMin/maximized/FullScreen - QWindowSurface *windowSurface; - QPainter *sharedPainter; }; struct QWExtra { - qint32 minw, minh; // minimum size - qint32 maxw, maxh; // maximum size - QPointer<QWidget> focus_proxy; -#ifndef QT_NO_CURSOR - QCursor *curs; -#endif + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + void *glContext; // if the widget is hijacked by QGLWindowSurface QTLWExtra *topextra; // only useful for TLWs QGraphicsProxyWidget *proxyWidget; // if the widget is embedded - void *glContext; // if the widget is hijacked by QGLWindowSurface -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *dropTarget; // drop target - QList<QPointer<QWidget> > oleDropWidgets; -#endif -#if defined(Q_WS_X11) - WId xDndProxy; // XDND forwarding to embedded windows +#ifndef QT_NO_CURSOR + QCursor *curs; #endif + QPointer<QStyle> style; + QPointer<QWidget> focus_proxy; + + // Implicit pointers (shared_empty/shared_null). QRegion mask; // widget mask + QString styleSheet; + + // Other variables. + qint32 minw; + qint32 minh; // minimum size + qint32 maxw; + qint32 maxh; // maximum size + quint16 customDpiX; + quint16 customDpiY; QSize staticContentsSize; -//bit flags at the end to improve packing -#if defined(Q_WS_WIN) - uint shown_mode : 8; // widget show mode -#endif -#if defined(Q_WS_X11) - uint compress_events : 1; -#endif + // *************************** Cross-platform bit fields **************************** uint explicitMinSize : 2; uint explicitMaxSize : 2; uint autoFillBackground : 1; @@ -188,16 +192,22 @@ struct QWExtra { uint inRenderWithPainter : 1; uint hasMask : 1; - QPointer<QStyle> style; - QString styleSheet; - - quint16 customDpiX; - quint16 customDpiY; -#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *dropTarget; // drop target + QList<QPointer<QWidget> > oleDropWidgets; +#endif +#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11 + uint compress_events : 1; + WId xDndProxy; // XDND forwarding to embedded windows +#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC +#ifdef QT_MAC_USE_COCOA // Cocoa Mask stuff QImage maskBits; CGImageRef imageMask; #endif +#endif }; class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate @@ -205,6 +215,24 @@ class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QWidget) public: + // *************************** Cross-platform *************************************** + enum DrawWidgetFlags { + DrawAsRoot = 0x01, + DrawPaintOnScreen = 0x02, + DrawRecursive = 0x04, + DrawInvisible = 0x08, + DontSubtractOpaqueChildren = 0x10, + DontSetCompositionMode = 0x20, + DontDrawOpaqueChildren = 0x40 + }; + + enum CloseMode { + CloseNoEvent, + CloseWithEvent, + CloseWithSpontaneousEvent + }; + + // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); ~QWidgetPrivate(); @@ -214,10 +242,6 @@ public: QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); QWidgetBackingStore *maybeBackingStore() const; -#ifdef Q_WS_QWS - void setMaxWindowState_helper(); - void setFullScreenSize_helper(); -#endif void init(QWidget *desktopWidget, Qt::WindowFlags f); void create_sys(WId window, bool initializeWindow, bool destroyOldWindow); void createRecursively(); @@ -238,24 +262,6 @@ public: QPalette naturalWidgetPalette(uint inheritedMask) const; void setMask_sys(const QRegion &); -#ifdef Q_WS_WIN - bool shouldShowMaximizeButton(); - void winUpdateIsOpaque(); -#endif - -#ifdef Q_WS_MAC - void macUpdateSizeAttribute(); - void macUpdateHideOnSuspend(); - void macUpdateOpaqueSizeGrip(); - void macUpdateIgnoreMouseEvents(); - void macUpdateMetalAttribute(); - void macUpdateIsOpaque(); - void setEnabled_helper_sys(bool enable); - bool isRealWindow() const; - void adjustWithinMaxAndMinSize(int &w, int &h); - void applyMaxAndMinSizeOnWindow(); -#endif - void raise_sys(); void lower_sys(); void stackUnder_sys(QWidget *); @@ -280,20 +286,9 @@ public: void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false); void inheritStyle(); - bool isBackgroundInherited() const; - void setUpdatesEnabled_helper(bool ); void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const; - enum DrawWidgetFlags { - DrawAsRoot = 0x01, - DrawPaintOnScreen = 0x02, - DrawRecursive = 0x04, - DrawInvisible = 0x08, - DontSubtractOpaqueChildren = 0x10, - DontSetCompositionMode = 0x20, - DontDrawOpaqueChildren = 0x40 - }; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, @@ -316,10 +311,6 @@ public: QWindowSurface *createDefaultWindowSurface(); QWindowSurface *createDefaultWindowSurface_sys(); void repaint_sys(const QRegion &rgn); -#ifdef Q_WS_MAC - void update_sys(const QRect &rect); - void update_sys(const QRegion &rgn); -#endif QRect clipRect() const; QRegion clipRegion() const; @@ -330,42 +321,20 @@ public: void updateIsOpaque(); void setOpaque(bool opaque); void updateIsTranslucent(); - bool hasBackground() const; bool paintOnScreen() const; QRegion getOpaqueRegion() const; const QRegion &getOpaqueChildren() const; void setDirtyOpaqueRegion(); - QRegion opaqueChildren; - - enum CloseMode { - CloseNoEvent, - CloseWithEvent, - CloseWithSpontaneousEvent - }; bool close_helper(CloseMode mode); - bool compositeEvent(QEvent *e); void setWindowIcon_helper(); void setWindowIcon_sys(bool forceReset = false); void setWindowOpacity_sys(qreal opacity); - void adjustQuitOnCloseAttribute(); -#if defined(Q_WS_X11) - void setWindowRole(); - void sendStartupMessage(const char *message) const; - void setNetWmWindowTypes(); - void x11UpdateIsOpaque(); -#endif - -#if defined (Q_WS_WIN) - void reparentChildren(); -#endif - void scrollChildren(int dx, int dy); - void moveRect(const QRect &, int dx, int dy); void scrollRect(const QRect &, int dx, int dy); void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize); @@ -379,7 +348,6 @@ public: void reparentFocusWidgets(QWidget *oldtlw); static int pointToRect(const QPoint &p, const QRect &r); - QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const; void setWinId(WId); void showChildren(bool spontaneous); @@ -389,9 +357,6 @@ public: void scroll_sys(int dx, int dy, const QRect &r); void deactivateWidgetCleanup(); void setGeometry_sys(int, int, int, int, bool); -#ifdef Q_WS_MAC - void setGeometry_sys_helper(int, int, int, int, bool); -#endif void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false); void activateChildLayoutsRecursively(); void show_recursive(); @@ -403,10 +368,6 @@ public: void setEnabled_helper(bool); void registerDropSite(bool); -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *registerOleDnd(QWidget *widget); - void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); -#endif static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0); void updateFrameStrut(); @@ -416,32 +377,11 @@ public: void setWindowIconText_helper(const QString &cap); void setWindowTitle_sys(const QString &cap); -#ifdef Q_OS_WIN - void grabMouseWhileInWindow(); -#endif - #ifndef QT_NO_CURSOR void setCursor_sys(const QCursor &cursor); void unsetCursor_sys(); #endif -#ifdef Q_WS_MAC - void setWindowModified_sys(bool b); - void updateMaximizeButton_sys(); - void setWindowFilePath_sys(const QString &filePath); - void createWindow_sys(); - void recreateMacWindow(); -#ifndef QT_MAC_USE_COCOA - void initWindowPtr(); - void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); -#else - void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); - void syncCocoaMask(); - void finishCocoaMaskSetup(); -#endif - void determineWindowClass(); - void transferChildren(); -#endif void setWindowTitle_helper(const QString &cap); void setWindowFilePath_helper(const QString &filePath); @@ -457,59 +397,89 @@ public: QInputContext *inputContext() const; -#if defined(Q_WS_QWS) - void moveSurface(QWindowSurface *surface, const QPoint &offset); + void setModal_sys(); - QRegion localRequestedRegion() const; - QRegion localAllocatedRegion() const; + inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) + { + Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); + redirectDev = replacement; + redirectOffset = offset; + } - void blitToScreen(const QRegion &globalrgn); -#ifndef QT_NO_CURSOR - void updateCursor() const; -#endif + inline QPaintDevice *redirected(QPoint *offset) const + { + if (offset) + *offset = redirectDev ? redirectOffset : QPoint(); + return redirectDev; + } - QScreen* getScreen() const; + inline void restoreRedirected() + { redirectDev = 0; } - friend class QWSManager; - friend class QWSManagerPrivate; - friend class QDecoration; -#endif + inline void enforceNativeChildren() + { + if (!extra) + createExtra(); - static int instanceCounter; // Current number of widget instances - static int maxInstances; // Maximum number of widget instances + if (extra->nativeChildrenForced) + return; + extra->nativeChildrenForced = 1; -#ifdef QT_KEYPAD_NAVIGATION - static QPointer<QWidget> editingWidget; -#endif + for (int i = 0; i < children.size(); ++i) { + if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) + child->setAttribute(Qt::WA_NativeWindow); + } + } - QWidgetData data; + inline bool nativeChildrenForced() const + { + return extra ? extra->nativeChildrenForced : false; + } + + QSize adjustedSize() const; + +#ifndef Q_WS_QWS // Almost cross-platform :-) + void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + + inline QPoint mapToWS(const QPoint &p) const + { return p - data.wrect.topLeft(); } + + inline QPoint mapFromWS(const QPoint &p) const + { return p + data.wrect.topLeft(); } + + inline QRect mapToWS(const QRect &r) const + { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } + + inline QRect mapFromWS(const QRect &r) const + { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } +#endif + // Variables. + // Regular pointers (keep them together to avoid gaps on 64 bit architectures). QWExtra *extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; -#ifndef QT_NO_ACTION - QList<QAction*> actions; -#endif QLayout *layout; + QRegion *needsFlush; + QPaintDevice *redirectDev; QWidgetItemV2 *widgetItem; -#if !defined(QT_NO_IM) - QPointer<QInputContext> ic; -#endif + QPaintEngine *extraPaintEngine; + mutable const QMetaObject *polished; // All widgets are initially added into the uncreatedWidgets set. Once // they receive a window id they are removed and added to the mapper static QWidgetMapper *mapper; static QWidgetSet *uncreatedWidgets; +#if !defined(QT_NO_IM) + QPointer<QInputContext> ic; +#endif +#ifdef QT_KEYPAD_NAVIGATION + static QPointer<QWidget> editingWidget; +#endif - short leftmargin, topmargin, rightmargin, bottommargin; - - signed char leftLayoutItemMargin; - signed char topLayoutItemMargin; - signed char rightLayoutItemMargin; - signed char bottomLayoutItemMargin; - - // ### TODO: reorganize private/extra/topextra to save memory - QPointer<QWidget> compositeChildGrab; + // Implicit pointers (shared_null/shared_empty). + QRegion opaqueChildren; + QRegion dirty; #ifndef QT_NO_TOOLTIP QString toolTip; #endif @@ -519,14 +489,37 @@ public: #ifndef QT_NO_WHATSTHIS QString whatsThis; #endif - QString accessibleName, accessibleDescription; +#ifndef QT_NO_ACCESSIBILITY + QString accessibleName; + QString accessibleDescription; +#endif + + // Other variables. + uint inheritedFontResolveMask; + uint inheritedPaletteResolveMask; + short leftmargin; + short topmargin; + short rightmargin; + short bottommargin; + signed char leftLayoutItemMargin; + signed char topLayoutItemMargin; + signed char rightLayoutItemMargin; + signed char bottomLayoutItemMargin; + static int instanceCounter; // Current number of widget instances + static int maxInstances; // Maximum number of widget instances + Qt::HANDLE hd; + QWidgetData data; + QSizePolicy size_policy; + QLocale locale; + QPoint redirectOffset; +#ifndef QT_NO_ACTION + QList<QAction*> actions; +#endif + // Bit fields. + uint high_attributes[3]; // the low ones are in QWidget::widget_attributes QPalette::ColorRole fg_role : 8; QPalette::ColorRole bg_role : 8; - uint high_attributes[3]; // the low ones are in QWidget::widget_attributes - Qt::HANDLE hd; - QRegion dirty; - QRegion *needsFlush; uint dirtyOpaqueChildren : 1; uint isOpaque : 1; uint inDirtyList : 1; @@ -534,35 +527,33 @@ public: uint isMoved : 1; uint usesDoubleBufferedGLContext : 1; -#ifdef Q_WS_WIN - uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() -#endif - - uint inheritedFontResolveMask; - uint inheritedPaletteResolveMask; -#if defined(Q_WS_X11) + // *************************** Platform specific ************************************ +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 QX11Info xinfo; Qt::HANDLE picture; + static QWidget *mouseGrabber; + static QWidget *keyboardGrabber; + + void setWindowRole(); + void sendStartupMessage(const char *message) const; + void setNetWmWindowTypes(); + void x11UpdateIsOpaque(); + bool isBackgroundInherited() const; +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() + + bool shouldShowMaximizeButton(); + void winUpdateIsOpaque(); + void reparentChildren(); +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *registerOleDnd(QWidget *widget); + void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); #endif -#if defined(Q_WS_MAC) - enum PaintChildrenOPs { - PC_None = 0x00, - PC_Now = 0x01, - PC_NoPaint = 0x04, - PC_Later = 0x10 - }; - EventHandlerRef window_event; - bool qt_mac_dnd_event(uint, DragRef); - void toggleDrawers(bool); - //mac event functions - static bool qt_create_root_win(); - static void qt_clean_root_win(); - static bool qt_recreate_root_win(); - static bool qt_mac_update_sizer(QWidget *, int up = 0); - static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); - static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); - static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool); + void grabMouseWhileInWindow(); +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + // This is new stuff + uint needWindowChange : 1; + uint isGLWidget : 1; // Each wiget keeps a list of all its child and grandchild OpenGL widgets. // This list is used to update the gl context whenever a parent and a granparent @@ -575,95 +566,70 @@ public: QWidget * widget; QWidget * lastUpdateWidget; }; - QList<GlWidgetInfo> glWidgets; // dirtyOnWidget contains the areas in the widget that needs to be repained, // in the same way as dirtyOnScreen does for the window. Areas are added in // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use // this information repaint invalid areas when widgets are scrolled. QRegion dirtyOnWidget; + EventHandlerRef window_event; + QList<GlWidgetInfo> glWidgets; //these are here just for code compat (HIViews) Qt::HANDLE qd_hd; - // This is new stuff - uint needWindowChange : 1; - uint isGLWidget : 1; -#endif - -#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) -#ifdef Q_WS_MAC - void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + void macUpdateSizeAttribute(); + void macUpdateHideOnSuspend(); + void macUpdateOpaqueSizeGrip(); + void macUpdateIgnoreMouseEvents(); + void macUpdateMetalAttribute(); + void macUpdateIsOpaque(); + void setEnabled_helper_sys(bool enable); + bool isRealWindow() const; + void adjustWithinMaxAndMinSize(int &w, int &h); + void applyMaxAndMinSizeOnWindow(); + void update_sys(const QRect &rect); + void update_sys(const QRegion &rgn); + void setGeometry_sys_helper(int, int, int, int, bool); + void setWindowModified_sys(bool b); + void updateMaximizeButton_sys(); + void setWindowFilePath_sys(const QString &filePath); + void createWindow_sys(); + void recreateMacWindow(); +#ifndef QT_MAC_USE_COCOA + void initWindowPtr(); + void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); #else - void setWSGeometry(bool dontShow=false); + void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); + void syncCocoaMask(); + void finishCocoaMaskSetup(); #endif + void determineWindowClass(); + void transferChildren(); + bool qt_mac_dnd_event(uint, DragRef); + void toggleDrawers(bool); + //mac event functions + static bool qt_create_root_win(); + static void qt_clean_root_win(); + static bool qt_mac_update_sizer(QWidget *, int up = 0); + static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); + static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); + static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); + void moveSurface(QWindowSurface *surface, const QPoint &offset); + QRegion localRequestedRegion() const; + QRegion localAllocatedRegion() const; - inline QPoint mapToWS(const QPoint &p) const - { return p - data.wrect.topLeft(); } - - inline QPoint mapFromWS(const QPoint &p) const - { return p + data.wrect.topLeft(); } - - inline QRect mapToWS(const QRect &r) const - { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } - - inline QRect mapFromWS(const QRect &r) const - { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } + friend class QWSManager; + friend class QWSManagerPrivate; + friend class QDecoration; +#ifndef QT_NO_CURSOR + void updateCursor() const; #endif - - QPaintEngine *extraPaintEngine; - - mutable const QMetaObject *polished; - - void setModal_sys(); - QSizePolicy size_policy; - QLocale locale; - -#ifdef Q_WS_X11 - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; + QScreen* getScreen() const; #endif - QPaintDevice *redirectDev; - QPoint redirectOffset; - - inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) - { - Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); - redirectDev = replacement; - redirectOffset = offset; - } - - inline QPaintDevice *redirected(QPoint *offset) const - { - if (offset) - *offset = redirectDev ? redirectOffset : QPoint(); - return redirectDev; - } - - inline void restoreRedirected() - { redirectDev = 0; } - - inline void enforceNativeChildren() - { - if (!extra) - createExtra(); - - if (extra->nativeChildrenForced) - return; - extra->nativeChildrenForced = 1; - - for (int i = 0; i < children.size(); ++i) { - if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) - child->setAttribute(Qt::WA_NativeWindow); - } - } - - inline bool nativeChildrenForced() const - { - return extra ? extra->nativeChildrenForced : false; - } - - QSize adjustedSize() const; }; inline QWExtra *QWidgetPrivate::extraData() const diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index 1445f57..94bdb85 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -565,20 +565,6 @@ void QWidget::activateWindow() } } -/* - Should we require that q is a toplevel window ??? - - Used by QWSManager - */ -void QWidgetPrivate::blitToScreen(const QRegion &globalrgn) -{ - Q_Q(QWidget); - QWidget *win = q->window(); - QBrush bgBrush = win->palette().brush(win->backgroundRole()); - bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque(); - QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn); -} - void QWidgetPrivate::show_sys() { Q_Q(QWidget); @@ -1037,6 +1023,9 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { +#ifndef QT_NO_QWS_MANAGER + extra->topextra->qwsManager = 0; +#endif } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index cfdabaf..0f341fd 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1025,13 +1025,13 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = Qt::WindowFlags(GetWindowLongA(internalWinId(), GWL_STYLE)); #ifndef Q_FLATTEN_EXPOSE UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; #else UINT style = WS_POPUP; #endif - if (d->topData()->savedFlags & WS_SYSMENU) + if (ulong(d->topData()->savedFlags) & WS_SYSMENU) style |= WS_SYSMENU; if (isVisible()) style |= WS_VISIBLE; @@ -1234,7 +1234,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget* w) (In all comments below: s/X/Windows/g) */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -1704,7 +1704,6 @@ int QWidget::metric(PaintDeviceMetric m) const return val; } -#ifndef Q_WS_WINCE void QWidgetPrivate::createSysExtra() { #ifndef QT_NO_DRAGANDDROP @@ -1712,6 +1711,7 @@ void QWidgetPrivate::createSysExtra() #endif } +#ifndef Q_WS_WINCE void QWidgetPrivate::deleteSysExtra() { } @@ -1719,8 +1719,9 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { - extra->topextra->winIconSmall = 0; + extra->topextra->savedFlags = 0; extra->topextra->winIconBig = 0; + extra->topextra->winIconSmall = 0; } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index cca928e..435fd31 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -535,7 +535,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = (Qt::WindowFlags) GetWindowLongA(internalWinId(), GWL_STYLE); UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; if (isVisible()) style |= WS_VISIBLE; @@ -598,13 +598,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) QApplication::sendEvent(this, &e); } - -void QWidgetPrivate::createSysExtra() { -#ifndef QT_NO_DRAGANDDROP - extra->dropTarget = 0; -#endif -} - void QWidgetPrivate::deleteSysExtra() { Q_Q(QWidget); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 6202b35..b35740a 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -906,6 +906,44 @@ void QWidgetPrivate::x11UpdateIsOpaque() #endif } +/* + Returns true if the background is inherited; otherwise returns + false. + + Mainly used in the paintOnScreen case. +*/ +bool QWidgetPrivate::isBackgroundInherited() const +{ + Q_Q(const QWidget); + + // windows do not inherit their background + if (q->isWindow() || q->windowType() == Qt::SubWindow) + return false; + + if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) + return false; + + const QPalette &pal = q->palette(); + QPalette::ColorRole bg = q->backgroundRole(); + QBrush brush = pal.brush(bg); + + // non opaque brushes leaves us no choice, we must inherit + if (!q->autoFillBackground() || !brush.isOpaque()) + return true; + + if (brush.style() == Qt::SolidPattern) { + // the background is just a solid color. If there is no + // propagated contents, then we claim as performance + // optimization that it was not inheritet. This is the normal + // case in standard Windows or Motif style. + const QWidget *w = q->parentWidget(); + if (!w->d_func()->isBackgroundInherited()) + return false; + } + + return true; +} + void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); @@ -2152,7 +2190,7 @@ static void do_size_hints(QWidget* widget, QWExtra *x) parentWRect is the geometry of the parent's X rect, measured in parent's coord sys */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -2610,8 +2648,8 @@ int QWidget::metric(PaintDeviceMetric m) const void QWidgetPrivate::createSysExtra() { - extra->xDndProxy = 0; extra->compress_events = true; + extra->xDndProxy = 0; } void QWidgetPrivate::deleteSysExtra() @@ -2620,8 +2658,11 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { + extra->topextra->spont_unmapped = 0; + extra->topextra->dnd = 0; extra->topextra->validWMState = 0; extra->topextra->waitingForMapNotify = 0; + extra->topextra->parentWinId = 0; extra->topextra->userTimeWindow = 0; } diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 24d167e..534a425 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -1369,7 +1369,7 @@ QColor QColor::toRgb() const */ QColor QColor::toHsv() const { - if (!isValid()) + if (!isValid() || cspec == Hsv) return *this; if (cspec != Rgb) @@ -1421,7 +1421,7 @@ QColor QColor::toHsv() const */ QColor QColor::toCmyk() const { - if (!isValid()) + if (!isValid() || cspec == Cmyk) return *this; if (cspec != Rgb) return toRgb().toCmyk(); diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp index 3397c45..175f1ab 100644 --- a/src/gui/painting/qemulationpaintengine.cpp +++ b/src/gui/painting/qemulationpaintengine.cpp @@ -123,14 +123,30 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen) real_engine->stroke(path, bgPen); } - QBrush brush = pen.brush(); + QPen copy = pen; Qt::BrushStyle style = qbrush_style(brush); if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { const QGradient *g = brush.gradient(); + if (g->coordinateMode() > QGradient::LogicalMode) { - QPaintEngineEx::stroke(path, pen); - return; + if (g->coordinateMode() == QGradient::StretchToDeviceMode) { + QTransform mat = brush.transform(); + mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height()); + brush.setTransform(mat); + copy.setBrush(brush); + real_engine->stroke(path, copy); + return; + } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) { + QTransform mat = brush.transform(); + QRealRect r = path.controlPointRect(); + mat.translate(r.x1, r.y1); + mat.scale(r.x2 - r.x1, r.y2 - r.y1); + brush.setTransform(mat); + copy.setBrush(brush); + real_engine->stroke(path, copy); + return; + } } } diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 1ea40ba..3fd1ffb 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -88,11 +88,12 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti, ti.ascent.toReal(), ti.descent.toReal()); #endif - int glyph_width = metrics.width.ceil().toInt() + margin * 2; - int glyph_height = metrics.height.ceil().toInt() + margin * 2; + int glyph_width = metrics.width.ceil().toInt(); + int glyph_height = metrics.height.ceil().toInt(); if (glyph_height == 0 || glyph_width == 0) continue; - + glyph_width += margin * 2 + 2; + glyph_height += margin * 2 + 2; // align to 8-bit boundary if (m_type == QFontEngineGlyphCache::Raster_Mono) glyph_width = (glyph_width+7)&~7; @@ -188,11 +189,7 @@ void QImageTextureGlyphCache::createTextureData(int width, int height) int QImageTextureGlyphCache::glyphMargin() const { -#ifdef Q_WS_MAC return 2; -#else - return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0; -#endif } void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g) diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp index 7821feb..7f515cd 100644 --- a/src/gui/statemachine/qbasickeyeventtransition.cpp +++ b/src/gui/statemachine/qbasickeyeventtransition.cpp @@ -25,6 +25,8 @@ QT_BEGIN_NAMESPACE /*! \internal \class QBasicKeyEventTransition + \since 4.6 + \ingroup statemachine \brief The QBasicKeyEventTransition class provides a transition for Qt key events. */ @@ -156,7 +158,7 @@ void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersM /*! \reimp */ -bool QBasicKeyEventTransition::eventTest(QEvent *event) const +bool QBasicKeyEventTransition::eventTest(QEvent *event) { Q_D(const QBasicKeyEventTransition); if (event->type() == d->eventType) { diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h index 0d08da0..7506747 100644 --- a/src/gui/statemachine/qbasickeyeventtransition_p.h +++ b/src/gui/statemachine/qbasickeyeventtransition_p.h @@ -55,7 +55,7 @@ public: void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); void onTransition(QEvent *); private: diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp index 0cb727e..42b7580 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition.cpp +++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp @@ -25,6 +25,8 @@ QT_BEGIN_NAMESPACE /*! \internal \class QBasicMouseEventTransition + \since 4.6 + \ingroup statemachine \brief The QBasicMouseEventTransition class provides a transition for Qt mouse events. */ @@ -159,7 +161,7 @@ void QBasicMouseEventTransition::setPath(const QPainterPath &path) /*! \reimp */ -bool QBasicMouseEventTransition::eventTest(QEvent *event) const +bool QBasicMouseEventTransition::eventTest(QEvent *event) { Q_D(const QBasicMouseEventTransition); if (event->type() == d->eventType) { diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h index 20c7f8f..57f83c6 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition_p.h +++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h @@ -58,7 +58,7 @@ public: void setPath(const QPainterPath &path); protected: - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); void onTransition(QEvent *); private: diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index d30265a..b7563d7 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -9,13 +9,8 @@ ** ****************************************************************************/ -#ifdef QT_STATEMACHINE_SOLUTION -#include "qstatemachine.h" -#include "qstatemachine_p.h" -#else #include <QtCore/qstatemachine.h> #include <private/qstatemachine_p.h> -#endif #include <QtGui/qevent.h> #include <QtGui/qgraphicssceneevent.h> diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index e6ab11b..3cf51a3 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -140,7 +140,7 @@ void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) /*! \reimp */ -bool QKeyEventTransition::eventTest(QEvent *event) const +bool QKeyEventTransition::eventTest(QEvent *event) { Q_D(const QKeyEventTransition); if (!QEventTransition::eventTest(event)) diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index 3f797f1..08595e8 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -46,7 +46,7 @@ public: protected: void onTransition(QEvent *event); - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); private: Q_DISABLE_COPY(QKeyEventTransition) diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 3191a2f..5ffdab0 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -170,7 +170,7 @@ void QMouseEventTransition::setPath(const QPainterPath &path) /*! \reimp */ -bool QMouseEventTransition::eventTest(QEvent *event) const +bool QMouseEventTransition::eventTest(QEvent *event) { Q_D(const QMouseEventTransition); if (!QEventTransition::eventTest(event)) diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index eee971e..e878a58 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -52,7 +52,7 @@ public: protected: void onTransition(QEvent *event); - bool eventTest(QEvent *event) const; + bool eventTest(QEvent *event); private: Q_DISABLE_COPY(QMouseEventTransition) diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index c0899f8..6972803 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -1664,6 +1664,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (!styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; rect.translate(shiftX, shiftY); + p->setFont(toolbutton->font); drawItemText(p, rect, alignment, toolbutton->palette, opt->state & State_Enabled, toolbutton->text, QPalette::ButtonText); diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp index 7d4fab8..be0e3eb 100644 --- a/src/gui/styles/qmotifstyle.cpp +++ b/src/gui/styles/qmotifstyle.cpp @@ -2026,10 +2026,6 @@ QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, QSize sz(contentsSize); switch(ct) { - case CT_Splitter: - sz = QSize(10, 10); - break; - case CT_RadioButton: case CT_CheckBox: sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget); diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index 7ccac85..de4b5a3 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -1333,7 +1333,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value PM_LayoutVerticalSpacing Default \l{QLayout::spacing}{vertical spacing} for a QLayout. \value PM_MaximumDragDistance The maximum allowed distance between - the mouse and a slider when dragging. Exceeding the specified + the mouse and a scrollbar when dragging. Exceeding the specified distance will cause the slider to jump back to the original position; a value of -1 disables this behavior. diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index dcc11b8..cd44bfd 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -3030,6 +3030,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { QStyleOptionToolButton toolOpt(*tool); rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button); + toolOpt.font = rule.font.resolve(toolOpt.font); toolOpt.rect = rule.borderRect(opt->rect); bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup)); bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup; diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 639eff0..3dac9f5 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -1792,7 +1792,12 @@ case PE_Frame: return; case PE_IndicatorToolBarSeparator: - + if (option->rect.height() < 3) { + // XP style requires a few pixels for the separator + // to be visible. + QWindowsStyle::drawPrimitive(pe, option, p, widget); + return; + } name = QLatin1String("TOOLBAR"); partId = TP_SEPARATOR; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 7a236fd..6f5ee1f 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -613,7 +613,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) subpixelType = Subpixel_None; lcdFilterType = 0; #if defined(FT_LCD_FILTER_H) - lcdFilterType = (int) FT_LCD_FILTER_DEFAULT; + lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT); #endif defaultFormat = Format_None; canUploadGlyphsToServer = false; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 6551e87..feea1f2 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -1406,8 +1406,8 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin #endif #endif - QNativeImage *ni = new QNativeImage(iw + 2 * margin, - ih + 2 * margin, + QNativeImage *ni = new QNativeImage(iw + 2 * margin + 2, + ih + 2 * margin + 2, QNativeImage::systemFormat(), true); ni->image.fill(0xffffffff); @@ -1449,7 +1449,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) font = CreateFontIndirectW(&lf); } - QNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform); + QNativeImage *mask = drawGDIGlyph(font, glyph, 2, xform); if (mask == 0) return QImage(); diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 9886969..0d8b4de 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -873,21 +873,22 @@ bool QAbstractScrollArea::event(QEvent *e) case QEvent::Resize: d->layoutChildren(); break; - case QEvent::Paint: + case QEvent::Paint: { + QStyleOption option; + option.initFrom(this); if (d->cornerPaintingRect.isValid()) { - QStyleOption option; option.rect = d->cornerPaintingRect; QPainter p(this); style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this); } #ifdef Q_WS_MAC if (d->reverseCornerPaintingRect.isValid()) { - QStyleOption option; option.rect = d->reverseCornerPaintingRect; QPainter p(this); style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this); } #endif + } QFrame::paintEvent((QPaintEvent*)e); break; #ifndef QT_NO_CONTEXTMENU diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 347f89a..d640c70 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -193,6 +193,7 @@ void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols) Q_D(QAbstractSpinBox); if (d->buttonSymbols != buttonSymbols) { d->buttonSymbols = buttonSymbols; + d->updateEditFieldGeometry(); update(); } } diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index 0befa6d..2ce89f9 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -214,7 +214,7 @@ static HWND qt_wce_create_menubar(HWND parentHandle, HINSTANCE resourceHandle, i mbi.nToolBarId = toolbarID; if (ptrCreateMenuBar(&mbi)) { -#ifdef Q_WS_WINCE_WM +#ifdef Q_OS_WINCE_WM // Tell the menu bar that we want to override hot key behaviour. LPARAM lparam = MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY); diff --git a/src/gui/widgets/qslider.cpp b/src/gui/widgets/qslider.cpp index 32b9021..5b9c8a4 100644 --- a/src/gui/widgets/qslider.cpp +++ b/src/gui/widgets/qslider.cpp @@ -62,7 +62,6 @@ public: int tickInterval; QSlider::TickPosition tickPosition; int clickOffset; - int snapBackPosition; void init(); void resetLayoutItemMargins(); int pixelPosToRangeValue(int pos) const; @@ -493,7 +492,6 @@ void QSlider::mousePressEvent(QMouseEvent *ev) setRepeatAction(SliderNoAction); QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); d->clickOffset = d->pick(ev->pos() - sr.topLeft()); - d->snapBackPosition = d->position; update(sr); setSliderDown(true); } @@ -513,14 +511,6 @@ void QSlider::mouseMoveEvent(QMouseEvent *ev) int newPosition = d->pixelPosToRangeValue(d->pick(ev->pos()) - d->clickOffset); QStyleOptionSlider opt; initStyleOption(&opt); - int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this); - if (m >= 0) { - QRect r = rect(); - r.adjust(-m, -m, m, m); - if (!r.contains(ev->pos())) { - newPosition = d->snapBackPosition; - } - } setSliderPosition(newPosition); } diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 5940fba..d4bf008 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qhttpnetworkconnection_p.h" +#include "private/qnoncontiguousbytedevice_p.h" #include <private/qnetworkrequest_p.h> #include <private/qobject_p.h> #include <private/qauthenticator_p.h> @@ -71,6 +72,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif + { } @@ -205,12 +207,19 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) // add missing fields for the request QByteArray value; // check if Content-Length is provided - QIODevice *data = request.data(); - if (data && request.contentLength() == -1) { - if (!data->isSequential()) - request.setContentLength(data->size()); - else - bufferData(messagePair); // ### or do chunked upload + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (uploadByteDevice) { + if (request.contentLength() != -1 && uploadByteDevice->size() != -1) { + // both values known, take the smaller one. + request.setContentLength(qMin(uploadByteDevice->size(), request.contentLength())); + } else if (request.contentLength() == -1 && uploadByteDevice->size() != -1) { + // content length not supplied by user, but the upload device knows it + request.setContentLength(uploadByteDevice->size()); + } else if (request.contentLength() != -1 && uploadByteDevice->size() == -1) { + // everything OK, the user supplied us the contentLength + } else if (request.contentLength() == -1 && uploadByteDevice->size() == -1) { + qFatal("QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given"); + } } // set the Connection/Proxy-Connection: Keep-Alive headers #ifndef QT_NO_NETWORKPROXY @@ -361,18 +370,12 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) false); #endif socket->write(header); - QIODevice *data = channels[i].request.d->data; - QHttpNetworkReply *reply = channels[i].reply; - if (reply && reply->d_func()->requestDataBuffer.size()) - data = &channels[i].reply->d_func()->requestDataBuffer; - if (data && (data->isOpen() || data->open(QIODevice::ReadOnly))) { - if (data->isSequential()) { - channels[i].bytesTotal = -1; - QObject::connect(data, SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadNoBuffer())); - QObject::connect(data, SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadNoBuffer())); - } else { - channels[i].bytesTotal = data->size(); - } + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + // connect the signals so this function gets called again + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + + channels[i].bytesTotal = channels[i].request.contentLength(); } else { channels[i].state = WaitingState; break; @@ -380,30 +383,81 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) // write the initial chunk together with the headers // fall through } - case WritingState: { // write the data - QIODevice *data = channels[i].request.d->data; - if (channels[i].reply->d_func()->requestDataBuffer.size()) - data = &channels[i].reply->d_func()->requestDataBuffer; - if (!data || channels[i].bytesTotal == channels[i].written) { + case WritingState: + { + // write the data + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (!uploadByteDevice || channels[i].bytesTotal == channels[i].written) { + if (uploadByteDevice) + emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); channels[i].state = WaitingState; // now wait for response + sendRequest(socket); break; } - QByteArray chunk; - chunk.resize(ChunkSize); - qint64 readSize = data->read(chunk.data(), ChunkSize); - if (readSize == -1) { - // source has reached EOF - channels[i].state = WaitingState; // now wait for response - } else if (readSize > 0) { - // source gave us something useful - channels[i].written += socket->write(chunk.data(), readSize); - if (channels[i].reply) - emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); + // only feed the QTcpSocket buffer when there is less than 32 kB in it + const qint64 socketBufferFill = 32*1024; + const qint64 socketWriteMaxSize = 16*1024; + + +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); + while ((sslSocket->encryptedBytesToWrite() + sslSocket->bytesToWrite()) <= socketBufferFill + && channels[i].bytesTotal != channels[i].written) +#else + while (socket->bytesToWrite() <= socketBufferFill + && channels[i].bytesTotal != channels[i].written) +#endif + { + // get pointer to upload data + qint64 currentReadSize; + qint64 desiredReadSize = qMin(socketWriteMaxSize, channels[i].bytesTotal - channels[i].written); + const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize); + + if (currentReadSize == -1) { + // premature eof happened + emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); + return false; + break; + } else if (readPointer == 0 || currentReadSize == 0) { + // nothing to read currently, break the loop + break; + } else { + qint64 currentWriteSize = socket->write(readPointer, currentReadSize); + if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { + // socket broke down + emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); + return false; + } else { + channels[i].written += currentWriteSize; + uploadByteDevice->advanceReadPointer(currentWriteSize); + + emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); + + if (channels[i].written == channels[i].bytesTotal) { + // make sure this function is called once again + channels[i].state = WaitingState; + sendRequest(socket); + break; + } + } + } } break; } + case WaitingState: + { + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + } + // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called + // this is needed if the sends an reply before we have finished sending the request. In that + // case receiveReply had been called before but ignored the server reply + receiveReply(socket, channels[i].reply); + break; + } case ReadingState: case Wait4AuthState: // ignore _q_bytesWritten in these states @@ -479,6 +533,9 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork // make sure that the reply is valid if (channels[i].reply != reply) return true; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); // make sure that the reply is valid if (channels[i].reply != reply) @@ -529,10 +586,20 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState; switch (state) { case QHttpNetworkReplyPrivate::NothingDoneState: - case QHttpNetworkReplyPrivate::ReadingStatusState: - bytes += reply->d_func()->readStatus(socket); + case QHttpNetworkReplyPrivate::ReadingStatusState: { + qint64 statusBytes = reply->d_func()->readStatus(socket); + if (statusBytes == -1) { + // error reading the status, close the socket and emit error + socket->close(); + reply->d_func()->errorString = errorDetail(QNetworkReply::ProtocolFailure, socket); + emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); + break; + } + bytes += statusBytes; channels[i].lastStatus = reply->d_func()->statusCode; break; + } case QHttpNetworkReplyPrivate::ReadingHeaderState: bytes += reply->d_func()->readHeader(socket); if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { @@ -569,6 +636,9 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN // make sure that the reply is valid if (channels[i].reply != reply) return; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); // make sure that the reply is valid if (channels[i].reply != reply) @@ -635,8 +705,25 @@ void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpN case 407: handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend); if (resend) { + int i = indexOf(socket); + + QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); + if (uploadByteDevice) { + if (uploadByteDevice->reset()) { + channels[i].written = 0; + } else { + emitReplyError(socket, reply, QNetworkReply::ContentReSendError); + break; + } + } + eraseData(reply); - sendRequest(socket); + + // also use async _q_startNextRequest so we dont break with closed + // proxy or server connections.. + channels[i].resendCurrent = true; + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); + } break; default: @@ -970,6 +1057,7 @@ void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes) QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender()); if (!socket) return; // ### error + // bytes have been written to the socket. write even more of them :) if (isSocketWriting(socket)) sendRequest(socket); // otherwise we do nothing @@ -1128,80 +1216,21 @@ void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetwor } #endif -void QHttpNetworkConnectionPrivate::_q_dataReadyReadNoBuffer() +void QHttpNetworkConnectionPrivate::_q_uploadDataReadyRead() { Q_Q(QHttpNetworkConnection); - // data emitted either readyRead() + // upload data emitted readyRead() // find out which channel it is for - QIODevice *sender = qobject_cast<QIODevice *>(q->sender()); + QObject *sender = q->sender(); - // won't match anything if the qobject_cast above failed for (int i = 0; i < channelCount; ++i) { - if (sender == channels[i].request.data()) { + if (sender == channels[i].request.uploadByteDevice()) { sendRequest(channels[i].socket); break; } } } -void QHttpNetworkConnectionPrivate::_q_dataReadyReadBuffer() -{ - Q_Q(QHttpNetworkConnection); - QIODevice *sender = qobject_cast<QIODevice *>(q->sender()); - HttpMessagePair *thePair = 0; - for (int i = 0; !thePair && i < lowPriorityQueue.size(); ++i) - if (lowPriorityQueue.at(i).first.data() == sender) - thePair = &lowPriorityQueue[i]; - - for (int i = 0; !thePair && i < highPriorityQueue.size(); ++i) - if (highPriorityQueue.at(i).first.data() == sender) - thePair = &highPriorityQueue[i]; - - if (thePair) { - bufferData(*thePair); - - // are we finished buffering? - if (!thePair->second->d_func()->requestIsBuffering) - _q_startNextRequest(); - } -} - -void QHttpNetworkConnectionPrivate::bufferData(HttpMessagePair &messagePair) -{ - Q_Q(QHttpNetworkConnection); - QHttpNetworkRequest &request = messagePair.first; - QHttpNetworkReply *reply = messagePair.second; - Q_ASSERT(request.data()); - if (!reply->d_func()->requestIsBuffering) { // first time - QObject::connect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer())); - QObject::connect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer())); - reply->d_func()->requestIsBuffering = true; - reply->d_func()->requestDataBuffer.open(QIODevice::ReadWrite); - } - - // always try to read at least one byte - // ### FIXME! use a QRingBuffer - qint64 bytesToRead = qMax<qint64>(1, request.data()->bytesAvailable()); - QByteArray newData; - newData.resize(bytesToRead); - qint64 bytesActuallyRead = request.data()->read(newData.data(), bytesToRead); - - if (bytesActuallyRead > 0) { - // we read something - newData.chop(bytesToRead - bytesActuallyRead); - reply->d_func()->requestDataBuffer.write(newData); - } else if (bytesActuallyRead == -1) { // last time - QObject::disconnect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer())); - QObject::disconnect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer())); - - request.setContentLength(reply->d_func()->requestDataBuffer.size()); - reply->d_func()->requestDataBuffer.seek(0); - reply->d_func()->requestIsBuffering = false; - } -} - -// QHttpNetworkConnection - QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) { diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 09bd459..9b127dd 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -146,8 +146,7 @@ private: #ifndef QT_NO_NETWORKPROXY Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)) #endif - Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadBuffer()) - Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadNoBuffer()) + Q_PRIVATE_SLOT(d_func(), void _q_uploadDataReadyRead()) #ifndef QT_NO_OPENSSL Q_PRIVATE_SLOT(d_func(), void _q_encrypted()) @@ -209,8 +208,8 @@ public: #ifndef QT_NO_NETWORKPROXY void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy #endif - void _q_dataReadyReadNoBuffer(); - void _q_dataReadyReadBuffer(); + + void _q_uploadDataReadyRead(); void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); bool ensureConnection(QAbstractSocket *socket); @@ -219,7 +218,6 @@ public: #ifndef QT_NO_COMPRESS bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); #endif - void bufferData(HttpMessagePair &request); void removeReply(QHttpNetworkReply *reply); QString hostName; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index fe3f6af..310994c 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -409,39 +409,62 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) if (fragment.endsWith('\r')) { fragment.truncate(fragment.length()-1); } - parseStatus(fragment); + bool ok = parseStatus(fragment); state = ReadingHeaderState; fragment.clear(); // next fragment + + if (!ok) + return -1; break; } else { c = 0; bytes += socket->read(&c, 1); fragment.append(c); } + + // is this a valid reply? + if (fragment.length() >= 5 && !fragment.startsWith("HTTP/")) + return -1; + } + return bytes; } -void QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) +bool QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status) { - const QByteArrayMatcher sp(" "); - int i = sp.indexIn(status); - const QByteArray version = status.mid(0, i); - int j = sp.indexIn(status, i + 1); + // from RFC 2616: + // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF + // HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT + // that makes: 'HTTP/n.n xxx Message' + // byte count: 0123456789012 + + static const int minLength = 11; + static const int dotPos = 6; + static const int spacePos = 8; + static const char httpMagic[] = "HTTP/"; + + if (status.length() < minLength + || !status.startsWith(httpMagic) + || status.at(dotPos) != '.' + || status.at(spacePos) != ' ') { + // I don't know how to parse this status line + return false; + } + + // optimize for the valid case: defer checking until the end + majorVersion = status.at(dotPos - 1) - '0'; + minorVersion = status.at(dotPos + 1) - '0'; + + int i = spacePos; + int j = status.indexOf(' ', i + 1); // j == -1 || at(j) == ' ' so j+1 == 0 && j+1 <= length() const QByteArray code = status.mid(i + 1, j - i - 1); - const QByteArray reason = status.mid(j + 1, status.count() - j); - const QByteArrayMatcher slash("/"); - int k = slash.indexIn(version); - const QByteArrayMatcher dot("."); - int l = dot.indexIn(version, k); - const QByteArray major = version.mid(k + 1, l - k - 1); - const QByteArray minor = version.mid(l + 1, version.count() - l); + bool ok; + statusCode = code.toInt(&ok); + reasonPhrase = QString::fromLatin1(status.constData() + j + 1); - majorVersion = QString::fromAscii(major.constData()).toInt(); - minorVersion = QString::fromAscii(minor.constData()).toInt(); - statusCode = QString::fromAscii(code.constData()).toInt(); - reasonPhrase = QString::fromAscii(reason.constData()); + return ok && uint(majorVersion) <= 9 && uint(minorVersion) <= 9; } qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) @@ -521,13 +544,13 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou { qint64 bytes = 0; if (isChunked()) { - bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) + bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) } else if (bodyLength > 0) { // we have a Content-Length - bytes += transferRaw(socket, out, bodyLength - contentRead); + bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead); if (contentRead + bytes == bodyLength) state = AllDoneState; } else { - bytes += transferRaw(socket, out, socket->bytesAvailable()); + bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } if (state == AllDoneState) socket->readAll(); // Read the rest to clean (CRLF) @@ -535,7 +558,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou return bytes; } -qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size) { qint64 bytes = 0; Q_ASSERT(in); @@ -561,7 +584,7 @@ qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint } -qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QIODevice *out) { qint64 bytes = 0; while (in->bytesAvailable()) { // while we can read from input @@ -660,4 +683,4 @@ void QHttpNetworkReply::ignoreSslErrors() QT_END_NAMESPACE -#endif // QT_NO_HTTP
\ No newline at end of file +#endif // QT_NO_HTTP diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index c17c65c..cc5cce8 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -139,7 +139,7 @@ Q_SIGNALS: void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); void headerChanged(); void dataReadProgress(int done, int total); - void dataSendProgress(int done, int total); + void dataSendProgress(qint64 done, qint64 total); private: Q_DECLARE_PRIVATE(QHttpNetworkReply) @@ -154,7 +154,7 @@ public: QHttpNetworkReplyPrivate(const QUrl &newUrl = QUrl()); ~QHttpNetworkReplyPrivate(); qint64 readStatus(QAbstractSocket *socket); - void parseStatus(const QByteArray &status); + bool parseStatus(const QByteArray &status); qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QIODevice *out); @@ -162,8 +162,8 @@ public: QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); - qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size); - qint64 transferChunked(QIODevice *in, QIODevice *out); + qint64 readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size); + qint64 readReplyBodyChunked(QIODevice *in, QIODevice *out); qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); qint64 bytesAvailable() const; @@ -206,7 +206,6 @@ public: QByteArray responseData; // uncompressed body QByteArray compressedData; // compressed body (temporary) - QBuffer requestDataBuffer; bool requestIsBuffering; bool requestIsPrepared; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 420cb69..7df68fc 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -40,12 +40,13 @@ ****************************************************************************/ #include "qhttpnetworkrequest_p.h" +#include "private/qnoncontiguousbytedevice_p.h" QT_BEGIN_NAMESPACE QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, QHttpNetworkRequest::Priority pri, const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0), + : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0), autoDecompress(false) { } @@ -55,7 +56,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest { operation = other.operation; priority = other.priority; - data = other.data; + uploadByteDevice = other.uploadByteDevice; autoDecompress = other.autoDecompress; } @@ -67,7 +68,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) - && (data == other.data); + && (uploadByteDevice == other.uploadByteDevice); } QByteArray QHttpNetworkRequestPrivate::methodName() const @@ -109,7 +110,7 @@ QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const QUrl::FormattingOptions format(QUrl::RemoveFragment); // for POST, query data is send as content - if (operation == QHttpNetworkRequest::Post && !data) + if (operation == QHttpNetworkRequest::Post && !uploadByteDevice) format |= QUrl::RemoveQuery; // for requests through proxy, the Request-URI contains full url if (throughProxy) @@ -140,7 +141,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request // add content type, if not set in the request if (request.headerField("content-type").isEmpty()) ba += "Content-Type: application/x-www-form-urlencoded\r\n"; - if (!request.d->data && request.d->url.hasQuery()) { + if (!request.d->uploadByteDevice && request.d->url.hasQuery()) { QByteArray query = request.d->url.encodedQuery(); ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n"; ba += "\r\n"; @@ -236,14 +237,14 @@ void QHttpNetworkRequest::setPriority(Priority priority) d->priority = priority; } -QIODevice *QHttpNetworkRequest::data() const +void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd) { - return d->data; + d->uploadByteDevice = bd; } -void QHttpNetworkRequest::setData(QIODevice *data) +QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const { - d->data = data; + return d->uploadByteDevice; } int QHttpNetworkRequest::majorVersion() const diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index d18e116..ed4325a 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +class QNonContiguousByteDevice; + class QHttpNetworkRequestPrivate; class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader { @@ -104,8 +106,8 @@ public: Priority priority() const; void setPriority(Priority priority); - QIODevice *data() const; - void setData(QIODevice *data); + void setUploadByteDevice(QNonContiguousByteDevice *bd); + QNonContiguousByteDevice* uploadByteDevice() const; private: QSharedDataPointer<QHttpNetworkRequestPrivate> d; @@ -113,7 +115,6 @@ private: friend class QHttpNetworkConnectionPrivate; }; - class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate { public: @@ -129,7 +130,7 @@ public: QHttpNetworkRequest::Operation operation; QHttpNetworkRequest::Priority priority; - mutable QIODevice *data; + mutable QNonContiguousByteDevice* uploadByteDevice; bool autoDecompress; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index df468b8..b9d1b85 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -50,6 +50,8 @@ #include "qnetworkaccesscachebackend_p.h" #include "qabstractnetworkcache.h" +#include "private/qnoncontiguousbytedevice_p.h" + QT_BEGIN_NAMESPACE static bool factoryDataShutdown = false; @@ -109,17 +111,43 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM return 0; } -QNetworkAccessBackend::QNetworkAccessBackend() + +QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() { + QNonContiguousByteDevice* device = 0; + + if (reply->outgoingDataBuffer) + device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer); + else + device = QNonContiguousByteDeviceFactory::create(reply->outgoingData); + + bool bufferDisallowed = + reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, + QVariant(false)) == QVariant(true); + if (bufferDisallowed) + device->disableReset(); + + // make sure we delete this later + device->setParent(this); + + connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64))); + + return device; } -QNetworkAccessBackend::~QNetworkAccessBackend() +// need to have this function since the reply is a private member variable +// and the special backends need to access this. +void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) { + reply->emitUploadProgress(bytesSent, bytesTotal); } -void QNetworkAccessBackend::upstreamReadyRead() +QNetworkAccessBackend::QNetworkAccessBackend() +{ +} + +QNetworkAccessBackend::~QNetworkAccessBackend() { - // do nothing } void QNetworkAccessBackend::downstreamReadyWrite() @@ -184,23 +212,6 @@ bool QNetworkAccessBackend::isCachingEnabled() const return reply->isCachingEnabled(); } -qint64 QNetworkAccessBackend::upstreamBytesAvailable() const -{ - return reply->writeBuffer.size(); -} - -void QNetworkAccessBackend::upstreamBytesConsumed(qint64 count) -{ - // remove count bytes from the write buffer - reply->consume(count); -} - -QByteArray QNetworkAccessBackend::readUpstream() -{ - // ### this is expensive. Consider making QRingBuffer::peekAll keep the buffer it returns - return reply->writeBuffer.peek(upstreamBytesAvailable()); -} - qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const { return reply->nextDownstreamBlockSize(); @@ -213,12 +224,12 @@ qint64 QNetworkAccessBackend::downstreamBytesToConsume() const void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data) { - reply->feed(data); + reply->appendDownstreamData(data); } void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) { - reply->feed(data); + reply->appendDownstreamData(data); } QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 9012396..6035f3a 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -70,6 +70,8 @@ class QNetworkAccessManagerPrivate; class QNetworkReplyImplPrivate; class QAbstractNetworkCache; class QNetworkCacheMetaData; +class QNetworkAccessBackendUploadIODevice; +class QNonContiguousByteDevice; // Should support direct file upload from disk or download to disk. // @@ -86,14 +88,13 @@ public: // have different names. The Connection has two streams: // // - Upstream: - // Upstream is data that is being written into this connection, - // from the user. Upstream operates in a "pull" mechanism: the - // connection will be notified that there is more data available - // by a call to "upstreamReadyRead". The number of bytes - // available is given by upstreamBytesAvailable(). A call to - // readUpstream() always yields the entire upstream buffer. When - // the connection has processed a certain amount of bytes from - // that buffer, it should call upstreamBytesConsumed(). + // The upstream uses a QNonContiguousByteDevice provided + // by the backend. This device emits the usual readyRead() + // signal when the backend has data available for the connection + // to write. The different backends can listen on this signal + // and then pull upload data from the QNonContiguousByteDevice and + // deal with it. + // // // - Downstream: // Downstream is the data that is being read from this @@ -111,12 +112,9 @@ public: virtual void open() = 0; virtual void closeDownstreamChannel() = 0; - virtual void closeUpstreamChannel() = 0; virtual bool waitForDownstreamReadyRead(int msecs) = 0; - virtual bool waitForUpstreamBytesWritten(int msecs) = 0; // slot-like: - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); virtual void copyFinished(QIODevice *); virtual void ignoreSslErrors(); @@ -155,18 +153,24 @@ public: QVariant attribute(QNetworkRequest::Attribute code) const; void setAttribute(QNetworkRequest::Attribute code, const QVariant &value); + // return true if the QNonContiguousByteDevice of the upload + // data needs to support reset(). Currently needed for HTTP. + // This will possibly enable buffering of the upload data. + virtual bool needsResetableUploadData() {return false;}; + protected: - // these functions control the upstream mechanism - // that is, data coming into the backend and out via the connection - qint64 upstreamBytesAvailable() const; - void upstreamBytesConsumed(qint64 count); - QByteArray readUpstream(); + // Create the device used for reading the upload data + QNonContiguousByteDevice* createUploadByteDevice(); + // these functions control the downstream mechanism // that is, data that has come via the connection and is going out the backend qint64 nextDownstreamBlockSize() const; qint64 downstreamBytesToConsume() const; void writeDownstreamData(const QByteArray &data); + +public slots: + // for task 251801, needs to be a slot to be called asynchronously void writeDownstreamData(QIODevice *data); protected slots: @@ -179,10 +183,12 @@ protected slots: void metaDataChanged(); void redirectionRequested(const QUrl &destination); void sslErrors(const QList<QSslError> &errors); + void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); private: friend class QNetworkAccessManager; friend class QNetworkAccessManagerPrivate; + friend class QNetworkAccessBackendUploadIODevice; QNetworkAccessManagerPrivate *manager; QNetworkReplyImplPrivate *reply; }; diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp index 2e5f1b1..d4bda9a 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend.cpp +++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp @@ -41,6 +41,8 @@ #include "qnetworkaccessdebugpipebackend_p.h" #include "QtCore/qdatastream.h" +#include <QCoreApplication> +#include "private/qnoncontiguousbytedevice_p.h" QT_BEGIN_NAMESPACE @@ -51,12 +53,6 @@ enum { WriteBufferSize = ReadBufferSize }; -struct QNetworkAccessDebugPipeBackend::DataPacket -{ - QList<QPair<QByteArray, QByteArray> > headers; - QByteArray data; -}; - QNetworkAccessBackend * QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const @@ -79,12 +75,14 @@ QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation o } QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend() - : incomingPacketSize(0), bareProtocol(false) + : bareProtocol(false), hasUploadFinished(false), hasDownloadFinished(false), + hasEverythingFinished(false), bytesDownloaded(0), bytesUploaded(0) { } QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend() { + // this is signals disconnect, not network! socket.disconnect(this); // we're not interested in the signals at this point } @@ -92,160 +90,150 @@ void QNetworkAccessDebugPipeBackend::open() { socket.connectToHost(url().host(), url().port(12345)); socket.setReadBufferSize(ReadBufferSize); + + // socket ready read -> we can push from socket to downstream connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead())); - connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError())); connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected())); + connect(&socket, SIGNAL(connected()), SLOT(socketConnected())); + // socket bytes written -> we can push more from upstream to socket + connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1"); - if (!bareProtocol) { - // "Handshake": - // send outgoing metadata and the URL being requested - DataPacket packet; - //packet.metaData = request().metaData(); - packet.data = url().toEncoded(); - send(packet); + if (operation() == QNetworkAccessManager::PutOperation) { + uploadByteDevice = createUploadByteDevice(); + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot())); + QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); } } -void QNetworkAccessDebugPipeBackend::closeDownstreamChannel() +void QNetworkAccessDebugPipeBackend::socketReadyRead() { - if (operation() == QNetworkAccessManager::GetOperation) - socket.disconnectFromHost(); + pushFromSocketToDownstream(); } -void QNetworkAccessDebugPipeBackend::closeUpstreamChannel() +void QNetworkAccessDebugPipeBackend::downstreamReadyWrite() { - if (operation() == QNetworkAccessManager::PutOperation) - socket.disconnectFromHost(); - else if (operation() == QNetworkAccessManager::PostOperation) { - send(DataPacket()); - } + pushFromSocketToDownstream(); } -bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms) +void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64) { - readyReadEmitted = false; - if (socket.bytesAvailable()) { - socketReadyRead(); - if (readyReadEmitted) - return true; - } - socket.waitForReadyRead(ms); - return readyReadEmitted; + pushFromUpstreamToSocket(); } -bool QNetworkAccessDebugPipeBackend::waitForUpstreamBytesWritten(int ms) +void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot() { - bytesWrittenEmitted = false; - upstreamReadyRead(); - if (bytesWrittenEmitted) - return true; - - socket.waitForBytesWritten(ms); - return bytesWrittenEmitted; + pushFromUpstreamToSocket(); } -void QNetworkAccessDebugPipeBackend::upstreamReadyRead() +void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream() { - int maxWrite = WriteBufferSize - socket.bytesToWrite(); - if (maxWrite <= 0) - return; // can't write yet, wait for the socket to write - - if (bareProtocol) { - QByteArray data = readUpstream(); - if (data.isEmpty()) - return; + QByteArray buffer; - socket.write(data); - upstreamBytesConsumed(data.size()); - bytesWrittenEmitted = true; + if (socket.state() == QAbstractSocket::ConnectingState) { return; } - DataPacket packet; - packet.data = readUpstream(); - if (packet.data.isEmpty()) - return; // we'll be called again when there's data - if (packet.data.size() > maxWrite) - packet.data.truncate(maxWrite); - - if (!send(packet)) { - QString msg = QObject::tr("Write error writing to %1: %2") - .arg(url().toString(), socket.errorString()); - error(QNetworkReply::ProtocolFailure, msg); + forever { + if (hasDownloadFinished) + return; - finished(); - return; + buffer.resize(ReadBufferSize); + qint64 haveRead = socket.read(buffer.data(), ReadBufferSize); + + if (haveRead == -1) { + hasDownloadFinished = true; + // this ensures a good last downloadProgress is emitted + setHeader(QNetworkRequest::ContentLengthHeader, QVariant()); + possiblyFinish(); + break; + } else if (haveRead == 0) { + break; + } else { + // have read something + buffer.resize(haveRead); + bytesDownloaded += haveRead; + writeDownstreamData(buffer); + } } - upstreamBytesConsumed(packet.data.size()); - bytesWrittenEmitted = true; } -void QNetworkAccessDebugPipeBackend::downstreamReadyWrite() +void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket() { - socketReadyRead(); -} + // FIXME + if (operation() == QNetworkAccessManager::PutOperation) { + if (hasUploadFinished) + return; -void QNetworkAccessDebugPipeBackend::socketReadyRead() -{ - if (bareProtocol) { - qint64 bytesToRead = socket.bytesAvailable(); - if (bytesToRead) { - QByteArray buffer; - buffer.resize(bytesToRead); - qint64 bytesRead = socket.read(buffer.data(), bytesToRead); - if (bytesRead < bytesToRead) - buffer.truncate(bytesRead); - writeDownstreamData(buffer); - readyReadEmitted = true; + forever { + if (socket.bytesToWrite() >= WriteBufferSize) + return; + + qint64 haveRead; + const char *readPointer = uploadByteDevice->readPointer(WriteBufferSize, haveRead); + if (haveRead == -1) { + // EOF + hasUploadFinished = true; + emitReplyUploadProgress(bytesUploaded, bytesUploaded); + possiblyFinish(); + break; + } else if (haveRead == 0 || readPointer == 0) { + // nothing to read right now, we will be called again later + break; + } else { + qint64 haveWritten; + haveWritten = socket.write(readPointer, haveRead); + + if (haveWritten < 0) { + // write error! + QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2") + .arg(url().toString(), socket.errorString()); + error(QNetworkReply::ProtocolFailure, msg); + finished(); + return; + } else { + uploadByteDevice->advanceReadPointer(haveWritten); + bytesUploaded += haveWritten; + emitReplyUploadProgress(bytesUploaded, -1); + } + + //QCoreApplication::processEvents(); + + } } - return; } +} - while (canReceive() && - (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) { - DataPacket packet; - if (receive(packet)) { - if (!packet.headers.isEmpty()) { - QList<QPair<QByteArray, QByteArray> >::ConstIterator - it = packet.headers.constBegin(), - end = packet.headers.constEnd(); - for ( ; it != end; ++it) - setRawHeader(it->first, it->second); - metaDataChanged(); - } +void QNetworkAccessDebugPipeBackend::possiblyFinish() +{ + if (hasEverythingFinished) + return; + hasEverythingFinished = true; - if (!packet.data.isEmpty()) { - writeDownstreamData(packet.data); - readyReadEmitted = true; - } + if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) { + socket.close(); + finished(); + } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) { + socket.close(); + finished(); + } - if (packet.headers.isEmpty() && packet.data.isEmpty()) { - // it's an eof - socket.close(); - readyReadEmitted = true; - } - } else { - // got an error - QString msg = QObject::tr("Read error reading from %1: %2") - .arg(url().toString(), socket.errorString()); - error(QNetworkReply::ProtocolFailure, msg); - finished(); - return; - } - } } -void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64) +void QNetworkAccessDebugPipeBackend::closeDownstreamChannel() { - upstreamReadyRead(); + qWarning() << "QNetworkAccessDebugPipeBackend::closeDownstreamChannel()" << operation(); + //if (operation() == QNetworkAccessManager::GetOperation) + // socket.disconnectFromHost(); } + void QNetworkAccessDebugPipeBackend::socketError() { + qWarning() << "QNetworkAccessDebugPipeBackend::socketError()" << socket.error(); QNetworkReply::NetworkError code; switch (socket.error()) { case QAbstractSocket::RemoteHostClosedError: @@ -269,76 +257,27 @@ void QNetworkAccessDebugPipeBackend::socketError() void QNetworkAccessDebugPipeBackend::socketDisconnected() { - socketReadyRead(); - if (incomingPacketSize == 0 && socket.bytesToWrite() == 0) { + pushFromSocketToDownstream(); + + if (socket.bytesToWrite() == 0) { // normal close - finished(); } else { // abnormal close QString msg = QObject::tr("Remote host closed the connection prematurely on %1") .arg(url().toString()); error(QNetworkReply::RemoteHostClosedError, msg); - finished(); } } -bool QNetworkAccessDebugPipeBackend::send(const DataPacket &packet) -{ - QByteArray ba; - { - QDataStream stream(&ba, QIODevice::WriteOnly); - stream.setVersion(QDataStream::Qt_4_4); - - stream << packet.headers << packet.data; - } - - qint32 outgoingPacketSize = ba.size(); - qint64 written = socket.write((const char*)&outgoingPacketSize, sizeof outgoingPacketSize); - written += socket.write(ba); - return quint64(written) == (outgoingPacketSize + sizeof outgoingPacketSize); -} - -bool QNetworkAccessDebugPipeBackend::receive(DataPacket &packet) +void QNetworkAccessDebugPipeBackend::socketConnected() { - if (!canReceive()) - return false; - - // canReceive() does the setting up for us - Q_ASSERT(socket.bytesAvailable() >= incomingPacketSize); - QByteArray incomingPacket = socket.read(incomingPacketSize); - QDataStream stream(&incomingPacket, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_4_4); - stream >> packet.headers >> packet.data; - - // reset for next packet: - incomingPacketSize = 0; - socket.setReadBufferSize(ReadBufferSize); - return true; } -bool QNetworkAccessDebugPipeBackend::canReceive() +bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms) { - if (incomingPacketSize == 0) { - // read the packet size - if (quint64(socket.bytesAvailable()) >= sizeof incomingPacketSize) - socket.read((char*)&incomingPacketSize, sizeof incomingPacketSize); - else - return false; - } - - if (incomingPacketSize == 0) { - QString msg = QObject::tr("Protocol error: packet of size 0 received"); - error(QNetworkReply::ProtocolFailure, msg); - finished(); - - socket.blockSignals(true); - socket.abort(); - socket.blockSignals(false); - return false; - } - - return socket.bytesAvailable() >= incomingPacketSize; + qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()"); + return false; } #endif diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h index 73a35cf..a13edc4 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend_p.h +++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h @@ -66,35 +66,38 @@ class QNetworkAccessDebugPipeBackend: public QNetworkAccessBackend { Q_OBJECT public: - struct DataPacket; QNetworkAccessDebugPipeBackend(); virtual ~QNetworkAccessDebugPipeBackend(); virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); +protected: + void pushFromSocketToDownstream(); + void pushFromUpstreamToSocket(); + void possiblyFinish(); + QNonContiguousByteDevice *uploadByteDevice; + private slots: + void uploadReadyReadSlot(); void socketReadyRead(); void socketBytesWritten(qint64 bytes); void socketError(); void socketDisconnected(); + void socketConnected(); private: QTcpSocket socket; - qint32 incomingPacketSize; - bool readyReadEmitted; - bool bytesWrittenEmitted; bool bareProtocol; + bool hasUploadFinished; + bool hasDownloadFinished; + bool hasEverythingFinished; - bool send(const DataPacket &packet); - bool canReceive(); - bool receive(DataPacket &packet); + qint64 bytesDownloaded; + qint64 bytesUploaded; }; class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index 8a5a665..6374fde 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -43,6 +43,7 @@ #include "qfileinfo.h" #include "qurlinfo.h" #include "qdir.h" +#include "private/qnoncontiguousbytedevice_p.h" #include <QtCore/QCoreApplication> @@ -77,7 +78,7 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, } QNetworkAccessFileBackend::QNetworkAccessFileBackend() - : totalBytes(0) + : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false) { } @@ -126,6 +127,9 @@ void QNetworkAccessFileBackend::open() break; case QNetworkAccessManager::PutOperation: mode = QIODevice::WriteOnly | QIODevice::Truncate; + uploadByteDevice = createUploadByteDevice(); + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot())); + QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection); break; default: Q_ASSERT_X(false, "QNetworkAccessFileBackend::open", @@ -152,19 +156,50 @@ void QNetworkAccessFileBackend::open() } } -void QNetworkAccessFileBackend::closeDownstreamChannel() +void QNetworkAccessFileBackend::uploadReadyReadSlot() { - if (operation() == QNetworkAccessManager::GetOperation) { - file.close(); - //downstreamChannelClosed(); + if (hasUploadFinished) + return; + + forever { + qint64 haveRead; + const char *readPointer = uploadByteDevice->readPointer(-1, haveRead); + if (haveRead == -1) { + // EOF + hasUploadFinished = true; + file.flush(); + file.close(); + finished(); + break; + } else if (haveRead == 0 || readPointer == 0) { + // nothing to read right now, we will be called again later + break; + } else { + qint64 haveWritten; + haveWritten = file.write(readPointer, haveRead); + + if (haveWritten < 0) { + // write error! + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") + .arg(url().toString(), file.errorString()); + error(QNetworkReply::ProtocolFailure, msg); + + finished(); + return; + } else { + uploadByteDevice->advanceReadPointer(haveWritten); + } + + + file.flush(); + } } } -void QNetworkAccessFileBackend::closeUpstreamChannel() +void QNetworkAccessFileBackend::closeDownstreamChannel() { - if (operation() == QNetworkAccessManager::PutOperation) { + if (operation() == QNetworkAccessManager::GetOperation) { file.close(); - finished(); } } @@ -174,40 +209,6 @@ bool QNetworkAccessFileBackend::waitForDownstreamReadyRead(int) return readMoreFromFile(); } -bool QNetworkAccessFileBackend::waitForUpstreamBytesWritten(int) -{ - Q_ASSERT_X(false, "QNetworkAccessFileBackend::waitForUpstreamBytesWritten", - "This function should never have been called, since there is never anything " - "left to be written!"); - return false; -} - -void QNetworkAccessFileBackend::upstreamReadyRead() -{ - Q_ASSERT_X(operation() == QNetworkAccessManager::PutOperation, "QNetworkAccessFileBackend", - "We're being told to upload data but operation isn't PUT!"); - - // there's more data to be written to the file - while (upstreamBytesAvailable()) { - // write everything and let QFile handle it - int written = file.write(readUpstream()); - - if (written < 0) { - // write error! - QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2") - .arg(url().toString(), file.errorString()); - error(QNetworkReply::ProtocolFailure, msg); - - finished(); - return; - } - - // successful write - file.flush(); - upstreamBytesConsumed(written); - } -} - void QNetworkAccessFileBackend::downstreamReadyWrite() { Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend", diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h index ce7d351..4615c5f 100644 --- a/src/network/access/qnetworkaccessfilebackend_p.h +++ b/src/network/access/qnetworkaccessfilebackend_p.h @@ -62,22 +62,25 @@ QT_BEGIN_NAMESPACE class QNetworkAccessFileBackend: public QNetworkAccessBackend { + Q_OBJECT public: QNetworkAccessFileBackend(); virtual ~QNetworkAccessFileBackend(); virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); +public slots: + void uploadReadyReadSlot(); +protected: + QNonContiguousByteDevice *uploadByteDevice; private: QFile file; qint64 totalBytes; + bool hasUploadFinished; bool loadFileInfo(); bool readMoreFromFile(); diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index ea39dec..ad55b85 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -42,6 +42,7 @@ #include "qnetworkaccessftpbackend_p.h" #include "qnetworkaccessmanager_p.h" #include "QtNetwork/qauthenticator.h" +#include "private/qnoncontiguousbytedevice_p.h" #ifndef QT_NO_FTP @@ -81,41 +82,6 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, return 0; } -class QNetworkAccessFtpIODevice: public QIODevice -{ - //Q_OBJECT -public: - QNetworkAccessFtpBackend *backend; - bool eof; - - inline QNetworkAccessFtpIODevice(QNetworkAccessFtpBackend *parent) - : QIODevice(parent), backend(parent), eof(false) - { open(ReadOnly); } - - bool isSequential() const { return true; } - bool atEnd() const { return backend->upstreamBytesAvailable() == 0; } - - qint64 bytesAvailable() const { return backend->upstreamBytesAvailable(); } - qint64 bytesToWrite() const { return backend->downstreamBytesToConsume(); } -protected: - qint64 readData(char *data, qint64 maxlen) - { - const QByteArray toSend = backend->readUpstream(); - maxlen = qMin<qint64>(maxlen, toSend.size()); - if (!maxlen) - return eof ? -1 : 0; - - backend->upstreamBytesConsumed(maxlen); - memcpy(data, toSend.constData(), maxlen); - return maxlen; - } - - qint64 writeData(const char *, qint64) - { return -1; } - - friend class QNetworkAccessFtpBackend; -}; - class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject { // Q_OBJECT @@ -198,7 +164,11 @@ void QNetworkAccessFtpBackend::open() ftpConnectionReady(ftp); } - uploadDevice = new QNetworkAccessFtpIODevice(this); + // Put operation + if (operation() == QNetworkAccessManager::PutOperation) { + uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice()); + uploadDevice->setParent(this); + } } void QNetworkAccessFtpBackend::closeDownstreamChannel() @@ -212,16 +182,6 @@ void QNetworkAccessFtpBackend::closeDownstreamChannel() #endif } -void QNetworkAccessFtpBackend::closeUpstreamChannel() -{ - if (operation() == QNetworkAccessManager::PutOperation) { - Q_ASSERT(uploadDevice); - uploadDevice->eof = true; - if (!upstreamBytesAvailable()) - emit uploadDevice->readyRead(); - } -} - bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms) { if (!ftp) @@ -239,18 +199,6 @@ bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms) return false; } -bool QNetworkAccessFtpBackend::waitForUpstreamBytesWritten(int ms) -{ - Q_UNUSED(ms); - qCritical("QNetworkAccess: FTP backend does not support waitForBytesWritten()"); - return false; -} - -void QNetworkAccessFtpBackend::upstreamReadyRead() -{ - // uh... how does QFtp operate? -} - void QNetworkAccessFtpBackend::downstreamReadyWrite() { if (state == Transferring && ftp && ftp->bytesAvailable()) diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h index 9ec2dd8..1bb7ff2 100644 --- a/src/network/access/qnetworkaccessftpbackend_p.h +++ b/src/network/access/qnetworkaccessftpbackend_p.h @@ -87,11 +87,8 @@ public: virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); void disconnectFromFtp(); @@ -105,7 +102,7 @@ public slots: private: friend class QNetworkAccessFtpIODevice; QPointer<QNetworkAccessFtpFtp> ftp; - QNetworkAccessFtpIODevice *uploadDevice; + QIODevice *uploadDevice; qint64 totalBytes; int helpId, sizeId, mdtmId; bool supportsSize, supportsMdtm; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index a52b5a0..bd364cb 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -286,37 +286,6 @@ public: } }; -class QNetworkAccessHttpBackendIODevice: public QIODevice -{ - // Q_OBJECT -public: - bool eof; - QNetworkAccessHttpBackendIODevice(QNetworkAccessHttpBackend *parent) - : QIODevice(parent), eof(false) - { - setOpenMode(ReadOnly); - } - bool isSequential() const { return true; } - qint64 bytesAvailable() const - { return static_cast<QNetworkAccessHttpBackend *>(parent())->upstreamBytesAvailable(); } - -protected: - virtual qint64 readData(char *buffer, qint64 maxlen) - { - qint64 ret = static_cast<QNetworkAccessHttpBackend *>(parent())->deviceReadData(buffer, maxlen); - if (!ret && eof) - return -1; - return ret; - } - - virtual qint64 writeData(const char *, qint64) - { - return -1; // cannot write - } - - friend class QNetworkAccessHttpBackend; -}; - QNetworkAccessHttpBackend::QNetworkAccessHttpBackend() : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0) #ifndef QT_NO_OPENSSL @@ -507,20 +476,19 @@ void QNetworkAccessHttpBackend::postRequest() case QNetworkAccessManager::PostOperation: invalidateCache(); httpRequest.setOperation(QHttpNetworkRequest::Post); - uploadDevice = new QNetworkAccessHttpBackendIODevice(this); + httpRequest.setUploadByteDevice(createUploadByteDevice()); break; case QNetworkAccessManager::PutOperation: invalidateCache(); httpRequest.setOperation(QHttpNetworkRequest::Put); - uploadDevice = new QNetworkAccessHttpBackendIODevice(this); + httpRequest.setUploadByteDevice(createUploadByteDevice()); break; default: break; // can't happen } - httpRequest.setData(uploadDevice); httpRequest.setUrl(url()); QList<QByteArray> headers = request().rawHeaderList(); @@ -528,7 +496,9 @@ void QNetworkAccessHttpBackend::postRequest() httpRequest.setHeaderField(header, request().rawHeader(header)); if (loadedFromCache) { - QNetworkAccessBackend::finished(); + // commented this out since it will be called later anyway + // by copyFinished() + //QNetworkAccessBackend::finished(); return; // no need to send the request! :) } @@ -624,14 +594,6 @@ void QNetworkAccessHttpBackend::closeDownstreamChannel() // this indicates that the user closed the stream while the reply isn't finished yet } -void QNetworkAccessHttpBackend::closeUpstreamChannel() -{ - // this indicates that the user finished uploading the data for POST - Q_ASSERT(uploadDevice); - uploadDevice->eof = true; - emit uploadDevice->readChannelFinished(); -} - bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs) { Q_ASSERT(http); @@ -651,38 +613,6 @@ bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs) return false; } -bool QNetworkAccessHttpBackend::waitForUpstreamBytesWritten(int msecs) -{ - - // ### FIXME: not implemented in QHttpNetworkAccess - Q_UNUSED(msecs); - qCritical("QNetworkAccess: HTTP backend does not support waitForBytesWritten()"); - return false; -} - -void QNetworkAccessHttpBackend::upstreamReadyRead() -{ - // There is more data available from the user to be uploaded - // QHttpNetworkAccess implements the upload rate control: - // we simply tell QHttpNetworkAccess that there is more data available - // it'll pull from us when it can (through uploadDevice) - - Q_ASSERT(uploadDevice); - emit uploadDevice->readyRead(); -} - -qint64 QNetworkAccessHttpBackend::deviceReadData(char *buffer, qint64 maxlen) -{ - QByteArray toBeUploaded = readUpstream(); - if (toBeUploaded.isEmpty()) - return 0; // nothing to be uploaded - - maxlen = qMin<qint64>(maxlen, toBeUploaded.length()); - - memcpy(buffer, toBeUploaded.constData(), maxlen); - upstreamBytesConsumed(maxlen); - return maxlen; -} void QNetworkAccessHttpBackend::downstreamReadyWrite() { @@ -904,7 +834,14 @@ bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &m checkForRedirect(status); - writeDownstreamData(contents); + emit metaDataChanged(); + + // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads + // see task 250221 / 251801 + qRegisterMetaType<QIODevice*>("QIODevice*"); + QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents)); + + #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes"; #endif @@ -1036,21 +973,39 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo if (it != cacheHeaders.rawHeaders.constEnd()) metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second)); - bool canDiskCache = true; // Everything defaults to being cacheable on disk + bool canDiskCache; + // only cache GET replies by default, all other replies (POST, PUT, DELETE) + // are not cacheable by default (according to RFC 2616 section 9) + if (httpReply->request().operation() == QHttpNetworkRequest::Get) { + + canDiskCache = true; + // 14.32 + // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client + // had sent "Cache-Control: no-cache". + it = cacheHeaders.findRawHeader("pragma"); + if (it != cacheHeaders.rawHeaders.constEnd() + && it->second == "no-cache") + canDiskCache = false; + + // HTTP/1.1. Check the Cache-Control header + if (cacheControl.contains("no-cache")) + canDiskCache = false; + else if (cacheControl.contains("no-store")) + canDiskCache = false; + + // responses to POST might be cacheable + } else if (httpReply->request().operation() == QHttpNetworkRequest::Post) { - // 14.32 - // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client - // had sent "Cache-Control: no-cache". - it = cacheHeaders.findRawHeader("pragma"); - if (it != cacheHeaders.rawHeaders.constEnd() - && it->second == "no-cache") canDiskCache = false; + // some pages contain "expires:" and "cache-control: no-cache" field, + // so we only might cache POST requests if we get "cache-control: max-age ..." + if (cacheControl.contains("max-age")) + canDiskCache = true; - // HTTP/1.1. Check the Cache-Control header - if (cacheControl.contains("no-cache")) - canDiskCache = false; - else if (cacheControl.contains("no-store")) + // responses to PUT and DELETE are not cacheable + } else { canDiskCache = false; + } metaData.setSaveToDisk(canDiskCache); int statusCode = httpReply->statusCode(); diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index 02915e7..225f944 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -79,11 +79,8 @@ public: virtual void open(); virtual void closeDownstreamChannel(); - virtual void closeUpstreamChannel(); virtual bool waitForDownstreamReadyRead(int msecs); - virtual bool waitForUpstreamBytesWritten(int msecs); - virtual void upstreamReadyRead(); virtual void downstreamReadyWrite(); virtual void copyFinished(QIODevice *); #ifndef QT_NO_OPENSSL @@ -96,6 +93,9 @@ public: qint64 deviceReadData(char *buffer, qint64 maxlen); + // we return true since HTTP needs to send PUT/POST data again after having authenticated + bool needsResetableUploadData() {return true;}; + private slots: void replyReadyRead(); void replyFinished(); @@ -108,7 +108,8 @@ private: QHttpNetworkReply *httpReply; QPointer<QNetworkAccessHttpBackendCache> http; QByteArray cacheKey; - QNetworkAccessHttpBackendIODevice *uploadDevice; + QNetworkAccessBackendUploadIODevice *uploadDevice; + #ifndef QT_NO_OPENSSL QSslConfiguration *pendingSslConfiguration; bool pendingIgnoreSslErrors; @@ -122,8 +123,6 @@ private: void postRequest(); void readFromHttp(); void checkForRedirect(const int statusCode); - - friend class QNetworkAccessHttpBackendIODevice; }; class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index bcbeef1..bf06ede 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -686,7 +686,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera priv->urlForLastAuthentication = url; } - // third step: setup the reply + // third step: find a backend + priv->backend = d->findBackend(op, request); + + // fourth step: setup the reply priv->setup(op, request, outgoingData); if (request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt() != QNetworkRequest::AlwaysNetwork) @@ -695,9 +698,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url())); priv->proxyList = proxyList; #endif - - // fourth step: find a backend - priv->backend = d->findBackend(op, request); if (priv->backend) { priv->backend->setParent(reply); priv->backend->reply = priv; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index f4dad3c..0990b17 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -151,6 +151,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() authentication to serve the content but the credentials provided were not accepted (if any) + \value ContentReSendError the request needed to be sent + again, but this failed for example because the upload data + could not be read a second time. + \value ProtocolUnknownError the Network Access API cannot honor the request because the protocol is not known diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 6f763b3..2f864fe 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -92,6 +92,7 @@ public: ContentOperationNotPermittedError, ContentNotFoundError, AuthenticationRequiredError, + ContentReSendError, UnknownContentError = 299, // protocol errors diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 79c3d1a..749a462 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -46,13 +46,15 @@ #include "QtCore/qcoreapplication.h" #include "QtCore/qdatetime.h" #include "QtNetwork/qsslconfiguration.h" +#include "qnetworkaccesshttpbackend_p.h" #include <QtCore/QCoreApplication> QT_BEGIN_NAMESPACE inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() - : copyDevice(0), networkCache(0), + : backend(0), outgoingData(0), outgoingDataBuffer(0), + copyDevice(0), networkCache(0), cacheEnabled(false), cacheSaveDevice(0), bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), state(Idle) @@ -61,8 +63,13 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() void QNetworkReplyImplPrivate::_q_startOperation() { - // This function is called exactly once + // ensure this function is only being called once + if (state == Working) { + qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); + return; + } state = Working; + if (!backend) { error(QNetworkReplyImpl::ProtocolUnknownError, QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!; @@ -74,57 +81,11 @@ void QNetworkReplyImplPrivate::_q_startOperation() if (state != Finished) { if (operation == QNetworkAccessManager::GetOperation) pendingNotifications.append(NotifyDownstreamReadyWrite); - if (outgoingData) { - _q_sourceReadyRead(); -#if 0 // ### FIXME - if (outgoingData->atEndOfStream() && writeBuffer.isEmpty()) - // empty upload - emit q->uploadProgress(0, 0); -#endif - } handleNotifications(); } } -void QNetworkReplyImplPrivate::_q_sourceReadyRead() -{ - // read data from the outgoingData QIODevice into our internal buffer - enum { DesiredBufferSize = 32 * 1024 }; - - if (writeBuffer.size() >= DesiredBufferSize) - return; // don't grow the buffer too much - - // read as many bytes are available or up until we fill up the buffer - // but always read at least one byte - qint64 bytesToRead = qBound<qint64>(1, outgoingData->bytesAvailable(), - DesiredBufferSize - writeBuffer.size()); - char *ptr = writeBuffer.reserve(bytesToRead); - qint64 bytesActuallyRead = outgoingData->read(ptr, bytesToRead); - if (bytesActuallyRead == -1) { - // EOF - writeBuffer.chop(bytesToRead); - backendNotify(NotifyCloseUpstreamChannel); - return; - } - - if (bytesActuallyRead < bytesToRead) - writeBuffer.chop(bytesToRead - bytesActuallyRead); - - // if we did read anything, let the backend know and handle it - if (bytesActuallyRead) - backendNotify(NotifyUpstreamReadyRead); - - // check for EOF again - if (!outgoingData->isSequential() && outgoingData->atEnd()) - backendNotify(NotifyCloseUpstreamChannel); -} - -void QNetworkReplyImplPrivate::_q_sourceReadChannelFinished() -{ - _q_sourceReadyRead(); -} - void QNetworkReplyImplPrivate::_q_copyReadyRead() { Q_Q(QNetworkReplyImpl); @@ -143,7 +104,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (bytesActuallyRead == -1) { readBuffer.chop(bytesToRead); backendNotify(NotifyCopyFinished); - return; + break; } if (bytesActuallyRead != bytesToRead) @@ -151,6 +112,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); + bytesDownloaded += bytesActuallyRead; break; } @@ -174,6 +136,67 @@ void QNetworkReplyImplPrivate::_q_copyReadChannelFinished() _q_copyReadyRead(); } +void QNetworkReplyImplPrivate::_q_bufferOutgoingDataFinished() +{ + Q_Q(QNetworkReplyImpl); + + // make sure this is only called once, ever. + //_q_bufferOutgoingData may call it or the readChannelFinished emission + if (state != Buffering) + return; + + // disconnect signals + QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData())); + QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished())); + + // finally, start the request + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); +} + +void QNetworkReplyImplPrivate::_q_bufferOutgoingData() +{ + Q_Q(QNetworkReplyImpl); + + if (!outgoingDataBuffer) { + // first call, create our buffer + outgoingDataBuffer = new QRingBuffer(); + + QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData())); + QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished())); + } + + qint64 bytesBuffered = 0; + qint64 bytesToBuffer = 0; + + // read data into our buffer + forever { + bytesToBuffer = outgoingData->bytesAvailable(); + // unknown? just try 2 kB, this also ensures we always try to read the EOF + if (bytesToBuffer <= 0) + bytesToBuffer = 2*1024; + + char *dst = outgoingDataBuffer->reserve(bytesToBuffer); + bytesBuffered = outgoingData->read(dst, bytesToBuffer); + + if (bytesBuffered == -1) { + // EOF has been reached. + outgoingDataBuffer->chop(bytesToBuffer); + + _q_bufferOutgoingDataFinished(); + break; + } else if (bytesBuffered == 0) { + // nothing read right now, just wait until we get called again + outgoingDataBuffer->chop(bytesToBuffer); + + break; + } else { + // don't break, try to read() again + outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered); + } + } +} + + void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data) { @@ -184,13 +207,42 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const url = request.url(); operation = op; - if (outgoingData) { - q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead())); - q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished())); + if (outgoingData && backend) { + // there is data to be uploaded, e.g. HTTP POST. + + if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) { + // backend does not need upload buffering or + // fixed size non-sequential + // just start the operation + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); + } else { + bool bufferingDisallowed = + req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, + false).toBool(); + + if (bufferingDisallowed) { + // if a valid content-length header for the request was supplied, we can disable buffering + // if not, we will buffer anyway + if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) { + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); + } else { + state = Buffering; + QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); + } + } else { + // _q_startOperation will be called when the buffering has finished. + state = Buffering; + QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); + } + } + } else { + // No outgoing data (e.g. HTTP GET request) + // or no backend + // if no backend, _q_startOperation will handle the error of this + QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } q->QIODevice::open(QIODevice::ReadOnly); - QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } void QNetworkReplyImplPrivate::setNetworkCache(QAbstractNetworkCache *nc) @@ -226,18 +278,10 @@ void QNetworkReplyImplPrivate::handleNotifications() backend->downstreamReadyWrite(); break; - case NotifyUpstreamReadyRead: - backend->upstreamReadyRead(); - break; - case NotifyCloseDownstreamChannel: backend->closeDownstreamChannel(); break; - case NotifyCloseUpstreamChannel: - backend->closeUpstreamChannel(); - break; - case NotifyCopyFinished: { QIODevice *dev = copyDevice; copyDevice = 0; @@ -299,29 +343,14 @@ void QNetworkReplyImplPrivate::completeCacheSave() cacheEnabled = false; } -void QNetworkReplyImplPrivate::consume(qint64 count) +void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytesTotal) { Q_Q(QNetworkReplyImpl); - if (count <= 0) { - qWarning("QNetworkConnection: backend signalled that it consumed %ld bytes", long(count)); - return; - } - - if (outgoingData) - // schedule another read from the source - QMetaObject::invokeMethod(q_func(), "_q_sourceReadyRead", Qt::QueuedConnection); - - writeBuffer.skip(count); - if (bytesUploaded == -1) - bytesUploaded = count; - else - bytesUploaded += count; - - QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader); - emit q->uploadProgress(bytesUploaded, - totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); + bytesUploaded = bytesSent; + emit q->uploadProgress(bytesSent, bytesTotal); } + qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const { enum { DesiredBufferSize = 32 * 1024 }; @@ -331,7 +360,9 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const return qMax<qint64>(0, readBufferMaxSize - readBuffer.size()); } -void QNetworkReplyImplPrivate::feed(const QByteArray &data) +// we received downstream data and send this to the cache +// and to our readBuffer (which in turn gets read by the user of QNetworkReply) +void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) { Q_Q(QNetworkReplyImpl); if (!q->isOpen()) @@ -379,7 +410,8 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data) } } -void QNetworkReplyImplPrivate::feed(QIODevice *data) +// this is used when it was fetched from the cache, right? +void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data) { Q_Q(QNetworkReplyImpl); Q_ASSERT(q->isOpen()); @@ -409,9 +441,11 @@ void QNetworkReplyImplPrivate::finished() pendingNotifications.clear(); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); - if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull()) + if (totalSize.isNull() || totalSize == -1) { emit q->downloadProgress(bytesDownloaded, bytesDownloaded); - if (bytesUploaded == -1 && outgoingData) + } + + if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer)) emit q->uploadProgress(0, 0); completeCacheSave(); diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index ad06f78..8d3c90e 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -59,6 +59,7 @@ #include "qnetworkproxy.h" #include "QtCore/qmap.h" #include "QtCore/qqueue.h" +#include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" QT_BEGIN_NAMESPACE @@ -91,10 +92,10 @@ public: Q_DECLARE_PRIVATE(QNetworkReplyImpl) Q_PRIVATE_SLOT(d_func(), void _q_startOperation()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReadyRead()) - Q_PRIVATE_SLOT(d_func(), void _q_sourceReadChannelFinished()) Q_PRIVATE_SLOT(d_func(), void _q_copyReadyRead()) Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished()) + Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData()) + Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished()) }; class QNetworkReplyImplPrivate: public QNetworkReplyPrivate @@ -102,15 +103,13 @@ class QNetworkReplyImplPrivate: public QNetworkReplyPrivate public: enum InternalNotifications { NotifyDownstreamReadyWrite, - NotifyUpstreamReadyRead, NotifyCloseDownstreamChannel, - NotifyCloseUpstreamChannel, NotifyCopyFinished }; enum State { Idle, - Opening, + Buffering, Working, Finished, Aborted @@ -125,6 +124,8 @@ public: void _q_sourceReadChannelFinished(); void _q_copyReadyRead(); void _q_copyReadChannelFinished(); + void _q_bufferOutgoingData(); + void _q_bufferOutgoingDataFinished(); void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); @@ -138,9 +139,10 @@ public: void setCachingEnabled(bool enable); bool isCachingEnabled() const; void consume(qint64 count); + void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal); qint64 nextDownstreamBlockSize() const; - void feed(const QByteArray &data); - void feed(QIODevice *data); + void appendDownstreamData(const QByteArray &data); + void appendDownstreamData(QIODevice *data); void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); @@ -149,6 +151,7 @@ public: QNetworkAccessBackend *backend; QIODevice *outgoingData; + QRingBuffer *outgoingDataBuffer; QIODevice *copyDevice; QAbstractNetworkCache *networkCache; diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 56b793d..8b1afba 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -162,6 +162,13 @@ QT_BEGIN_NAMESPACE Indicates whether the data was obtained from cache or not. + \value DoNotBufferUploadDataAttribute + Requests only, type: QVariant::Bool (default: false) + Indicates whether the QNetworkAccessManager code is + allowed to buffer the upload data, e.g. when doing a HTTP POST. + When using this flag with sequential upload data, the ContentLengthHeader + header must be set. + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 6f34bce..5dea1df 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -75,6 +75,7 @@ public: CacheLoadControlAttribute, CacheSaveControlAttribute, SourceIsFromCacheAttribute, + DoNotBufferUploadDataAttribute, User = 1000, UserMax = 32767 diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 0bfed12..83e6717 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -172,7 +172,7 @@ QGLPixmapColorizeFilter::QGLPixmapColorizeFilter() m_program.addShader(QGLShader::FragmentShader, qt_gl_colorize_filter); m_program.link(); m_program.enable(); - m_program.setUniformValue(m_program.uniformLocation("texture"),GLint(0)); // GL_TEXTURE_0 + m_program.setUniformValue(m_program.uniformLocation("texture"), GLint(0)); // GL_TEXTURE_0 m_colorUniform = m_program.uniformLocation("color"); } diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/plugins/accessible/widgets/simplewidgets.h index d4552e3..d1fd0da 100644 --- a/src/plugins/accessible/widgets/simplewidgets.h +++ b/src/plugins/accessible/widgets/simplewidgets.h @@ -115,6 +115,7 @@ public: class QAccessibleLineEdit : public QAccessibleWidgetEx, public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface { + Q_ACCESSIBLE_OBJECT public: explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString()); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 91a60e7..989a37a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -275,7 +275,6 @@ private: int lastLockedHeight; IDirectFB *fb; - DFBSurfaceDescription fbDescription; int fbWidth; int fbHeight; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 7297a99..c9b676a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -271,7 +271,7 @@ void QDirectFBPixmapData::fill(const QColor &color) forceRaster = false; setSerialNumber(++global_ser_no); if (!dfbSurface) { - qWarning("QDirecttFBPixmapData::fill()"); + qWarning("QDirectFBPixmapData::fill()"); invalidate(); return; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index f571d1b..98e32ed 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -205,6 +205,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, SurfaceCreationOptions options) { DFBSurfaceDescription desc; + memset(&desc, 0, sizeof(DFBSurfaceDescription)); desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH|DSDESC_HEIGHT); if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format)) return 0; @@ -213,7 +214,6 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, return createDFBSurface(desc, options); } - IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options) { DFBResult result = DFB_OK; @@ -247,6 +247,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, } desc.caps = DFBSurfaceCapabilities(desc.caps & ~DSCAPS_VIDEOONLY); } + if (d_ptr->directFBFlags & SystemOnly) desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_SYSTEMONLY); @@ -293,14 +294,14 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, IDirectFBSurface *dfbSurface = createDFBSurface(image.size(), pixmapFormat, options); if (!dfbSurface) { - qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface"); + qWarning("QDirectFBScreen::copyToDFBSurface() Couldn't create surface"); return 0; } #ifndef QT_NO_DIRECTFB_PREALLOCATED IDirectFBSurface *imgSurface = createDFBSurface(image, DontTrackSurface); if (!imgSurface) { - qWarning("QDirectFBPixmapData::fromImage()"); + qWarning("QDirectFBScreen::copyToDFBSurface()"); QDirectFBScreen::releaseDFBSurface(dfbSurface); return 0; } @@ -315,7 +316,7 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, dfbSurface->SetBlittingFlags(dfbSurface, flags); DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); if (result != DFB_OK) - DirectFBError("QDirectFBPixmapData::fromImage()", result); + DirectFBError("QDirectFBScreen::copyToDFBSurface()", result); dfbSurface->ReleaseSource(dfbSurface); imgSurface->Release(imgSurface); #else // QT_NO_DIRECTFB_PREALLOCATED @@ -445,6 +446,7 @@ QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface) DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image) { DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format()); @@ -479,6 +481,7 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer, int length) { DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS | DSDESC_WIDTH @@ -917,6 +920,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN); DFBSurfaceDescription description; + memset(&description, 0, sizeof(DFBSurfaceDescription)); + description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS); if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); diff --git a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp index c7249d3..3273513 100644 --- a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp +++ b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp @@ -122,16 +122,10 @@ QSize QSvgIconEngine::actualSize(const QSize &size, QIcon::Mode mode, return size; } - QSvgRenderer renderer; - d->loadDataForModeAndState(&renderer, mode, state); - if (renderer.isValid()) { - QSize defaultSize = renderer.defaultSize(); - if (!defaultSize.isNull()) - defaultSize.scale(size, Qt::KeepAspectRatio); - return defaultSize; - } else { + QPixmap pm = pixmap(size, mode, state); + if (pm.isNull()) return QSize(); - } + return pm.size(); } void QSvgIconEnginePrivate::loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 6834d9a..4f3d79d 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -66,8 +66,11 @@ QT_BEGIN_NAMESPACE enum { QIBaseChunkSize = SHRT_MAX / 2 }; -static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, - QTextCodec *tc) +#if defined(FB_API_VER) && FB_API_VER >= 20 +static bool getIBaseError(QString& msg, const ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc) +#else +static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc) +#endif { if (status[0] != 1 || status[1] <= 0) return false; @@ -75,7 +78,11 @@ static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, msg.clear(); sqlcode = isc_sqlcode(status); char buf[512]; +#if defined(FB_API_VER) && FB_API_VER >= 20 + while(fb_interpret(buf, 512, &status)) { +#else while(isc_interprete(buf, &status)) { +#endif if(!msg.isEmpty()) msg += QLatin1String(" - "); if (tc) diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 1f54db7..fbefa0c 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -163,18 +163,21 @@ static inline QVariant qDateTimeFromString(QString &val) #endif } -class QMYSQLResultPrivate +class QMYSQLResultPrivate : public QObject { + Q_OBJECT public: - QMYSQLResultPrivate(QMYSQLDriverPrivate* dp) : d(dp), result(0), + QMYSQLResultPrivate(const QMYSQLDriver* dp) : driver(dp), result(0), rowsAffected(0), hasBlobs(false) #if MYSQL_VERSION_ID >= 40108 , stmt(0), meta(0), inBinds(0), outBinds(0) #endif , precisionPolicy(QSql::HighPrecision) - {} + { + connect(dp, SIGNAL(destroyed()), this, SLOT(driverDestroyed())); + } - QMYSQLDriverPrivate* d; + const QMYSQLDriver* driver; MYSQL_RES *result; MYSQL_ROW row; @@ -207,6 +210,8 @@ public: MYSQL_BIND *outBinds; #endif QSql::NumericalPrecisionPolicy precisionPolicy; +private Q_SLOTS: + void driverDestroyed() { driver = NULL; } }; #ifndef QT_NO_TEXTCODEC @@ -379,7 +384,7 @@ bool QMYSQLResultPrivate::bindInValues() QMYSQLResult::QMYSQLResult(const QMYSQLDriver* db) : QSqlResult(db) { - d = new QMYSQLResultPrivate(db->d); + d = new QMYSQLResultPrivate(db); } QMYSQLResult::~QMYSQLResult() @@ -391,7 +396,7 @@ QMYSQLResult::~QMYSQLResult() QVariant QMYSQLResult::handle() const { #if MYSQL_VERSION_ID >= 40108 - if(d->d->preparedQuerys) + if(d->driver && d->driver->d->preparedQuerys) return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt); else #endif @@ -406,8 +411,8 @@ void QMYSQLResult::cleanup() // must iterate trough leftover result sets from multi-selects or stored procedures // if this isn't done subsequent queries will fail with "Commands out of sync" #if MYSQL_VERSION_ID >= 40100 - while (d->d->mysql && mysql_next_result(d->d->mysql) == 0) { - MYSQL_RES *res = mysql_store_result(d->d->mysql); + while (d->driver && d->driver->d->mysql && mysql_next_result(d->driver->d->mysql) == 0) { + MYSQL_RES *res = mysql_store_result(d->driver->d->mysql); if (res) mysql_free_result(res); } @@ -447,11 +452,14 @@ void QMYSQLResult::cleanup() setAt(-1); setActive(false); - d->d->preparedQuerys = d->d->preparedQuerysEnabled; + if(d->driver) + d->driver->d->preparedQuerys = d->driver->d->preparedQuerysEnabled; } bool QMYSQLResult::fetch(int i) { + if(!d->driver) + return false; if (isForwardOnly()) { // fake a forward seek if (at() < i) { int x = i - at(); @@ -463,7 +471,7 @@ bool QMYSQLResult::fetch(int i) } if (at() == i) return true; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 mysql_stmt_data_seek(d->stmt, i); @@ -494,7 +502,9 @@ bool QMYSQLResult::fetch(int i) bool QMYSQLResult::fetchNext() { - if (d->d->preparedQuerys) { + if(!d->driver) + return false; + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 if (mysql_stmt_fetch(d->stmt)) return false; @@ -512,6 +522,8 @@ bool QMYSQLResult::fetchNext() bool QMYSQLResult::fetchLast() { + if(!d->driver) + return false; if (isForwardOnly()) { // fake this since MySQL can't seek on forward only queries bool success = fetchNext(); // did we move at all? while (fetchNext()) {}; @@ -519,7 +531,7 @@ bool QMYSQLResult::fetchLast() } my_ulonglong numRows; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 numRows = mysql_stmt_num_rows(d->stmt); #else @@ -553,15 +565,18 @@ QVariant QMYSQLResult::data(int field) return QVariant(); } + if (!d->driver) + return QVariant(); + int fieldLength = 0; const QMYSQLResultPrivate::QMyField &f = d->fields.at(field); QString val; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { if (f.nullIndicator) return QVariant(f.type); if (f.type != QVariant::ByteArray) - val = toUnicode(d->d->tc, f.outField, f.bufLength); + val = toUnicode(d->driver->d->tc, f.outField, f.bufLength); } else { if (d->row[field] == NULL) { // NULL value @@ -569,7 +584,7 @@ QVariant QMYSQLResult::data(int field) } fieldLength = mysql_fetch_lengths(d->result)[field]; if (f.type != QVariant::ByteArray) - val = toUnicode(d->d->tc, d->row[field], fieldLength); + val = toUnicode(d->driver->d->tc, d->row[field], fieldLength); } switch(f.type) { @@ -614,7 +629,7 @@ QVariant QMYSQLResult::data(int field) case QVariant::ByteArray: { QByteArray ba; - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { ba = QByteArray(f.outField, f.bufLength); } else { ba = QByteArray(d->row[field], fieldLength); @@ -631,7 +646,7 @@ QVariant QMYSQLResult::data(int field) bool QMYSQLResult::isNull(int field) { - if (d->d->preparedQuerys) + if (d->driver->d->preparedQuerys) return d->fields.at(field).nullIndicator; else return d->row[field] == NULL; @@ -639,31 +654,31 @@ bool QMYSQLResult::isNull(int field) bool QMYSQLResult::reset (const QString& query) { - if (!driver() || !driver()->isOpen() || driver()->isOpenError()) + if (!driver() || !driver()->isOpen() || driver()->isOpenError() || !d->driver) return false; - if(d->d->preparedQuerysEnabled && prepare(query)) { - d->d->preparedQuerys = true; + if(d->driver->d->preparedQuerysEnabled && prepare(query)) { + d->driver->d->preparedQuerys = true; return exec(); } - d->d->preparedQuerys = false; + d->driver->d->preparedQuerys = false; - const QByteArray encQuery(fromUnicode(d->d->tc, query)); - if (mysql_real_query(d->d->mysql, encQuery.data(), encQuery.length())) { + const QByteArray encQuery(fromUnicode(d->driver->d->tc, query)); + if (mysql_real_query(d->driver->d->mysql, encQuery.data(), encQuery.length())) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute query"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - d->result = mysql_store_result(d->d->mysql); - if (!d->result && mysql_field_count(d->d->mysql) > 0) { + d->result = mysql_store_result(d->driver->d->mysql); + if (!d->result && mysql_field_count(d->driver->d->mysql) > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store result"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - int numFields = mysql_field_count(d->d->mysql); + int numFields = mysql_field_count(d->driver->d->mysql); setSelect(numFields != 0); d->fields.resize(numFields); - d->rowsAffected = mysql_affected_rows(d->d->mysql); + d->rowsAffected = mysql_affected_rows(d->driver->d->mysql); if (isSelect()) { for(int i = 0; i < numFields; i++) { MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i); @@ -677,8 +692,8 @@ bool QMYSQLResult::reset (const QString& query) int QMYSQLResult::size() { - if (isSelect()) - if (d->d->preparedQuerys) + if (d->driver && isSelect()) + if (d->driver->d->preparedQuerys) #if MYSQL_VERSION_ID >= 40108 return mysql_stmt_num_rows(d->stmt); #else @@ -697,17 +712,17 @@ int QMYSQLResult::numRowsAffected() QVariant QMYSQLResult::lastInsertId() const { - if (!isActive()) + if (!isActive() || !d->driver) return QVariant(); - if (d->d->preparedQuerys) { + if (d->driver->d->preparedQuerys) { #if MYSQL_VERSION_ID >= 40108 quint64 id = mysql_stmt_insert_id(d->stmt); if (id) return QVariant(id); #endif } else { - quint64 id = mysql_insert_id(d->d->mysql); + quint64 id = mysql_insert_id(d->driver->d->mysql); if (id) return QVariant(id); } @@ -718,20 +733,20 @@ QSqlRecord QMYSQLResult::record() const { QSqlRecord info; MYSQL_RES *res; - if (!isActive() || !isSelect()) + if (!isActive() || !isSelect() || !d->driver) return info; #if MYSQL_VERSION_ID >= 40108 - res = d->d->preparedQuerys ? d->meta : d->result; + res = d->driver->d->preparedQuerys ? d->meta : d->result; #else res = d->result; #endif - if (!mysql_errno(d->d->mysql)) { + if (!mysql_errno(d->driver->d->mysql)) { mysql_field_seek(res, 0); MYSQL_FIELD* field = mysql_fetch_field(res); while(field) { - info.append(qToField(field, d->d->tc)); + info.append(qToField(field, d->driver->d->tc)); field = mysql_fetch_field(res); } } @@ -741,6 +756,8 @@ QSqlRecord QMYSQLResult::record() const bool QMYSQLResult::nextResult() { + if(!d->driver) + return false; #if MYSQL_VERSION_ID >= 40100 setAt(-1); setActive(false); @@ -754,26 +771,26 @@ bool QMYSQLResult::nextResult() delete[] d->fields[i].outField; d->fields.clear(); - int status = mysql_next_result(d->d->mysql); + int status = mysql_next_result(d->driver->d->mysql); if (status > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute next query"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } else if (status == -1) { return false; // No more result sets } - d->result = mysql_store_result(d->d->mysql); - int numFields = mysql_field_count(d->d->mysql); + d->result = mysql_store_result(d->driver->d->mysql); + int numFields = mysql_field_count(d->driver->d->mysql); if (!d->result && numFields > 0) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store next result"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } setSelect(numFields > 0); d->fields.resize(numFields); - d->rowsAffected = mysql_affected_rows(d->d->mysql); + d->rowsAffected = mysql_affected_rows(d->driver->d->mysql); if (isSelect()) { for (int i = 0; i < numFields; i++) { @@ -833,9 +850,11 @@ static MYSQL_TIME *toMySqlDate(QDate date, QTime time, QVariant::Type type) bool QMYSQLResult::prepare(const QString& query) { + if(!d->driver) + return false; #if MYSQL_VERSION_ID >= 40108 cleanup(); - if (!d->d->preparedQuerys) + if (!d->driver->d->preparedQuerys) return QSqlResult::prepare(query); int r; @@ -844,14 +863,14 @@ bool QMYSQLResult::prepare(const QString& query) return false; if (!d->stmt) - d->stmt = mysql_stmt_init(d->d->mysql); + d->stmt = mysql_stmt_init(d->driver->d->mysql); if (!d->stmt) { setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to prepare statement"), - QSqlError::StatementError, d->d)); + QSqlError::StatementError, d->driver->d)); return false; } - const QByteArray encQuery(fromUnicode(d->d->tc, query)); + const QByteArray encQuery(fromUnicode(d->driver->d->tc, query)); r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.length()); if (r != 0) { setLastError(qMakeStmtError(QCoreApplication::translate("QMYSQLResult", @@ -873,7 +892,9 @@ bool QMYSQLResult::prepare(const QString& query) bool QMYSQLResult::exec() { - if (!d->d->preparedQuerys) + if (!d->driver) + return false; + if (!d->driver->d->preparedQuerys) return QSqlResult::exec(); if (!d->stmt) return false; @@ -963,7 +984,7 @@ bool QMYSQLResult::exec() break; case QVariant::String: default: { - QByteArray ba = fromUnicode(d->d->tc, val.toString()); + QByteArray ba = fromUnicode(d->driver->d->tc, val.toString()); stringVector.append(ba); currBind->buffer_type = MYSQL_TYPE_STRING; currBind->buffer = const_cast<char *>(ba.constData()); @@ -1459,3 +1480,5 @@ bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier, } QT_END_NAMESPACE + +#include "qsql_mysql.moc"
\ No newline at end of file diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 6232452..a270c0e 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -378,7 +378,7 @@ void QSqlDatabasePrivate::disable() the connection name argument, if you don't pass the connection name argument, the default connection is assumed. The following snippet shows how to create and open a default connection to a - MySQL database: + PostgreSQL database: \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 0 diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 8c76c5d..041f2db 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1465,8 +1465,12 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) #if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS) if (QBenchmarkGlobalData::current->createChart) { - QString chartLocation = QLibraryInfo::location(QLibraryInfo::BinariesPath) - + QLatin1String("/../tools/qtestlib/chart/chart"); + QString chartLocation = QLibraryInfo::location(QLibraryInfo::BinariesPath); +#ifdef Q_OS_WIN + chartLocation += QLatin1String("/../tools/qtestlib/chart/release/chart.exe"); +#else + chartLocation += QLatin1String("/../tools/qtestlib/chart/chart"); +#endif if (QFile::exists(chartLocation)) { QProcess p; p.setProcessChannelMode(QProcess::ForwardedChannels); |