summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-08-12 14:13:24 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-08-12 14:13:24 (GMT)
commitc792951aba5fd897610e199c457846d0b6b0690d (patch)
tree8843e93273ce11c9e3afc8574bf5d7e6063ebc74 /src/corelib
parenta6905066d18c29c55944653678e85698c9babc6e (diff)
parentfe5d0c32887b17a76c259bea951beaaaad675968 (diff)
downloadQt-c792951aba5fd897610e199c457846d0b6b0690d.zip
Qt-c792951aba5fd897610e199c457846d0b6b0690d.tar.gz
Qt-c792951aba5fd897610e199c457846d0b6b0690d.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into qtscript-jsc-backend
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/animation/qvariantanimation.cpp84
-rw-r--r--src/corelib/animation/qvariantanimation_p.h1
-rw-r--r--src/corelib/tools/qsharedpointer.cpp111
-rw-r--r--src/corelib/tools/qsharedpointer.h3
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h21
5 files changed, 167 insertions, 53 deletions
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index 61321c8..e647318 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -178,8 +178,7 @@ template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF
return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
}
-QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), hasStartValue(false),
- interpolator(&defaultInterpolator),
+QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolator(&defaultInterpolator),
changedSignalMask(1 << QVariantAnimation::staticMetaObject.indexOfSignal("valueChanged(QVariant)"))
{
//we keep the mask so that we emit valueChanged only when needed (for performance reasons)
@@ -222,34 +221,59 @@ void QVariantAnimationPrivate::updateInterpolator()
void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
{
// can't interpolate if we have only 1 key value
- if (keyValues.count() <= 1)
+ if ((keyValues.count() + (defaultStartValue.isValid() ? 1 : 0)) <=1)
return;
const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) {
//let's update currentInterval
- QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(),
+ QVariantAnimation::KeyValues::const_iterator it = 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.constBegin()) {
- ++itEnd;
+ if (it == keyValues.constEnd()) {
+ if (direction == QVariantAnimation::Backward && defaultStartValue.isValid()) {
+ --it;
+ if (it->first == 1) {
+ //we have an end value (item with progress = 1)
+ currentInterval.start = *(it-1);
+ currentInterval.end = *it;
+ } else if (direction == QVariantAnimation::Backward && defaultStartValue.isValid()) {
+ //the default start value should be used as the default end value
+ currentInterval.start = *it;
+ currentInterval.end = qMakePair(qreal(1), defaultStartValue);
+ } else {
+ ///This should not happen
+ }
+ }
+ } else if (it == keyValues.constBegin()) {
+ if (it+1 != keyValues.constEnd() && (it->first == progress || it->first == 0)) {
+ //the item pointed to by it is the start element in the range
+ //we also test if the current element is for progress 0 (ie the real start) because
+ //some easing curves might get the progress below 0.
+ currentInterval.start = *it;
+ currentInterval.end = *(it+1);
+ } else if (defaultStartValue.isValid()) {
+ if (direction == QVariantAnimation::Forward) {
+ //we should have an end value
+ currentInterval.start = qMakePair(qreal(0), defaultStartValue);
+ currentInterval.end = *it;
+ } else {
+ //we should have a start value
+ currentInterval.start = *it;
+ currentInterval.end = qMakePair(qreal(1), defaultStartValue);
+ }
} else {
- --itStart;
+ ///this should not happen
}
-
- // update all the values of the currentInterval
- currentInterval.start = *itStart;
- currentInterval.end = *itEnd;
- updateInterpolator();
+ } else {
+ currentInterval.start = *(it-1);
+ currentInterval.end = *it;
}
+
+ // update all the values of the currentInterval
+ updateInterpolator();
}
setCurrentValueForProgress(progress);
}
@@ -298,8 +322,6 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
} else {
if (value.isValid())
result->second = value; // replaces the previous value
- else if (step == 0 && !hasStartValue && defaultStartValue.isValid())
- result->second = defaultStartValue; // resets to the default start value
else
keyValues.erase(result); // removes the previous value
}
@@ -310,8 +332,7 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value)
{
defaultStartValue = value;
- if (!hasStartValue)
- setValueAt(0, value);
+ recalculateCurrentInterval(/*force=*/true);
}
/*!
@@ -526,11 +547,7 @@ void QVariantAnimation::setEndValue(const QVariant &value)
*/
QVariant QVariantAnimation::keyValueAt(qreal step) const
{
- Q_D(const QVariantAnimation);
- if (step == 0 && !d->hasStartValue)
- return QVariant(); //special case where we don't have an explicit startValue
-
- return d->valueAt(step);
+ return d_func()->valueAt(step);
}
/*!
@@ -552,10 +569,7 @@ QVariant QVariantAnimation::keyValueAt(qreal step) const
*/
void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
{
- Q_D(QVariantAnimation);
- if (step == 0)
- d->hasStartValue = value.isValid();
- d->setValueAt(step, value);
+ d_func()->setValueAt(step, value);
}
/*!
@@ -565,12 +579,7 @@ void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
*/
QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
{
- Q_D(const QVariantAnimation);
- QVariantAnimation::KeyValues ret = d->keyValues;
- //in case we added the default start value, we remove it
- if (!d->hasStartValue && !ret.isEmpty() && ret.at(0).first == 0)
- ret.remove(0);
- return ret;
+ return d_func()->keyValues;
}
/*!
@@ -584,7 +593,6 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
Q_D(QVariantAnimation);
d->keyValues = keyValues;
qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
- d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0;
d->recalculateCurrentInterval(/*force=*/true);
}
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
index dbfd956..9c9d25b 100644
--- a/src/corelib/animation/qvariantanimation_p.h
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -84,7 +84,6 @@ public:
QVariantAnimation::KeyValues keyValues;
QVariant currentValue;
QVariant defaultStartValue;
- bool hasStartValue;
//this is used to keep track of the KeyValue interval in which we currently are
struct
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 644ccc3..e3e1db6 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -98,15 +98,14 @@
access made to the data being guarded: if it's a non-const access,
it creates a copy atomically for the operation to complete.
- QExplicitlySharedDataPointer behaves like QSharedDataPointer,
- except that it only detaches if
- QExplicitlySharedDataPointer::detach() is explicitly called.
+ QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except
+ that it only detaches if QExplicitlySharedDataPointer::detach() is
+ explicitly called (hence the name).
- Finally, QPointer holds a pointer to a QObject-derived object, but
- it does so weakly. QPointer is similar, in that behaviour, to
- QWeakPointer: it does not allow you to prevent the object from
- being destroyed. All you can do is query whether it has been
- destroyed or not.
+ Finally, QPointer holds a pointer to a QObject-derived object, but it
+ does so weakly. QPointer can be replaced by QWeakPointer in almost all
+ cases, since they have the same functionality. See
+ \l{QWeakPointer#tracking-qobject} for more information.
\sa QSharedDataPointer, QWeakPointer
*/
@@ -123,12 +122,65 @@
directly, but it can be used to verify if the pointer has been
deleted or not in another context.
- QWeakPointer objects can only be created by assignment
- from a QSharedPointer.
-
- To access the pointer that QWeakPointer is tracking, you
- must first create a QSharedPointer object and verify if the pointer
- is null or not. See QWeakPointer::toStrongRef() for more information.
+ QWeakPointer objects can only be created by assignment from a
+ QSharedPointer. The exception is pointers derived from QObject: in that
+ case, QWeakPointer serves as a replacement to QPointer.
+
+ It's important to note that QWeakPointer provides no automatic casting
+ operators to prevent mistakes from happening. Even though QWeakPointer
+ tracks a pointer, it should not be considered a pointer itself, since it
+ doesn't guarantee that the pointed object remains valid.
+
+ Therefore, to access the pointer that QWeakPointer is tracking, you must
+ first promote it to QSharedPointer and verify if the resulting object is
+ null or not. QSharedPointer guarantees that the object isn't deleted, so
+ if you obtain a non-null object, you may use the pointer. See
+ QWeakPointer::toStrongRef() for more an example.
+
+ QWeakPointer also provides the QWeakPointer::data() method that returns
+ the tracked pointer without ensuring that it remains valid. This function
+ is provided if you can guarantee by external means that the object will
+ not get deleted (or if you only need the pointer value) and the cost of
+ creating a QSharedPointer using toStrongRef() is too high.
+
+ That function can also be used to obtain the tracked pointer for
+ QWeakPointers that cannot be promoted to QSharedPointer, such as those
+ created directly from a QObject pointer (not via QSharedPointer).
+
+ \section1 Tracking QObject
+
+ QWeakPointer can be used to track deletion classes derives from QObject,
+ even if they are not managed by QSharedPointer. When used in that role,
+ QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer
+ is also more efficient than QPointer, so it should be preferred in all
+ new code.
+
+ To do that, QWeakPointer provides a special constructor that is only
+ available if the template parameter \tt T is either QObject or a class
+ deriving from it. Trying to use that constructor if \tt T does not derive
+ from QObject will result in compilation errors.
+
+ To obtain the QObject being tracked by QWeakPointer, you must use the
+ QWeakPointer::data() function, but only if you can guarantee that the
+ object cannot get deleted by another context. It should be noted that
+ QPointer had the same constraint, so use of QWeakPointer forces you to
+ consider whether the pointer is still valid.
+
+ QObject-derived classes can only be deleted in the thread they have
+ affinity to (which is the thread they were created in or moved to, using
+ QObject::moveToThread()). In special, QWidget-derived classes cannot be
+ created in non-GUI threads nor moved there. Therefore, guaranteeing that
+ the tracked QObject has affinity to the current thread is enough to also
+ guarantee that it won't be deleted asynchronously.
+
+ Note that QWeakPointer's size and data layout do not match QPointer, so
+ it cannot replace that class in a binary-compatible manner.
+
+ Care must also be taken with QWeakPointers created directly from QObject
+ pointers when dealing with code that was compiled with Qt versions prior
+ to 4.6. Those versions may not track the reference counters correctly, so
+ QWeakPointers created from QObject should never be passed to code that
+ hasn't been recompiled.
\sa QSharedPointer
*/
@@ -412,6 +464,35 @@
*/
/*!
+ \fn QWeakPointer::QWeakPointer(const QObject *obj)
+ \since 4.6
+
+ Creates a QWeakPointer that holds a weak reference directly to the
+ QObject \a obj. This constructor is only available if the template type
+ \tt T is QObject or derives from it (otherwise a compilation error will
+ result).
+
+ You can use this constructor with any QObject, even if they were not
+ created with \l QSharedPointer.
+
+ Note that QWeakPointers created this way on arbitrary QObjects usually
+ cannot be promoted to QSharedPointer.
+
+ \sa QSharedPointer, QWeakPointer#tracking-qobject
+*/
+
+/*!
+ \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
+ \since 4.6
+
+ Makes this QWeakPointer hold a weak reference to directly to the QObject
+ \a obj. This function is only available if the template type \tt T is
+ QObject or derives from it.
+
+ \sa QWeakPointer#tracking-qobject
+*/
+
+/*!
\fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other)
Makes this object share \a other's pointer. The current pointer
@@ -896,6 +977,8 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
{
Q_ASSERT(obj);
QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+ Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
+
ExternalRefCountData *that = d->sharedRefcount;
if (that) {
that->weakref.ref();
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index e0fe3b1..332883a 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -115,6 +115,9 @@ public:
QWeakPointer<T> operator=(const QWeakPointer<T> &other);
QWeakPointer<T> operator=(const QSharedPointer<T> &other);
+ QWeakPointer(const QObject *other);
+ QWeakPointer<T> operator=(const QObject *other);
+
T *data() const;
void clear();
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 7b3239b..ba479f9 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -121,6 +121,13 @@ namespace QtSharedPointer {
typedef T *Basic:: *RestrictedBool;
public:
typedef T Type;
+ typedef T element_type;
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef ptrdiff_t difference_type;
inline T *data() const { return value; }
inline bool isNull() const { return !data(); }
@@ -490,6 +497,14 @@ class QWeakPointer
typedef QtSharedPointer::ExternalRefCountData Data;
public:
+ typedef T element_type;
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef ptrdiff_t difference_type;
+
inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; }
inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; }
inline bool operator !() const { return isNull(); }
@@ -634,6 +649,12 @@ bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
return ptr2 != ptr1;
}
+template <class T, class X>
+Q_INLINE_TEMPLATE typename T::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
+{
+ return ptr1.data() - ptr2.data();
+}
+
template <class T>
Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
{