diff options
author | mread <qt-info@nokia.com> | 2009-08-07 13:34:12 (GMT) |
---|---|---|
committer | mread <qt-info@nokia.com> | 2009-08-07 13:34:12 (GMT) |
commit | 5a72890b7ce12815f9567316da867006cff73f39 (patch) | |
tree | 46c8c793f19274f9ed19678d1732d2123adbdf34 /src/corelib | |
parent | 0f6f1f841cea61cbb6905de92c2ca63bd369d55d (diff) | |
parent | cc0a411e5e874aa224c26298a109973cb15ea291 (diff) | |
download | Qt-5a72890b7ce12815f9567316da867006cff73f39.zip Qt-5a72890b7ce12815f9567316da867006cff73f39.tar.gz Qt-5a72890b7ce12815f9567316da867006cff73f39.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts fixed:
src/corelib/io/qdiriterator.cpp
Diffstat (limited to 'src/corelib')
204 files changed, 6852 insertions, 3564 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 3720984..1d274c9 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -177,17 +177,6 @@ QUnifiedTimer *QUnifiedTimer::instance() return inst; } -void QUnifiedTimer::updateRecentlyStartedAnimations() -{ - if (animationsToStart.isEmpty()) - return; - - animations += animationsToStart; - updateTimer(); //we make sure we start the timer there - - animationsToStart.clear(); -} - void QUnifiedTimer::timerEvent(QTimerEvent *event) { //this is simply the time we last received a tick @@ -195,15 +184,16 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) if (time.isValid()) lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed(); - //we transfer the waiting animations into the "really running" state - updateRecentlyStartedAnimations(); if (event->timerId() == startStopAnimationTimer.timerId()) { startStopAnimationTimer.stop(); + //we transfer the waiting animations into the "really running" state + animations += animationsToStart; + animationsToStart.clear(); if (animations.isEmpty()) { animationTimer.stop(); time = QTime(); - } else { + } else if (!animationTimer.isActive()) { animationTimer.start(timingInterval, this); lastTick = 0; time.start(); @@ -219,27 +209,19 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) } } -void QUnifiedTimer::updateTimer() -{ - //we delay the call to start and stop for the animation timer so that if you - //stop and start animations in batch you don't stop/start the timer too often. - if (!startStopAnimationTimer.isActive()) - startStopAnimationTimer.start(0, this); // we delay the actual start of the animation -} - void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation) { if (animations.contains(animation) ||animationsToStart.contains(animation)) return; animationsToStart << animation; - updateTimer(); + startStopAnimationTimer.start(0, this); // we delay the check if we should start/stop the global timer } void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) { animations.removeAll(animation); animationsToStart.removeAll(animation); - updateTimer(); + startStopAnimationTimer.start(0, this); // we delay the check if we should start/stop the global timer } @@ -254,8 +236,17 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) int oldCurrentLoop = currentLoop; QAbstractAnimation::Direction oldDirection = direction; - state = newState; + // check if we should Rewind + if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running) + && oldState == QAbstractAnimation::Stopped) { + //here we reset the time if needed + //we don't call setCurrentTime because this might change the way the animation + //behaves: changing the state or changing the current value + totalCurrentTime = currentTime =(direction == QAbstractAnimation::Forward) ? + 0 : (loopCount == -1 ? q->duration() : q->totalDuration()); + } + state = newState; QPointer<QAbstractAnimation> guard(q); guard->updateState(oldState, newState); @@ -268,36 +259,22 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) if (guard) emit guard->stateChanged(oldState, newState); - // Enter running state. switch (state) { case QAbstractAnimation::Paused: case QAbstractAnimation::Running: - { - // Rewind - if (oldState == QAbstractAnimation::Stopped) { - if (guard) { - if (direction == QAbstractAnimation::Forward) - q->setCurrentTime(0); - else - q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration()); - } - - // Check if the setCurrentTime() function called stop(). - // This can happen for a 0-duration animation - if (state == QAbstractAnimation::Stopped) - return; - } - - // Register timer if our parent is not running. - if (state == QAbstractAnimation::Running && guard) { - if (!group || group->state() == QAbstractAnimation::Stopped) { - QUnifiedTimer::instance()->registerAnimation(q); - } - } else { - //new state is paused - QUnifiedTimer::instance()->unregisterAnimation(q); + //this ensures that the value is updated now that the animation is running + if(oldState == QAbstractAnimation::Stopped && guard) + guard->setCurrentTime(currentTime); + + // Register timer if our parent is not running. + if (state == QAbstractAnimation::Running && guard) { + if (!group || group->state() == QAbstractAnimation::Stopped) { + QUnifiedTimer::instance()->registerAnimation(q); } + } else { + //new state is paused + QUnifiedTimer::instance()->unregisterAnimation(q); } break; case QAbstractAnimation::Stopped: @@ -625,8 +602,8 @@ void QAbstractAnimation::start(DeletionPolicy policy) Q_D(QAbstractAnimation); if (d->state == Running) return; - d->setState(Running); d->deleteWhenStopped = policy; + d->setState(Running); } /*! @@ -648,9 +625,8 @@ void QAbstractAnimation::stop() /*! Pauses the animation. When the animation is paused, state() returns Paused. - The currenttime will remain unchanged until resume() or start() is called. - If you want to continue from the current time, call resume(). - + The value of currentTime will remain unchanged until resume() or start() + is called. If you want to continue from the current time, call resume(). \sa start(), state(), resume() */ diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h index 8da0935..e4b1fcc 100644 --- a/src/corelib/animation/qabstractanimation.h +++ b/src/corelib/animation/qabstractanimation.h @@ -125,7 +125,7 @@ protected: private: Q_DISABLE_COPY(QAbstractAnimation) - Q_DECLARE_SCOPED_PRIVATE(QAbstractAnimation) + Q_DECLARE_PRIVATE(QAbstractAnimation) }; #endif //QT_NO_ANIMATION diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 00def55..b281aa2 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -58,6 +58,8 @@ #include <QtCore/qtimer.h> #include <private/qobject_p.h> +#ifndef QT_NO_ANIMATION + QT_BEGIN_NAMESPACE class QAnimationGroup; @@ -133,11 +135,8 @@ public: protected: void timerEvent(QTimerEvent *); - void updateTimer(); private: - void updateRecentlyStartedAnimations(); - QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; @@ -147,4 +146,7 @@ private: }; QT_END_NAMESPACE -#endif + +#endif //QT_NO_ANIMATION + +#endif //QABSTRACTANIMATION_P_H diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h index 5b07524..93c6fb1 100644 --- a/src/corelib/animation/qanimationgroup.h +++ b/src/corelib/animation/qanimationgroup.h @@ -76,7 +76,7 @@ protected: private: Q_DISABLE_COPY(QAnimationGroup) - Q_DECLARE_SCOPED_PRIVATE(QAnimationGroup) + Q_DECLARE_PRIVATE(QAnimationGroup) }; #endif //QT_NO_ANIMATION diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h index 8e668f0..01252c5 100644 --- a/src/corelib/animation/qanimationgroup_p.h +++ b/src/corelib/animation/qanimationgroup_p.h @@ -59,6 +59,8 @@ #include "private/qabstractanimation_p.h" +#ifndef QT_NO_ANIMATION + QT_BEGIN_NAMESPACE class QAnimationGroupPrivate : public QAbstractAnimationPrivate @@ -76,4 +78,6 @@ public: QT_END_NAMESPACE +#endif //QT_NO_ANIMATION + #endif //QANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index 5e4b0d2..8aa04a4 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -214,7 +214,8 @@ void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState, d->connectUncontrolledAnimations(); for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); - animation->stop(); + if (oldState == Stopped) + animation->stop(); animation->setDirection(d->direction); animation->start(); } diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h index 8422102..07808f1 100644 --- a/src/corelib/animation/qparallelanimationgroup.h +++ b/src/corelib/animation/qparallelanimationgroup.h @@ -73,7 +73,7 @@ protected: private: Q_DISABLE_COPY(QParallelAnimationGroup) - Q_DECLARE_SCOPED_PRIVATE(QParallelAnimationGroup) + Q_DECLARE_PRIVATE(QParallelAnimationGroup) Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished()) }; diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h index 201eb16..949a9b2 100644 --- a/src/corelib/animation/qparallelanimationgroup_p.h +++ b/src/corelib/animation/qparallelanimationgroup_p.h @@ -57,6 +57,8 @@ #include "private/qanimationgroup_p.h" #include <QtCore/QHash> +#ifndef QT_NO_ANIMATION + QT_BEGIN_NAMESPACE class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate @@ -82,4 +84,6 @@ public: QT_END_NAMESPACE +#endif //QT_NO_ANIMATION + #endif //QPARALLELANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h index b84e940..6907d0a 100644 --- a/src/corelib/animation/qpauseanimation.h +++ b/src/corelib/animation/qpauseanimation.h @@ -72,7 +72,7 @@ protected: private: Q_DISABLE_COPY(QPauseAnimation) - Q_DECLARE_SCOPED_PRIVATE(QPauseAnimation) + Q_DECLARE_PRIVATE(QPauseAnimation) }; #endif //QT_NO_ANIMATION diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 7526a81..5f224aa 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -100,10 +100,6 @@ QT_BEGIN_NAMESPACE -typedef QPair<QObject *, QByteArray> QPropertyAnimationPair; -typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash; -Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations) - void QPropertyAnimationPrivate::updateMetaProperty() { if (!target || propertyName.isEmpty()) @@ -286,19 +282,21 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State oldState, QPropertyAnimation *animToStop = 0; { - QPropertyAnimationHash * hash = _q_runningAnimations(); - QMutexLocker locker(QMutexPool::globalInstanceGet(hash)); + QMutexLocker locker(QMutexPool::globalInstanceGet(&staticMetaObject)); + typedef QPair<QObject *, QByteArray> QPropertyAnimationPair; + typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash; + static QPropertyAnimationHash hash; QPropertyAnimationPair key(d->target, d->propertyName); if (newState == Running) { d->updateMetaProperty(); - animToStop = hash->value(key, 0); - hash->insert(key, this); + animToStop = hash.value(key, 0); + hash.insert(key, this); // update the default start value if (oldState == Stopped) { d->setDefaultStartValue(d->target->property(d->propertyName.constData())); } - } else if (hash->value(key) == this) { - hash->remove(key); + } else if (hash.value(key) == this) { + hash.remove(key); } } diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h index 6631f67..e07444c 100644 --- a/src/corelib/animation/qpropertyanimation.h +++ b/src/corelib/animation/qpropertyanimation.h @@ -78,7 +78,7 @@ protected: private: Q_PRIVATE_SLOT(d_func(), void _q_targetDestroyed()) Q_DISABLE_COPY(QPropertyAnimation) - Q_DECLARE_SCOPED_PRIVATE(QPropertyAnimation) + Q_DECLARE_PRIVATE(QPropertyAnimation) }; #endif //QT_NO_ANIMATION diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h index 68b2519..a2ae5ec 100644 --- a/src/corelib/animation/qpropertyanimation_p.h +++ b/src/corelib/animation/qpropertyanimation_p.h @@ -58,6 +58,8 @@ #include "private/qvariantanimation_p.h" +#ifndef QT_NO_ANIMATION + QT_BEGIN_NAMESPACE class QPropertyAnimationPrivate : public QVariantAnimationPrivate @@ -86,4 +88,6 @@ public: QT_END_NAMESPACE -#endif +#endif //QT_NO_ANIMATION + +#endif //QPROPERTYANIMATION_P_H diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 5932e7c..05dc307 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -269,8 +269,10 @@ QSequentialAnimationGroup::~QSequentialAnimationGroup() /*! Adds a pause of \a msecs to this animation group. - The pause is considered as a special type of animation, thus count() will be + The pause is considered as a special type of animation, thus + \l{QAnimationGroup::animationCount()}{animationCount} will be increased by one. + \sa insertPauseAt(), QAnimationGroup::addAnimation() */ QPauseAnimation *QSequentialAnimationGroup::addPause(int msecs) diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h index 81a7ff5..5d43356 100644 --- a/src/corelib/animation/qsequentialanimationgroup.h +++ b/src/corelib/animation/qsequentialanimationgroup.h @@ -83,7 +83,7 @@ protected: private: Q_DISABLE_COPY(QSequentialAnimationGroup) - Q_DECLARE_SCOPED_PRIVATE(QSequentialAnimationGroup) + Q_DECLARE_PRIVATE(QSequentialAnimationGroup) Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished()) }; diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index 555b696..8db79a0 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -56,6 +56,7 @@ #include "qsequentialanimationgroup.h" #include "private/qanimationgroup_p.h" +#ifndef QT_NO_ANIMATION QT_BEGIN_NAMESPACE @@ -108,4 +109,6 @@ public: QT_END_NAMESPACE +#endif //QT_NO_ANIMATION + #endif //QSEQUENTIALANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 48e5ec1..fdd98c2 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -267,7 +267,7 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) localProgress); qSwap(currentValue, ret); q->updateCurrentValue(currentValue); - if ((connectedSignals & changedSignalMask) && currentValue != ret) { + if ((connectedSignals[0] & changedSignalMask) && currentValue != ret) { //the value has changed emit q->valueChanged(currentValue); } diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h index 0afe80f..3e397ca 100644 --- a/src/corelib/animation/qvariantanimation.h +++ b/src/corelib/animation/qvariantanimation.h @@ -62,7 +62,7 @@ class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation Q_OBJECT Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue) Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue) - Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged) + Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY valueChanged) Q_PROPERTY(int duration READ duration WRITE setDuration) Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve) @@ -113,7 +113,7 @@ private: static void registerInterpolator(Interpolator func, int interpolationType); Q_DISABLE_COPY(QVariantAnimation) - Q_DECLARE_SCOPED_PRIVATE(QVariantAnimation) + Q_DECLARE_PRIVATE(QVariantAnimation) }; template <typename T> diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index b848e12..69e23dc 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -60,6 +60,8 @@ #include "private/qabstractanimation_p.h" +#ifndef QT_NO_ANIMATION + QT_BEGIN_NAMESPACE class QVariantAnimationPrivate : public QAbstractAnimationPrivate @@ -120,4 +122,6 @@ template<typename T > inline QVariant _q_interpolateVariant(const T &from, const QT_END_NAMESPACE +#endif //QT_NO_ANIMATION + #endif //QANIMATION_P_H diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index de4de1f..9f0e289 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -7,6 +7,8 @@ mac:HEADERS += arch/qatomic_macosx.h \ symbian:HEADERS += arch/qatomic_symbian.h \ arch/qatomic_generic.h +vxworks:HEADERS += arch/qatomic_vxworks.h + !wince*:!win32:!mac:!symbian:HEADERS += arch/qatomic_alpha.h \ arch/qatomic_avr32.h \ arch/qatomic_ia64.h \ diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h index 6c14575..17bced6 100644 --- a/src/corelib/arch/qatomic_arch.h +++ b/src/corelib/arch/qatomic_arch.h @@ -46,7 +46,9 @@ QT_BEGIN_HEADER #include "QtCore/qglobal.h" -#if defined(QT_ARCH_ALPHA) +#if defined(QT_ARCH_VXWORKS) +# include "QtCore/qatomic_vxworks.h" +#elif defined(QT_ARCH_ALPHA) # include "QtCore/qatomic_alpha.h" #elif defined(QT_ARCH_ARM) # include "QtCore/qatomic_arm.h" diff --git a/src/corelib/arch/qatomic_powerpc.h b/src/corelib/arch/qatomic_powerpc.h index ea3f458..c3b31f9 100644 --- a/src/corelib/arch/qatomic_powerpc.h +++ b/src/corelib/arch/qatomic_powerpc.h @@ -101,8 +101,6 @@ template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() { return false; } -QT_BEGIN_NAMESPACE - #if defined(Q_CC_GNU) #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) \ diff --git a/src/corelib/arch/qatomic_symbian.h b/src/corelib/arch/qatomic_symbian.h index 9b8b341..74a0ca8 100644 --- a/src/corelib/arch/qatomic_symbian.h +++ b/src/corelib/arch/qatomic_symbian.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/arch/qatomic_vxworks.h b/src/corelib/arch/qatomic_vxworks.h new file mode 100644 index 0000000..b441210 --- /dev/null +++ b/src/corelib/arch/qatomic_vxworks.h @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake spec 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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_VXWORKS_H +#define QATOMIC_VXWORKS_H + +QT_BEGIN_HEADER + +#if defined(__ppc) +# include <QtCore/qatomic_powerpc.h> +#else // generic implementation with taskLock() + +#if 0 +// we don't want to include the system header here for two function prototypes, +// because it pulls in a _lot_ of stuff that pollutes the global namespace +# include <vxWorksCommon.h> +# include <taskLib.h> +#else +extern "C" int taskLock(); +extern "C" int taskUnlock(); +#endif + + + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ + taskLock(); + bool ret = (++_q_value != 0); + taskUnlock(); + return ret; +} + +inline bool QBasicAtomicInt::deref() +{ + taskLock(); + bool ret = (--_q_value != 0); + taskUnlock(); + return ret; +} + +// Test-and-set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + taskLock(); + if (_q_value == expectedValue) { + _q_value = newValue; + taskUnlock(); + return true; + } + taskUnlock(); + return false; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch-and-store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + taskLock(); + int returnValue = _q_value; + _q_value = newValue; + taskUnlock(); + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch-and-add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + taskLock(); + int originalValue = _q_value; + _q_value += valueToAdd; + taskUnlock(); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + taskLock(); + if (_q_value == expectedValue) { + _q_value = newValue; + taskUnlock(); + return true; + } + taskUnlock(); + return false; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + taskLock(); + T *returnValue = (_q_value); + _q_value = newValue; + taskUnlock(); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + taskLock(); + T *returnValue = (_q_value); + _q_value += valueToAdd; + taskUnlock(); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +#endif // generic implementation with taskLock() + +QT_END_HEADER + +#endif // QATOMIC_VXWORKS_H diff --git a/src/corelib/arch/symbian/qatomic_symbian.cpp b/src/corelib/arch/symbian/qatomic_symbian.cpp index a228696..b08a468 100644 --- a/src/corelib/arch/symbian/qatomic_symbian.cpp +++ b/src/corelib/arch/symbian/qatomic_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/arch/vxworks/arch.pri b/src/corelib/arch/vxworks/arch.pri new file mode 100644 index 0000000..a768618 --- /dev/null +++ b/src/corelib/arch/vxworks/arch.pri @@ -0,0 +1,6 @@ +# +# VxWorks generic +# +*-ppc-* { + SOURCES += qatomic_ppc.s +} diff --git a/src/corelib/arch/vxworks/qatomic_ppc.s b/src/corelib/arch/vxworks/qatomic_ppc.s new file mode 100644 index 0000000..03971e8 --- /dev/null +++ b/src/corelib/arch/vxworks/qatomic_ppc.s @@ -0,0 +1,415 @@ + + .align 2 + .globl q_atomic_test_and_set_int + .globl .q_atomic_test_and_set_int +q_atomic_test_and_set_int: +.q_atomic_test_and_set_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int + .short 25 + .byte "q_atomic_test_and_set_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_int + .globl .q_atomic_test_and_set_acquire_int +q_atomic_test_and_set_acquire_int: +.q_atomic_test_and_set_acquire_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int + .short 33 + .byte "q_atomic_test_and_set_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_int + .globl .q_atomic_test_and_set_release_int +q_atomic_test_and_set_release_int: +.q_atomic_test_and_set_release_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int + .short 33 + .byte "q_atomic_test_and_set_release_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_ptr + .globl .q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: +.q_atomic_test_and_set_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr + .short 25 + .byte "q_atomic_test_and_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_ptr + .globl .q_atomic_test_and_set_acquire_ptr +q_atomic_test_and_set_acquire_ptr: +.q_atomic_test_and_set_acquire_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr + .short 25 + .byte "q_atomic_test_and_set_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_ptr + .globl .q_atomic_test_and_set_release_ptr +q_atomic_test_and_set_release_ptr: +.q_atomic_test_and_set_release_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr + .short 33 + .byte "q_atomic_test_and_set_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_increment + .globl .q_atomic_increment +q_atomic_increment: +.q_atomic_increment: + lwarx 4,0,3 + addi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_increment: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_increment-.q_atomic_increment + .short 18 + .byte "q_atomic_increment" + .align 2 + + .align 2 + .globl q_atomic_decrement + .globl .q_atomic_decrement +q_atomic_decrement: +.q_atomic_decrement: + lwarx 4,0,3 + subi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_decrement: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_decrement-.q_atomic_decrement + .short 18 + .byte "q_atomic_decrement" + .align 2 + + .align 2 + .globl q_atomic_set_int + .globl .q_atomic_set_int +q_atomic_set_int: +.q_atomic_set_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_int-.q_atomic_set_int + .short 16 + .byte "q_atomic_set_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_int + .globl .q_atomic_fetch_and_store_acquire_int +q_atomic_fetch_and_store_acquire_int: +.q_atomic_fetch_and_store_acquire_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int + .short 16 + .byte "q_atomic_fetch_and_store_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_int + .globl .q_atomic_fetch_and_store_release_int +q_atomic_fetch_and_store_release_int: +.q_atomic_fetch_and_store_release_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int + .short 16 + .byte "q_atomic_fetch_and_store_release_int" + .align 2 + + .align 2 + .globl q_atomic_set_ptr + .globl .q_atomic_set_ptr +q_atomic_set_ptr: +.q_atomic_set_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_ptr-.q_atomic_set_ptr + .short 16 + .byte "q_atomic_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_ptr + .globl .q_atomic_fetch_and_store_acquire_ptr +q_atomic_fetch_and_store_acquire_ptr: +.q_atomic_fetch_and_store_acquire_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr + .short 16 + .byte "q_atomic_fetch_and_store_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_ptr + .globl .q_atomic_fetch_and_store_release_ptr +q_atomic_fetch_and_store_release_ptr: +.q_atomic_fetch_and_store_release_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr + .short 16 + .byte "q_atomic_fetch_and_store_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_int + .globl .q_atomic_fetch_and_add_int +q_atomic_fetch_and_add_int: +.q_atomic_fetch_and_add_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int + .short 18 + .byte "q_atomic_fetch_and_add_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_int + .globl .q_atomic_fetch_and_add_acquire_int +q_atomic_fetch_and_add_acquire_int: +.q_atomic_fetch_and_add_acquire_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int + .short 18 + .byte "q_atomic_fetch_and_add_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_int + .globl .q_atomic_fetch_and_add_release_int +q_atomic_fetch_and_add_release_int: +.q_atomic_fetch_and_add_release_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int + .short 34 + .byte "q_atomic_fetch_and_add_release_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_ptr + .globl .q_atomic_fetch_and_add_ptr +q_atomic_fetch_and_add_ptr: +.q_atomic_fetch_and_add_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr + .short 26 + .byte "q_atomic_fetch_and_add_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_ptr + .globl .q_atomic_fetch_and_add_acquire_ptr +q_atomic_fetch_and_add_acquire_ptr: +.q_atomic_fetch_and_add_acquire_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr + .short 34 + .byte "q_atomic_fetch_and_add_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_ptr + .globl .q_atomic_fetch_and_add_release_ptr +q_atomic_fetch_and_add_release_ptr: +.q_atomic_fetch_and_add_release_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr + .short 34 + .byte "q_atomic_fetch_and_add_release_ptr" + .align 2 + +_section_.text: + .long _section_.text diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 1bf76ea..7f89a8f 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -52,7 +52,7 @@ // unistd.h is needed for the _XOPEN_UNIX macro #include <unistd.h> -#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) # include <langinfo.h> #endif @@ -225,10 +225,11 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState char *inBytes = const_cast<char *>(chars); #endif + QByteArray in; if (remainingCount) { // we have to prepend the remaining bytes from the previous conversion inBytesLeft += remainingCount; - QByteArray in(inBytesLeft, Qt::Uninitialized); + in.resize(inBytesLeft); inBytes = in.data(); memcpy(in.data(), remainingBuffer, remainingCount); @@ -362,9 +363,10 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt inBytes = const_cast<char *>(reinterpret_cast<const char *>(uc)); inBytesLeft = len * sizeof(QChar); + QByteArray in; if (convState && convState->remainingChars) { // we have one surrogate char to be prepended - QByteArray in(sizeof(QChar) + len, Qt::Uninitialized); + in.resize(sizeof(QChar) + len); inBytes = in.data(); QChar remaining = convState->state_data[0]; @@ -453,7 +455,7 @@ iconv_t QIconvCodec::createIconv_t(const char *to, const char *from) char *codeset = 0; #endif -#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) if (cd == (iconv_t) -1) { codeset = nl_langinfo(CODESET); if (codeset) diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index bca36a6..9e3fdf2 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -84,7 +84,7 @@ #include <stdlib.h> #include <ctype.h> #include <locale.h> -#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) #include <langinfo.h> #endif @@ -104,6 +104,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QTextCodecFactoryInterface_iid, QLatin1String("/codecs"))) #endif +static char qtolower(register char c) +{ if (c >= 'A' && c <= 'Z') return c + 0x20; return c; } +static bool qisalnum(register char c) +{ return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); } static bool nameMatch(const QByteArray &name, const QByteArray &test) { @@ -116,21 +120,21 @@ static bool nameMatch(const QByteArray &name, const QByteArray &test) // if the letters and numbers are the same, we have a match while (*n != '\0') { - if (isalnum((uchar)*n)) { + if (qisalnum(*n)) { for (;;) { if (*h == '\0') return false; - if (isalnum((uchar)*h)) + if (qisalnum(*h)) break; ++h; } - if (tolower((uchar)*n) != tolower((uchar)*h)) + if (qtolower(*n) != qtolower(*h)) return false; ++h; } ++n; } - while (*h && !isalnum((uchar)*h)) + while (*h && !qisalnum(*h)) ++h; return (*h == '\0'); } @@ -246,9 +250,9 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv return QString(); const int wclen_auto = 4096; - WCHAR wc_auto[wclen_auto]; + wchar_t wc_auto[wclen_auto]; int wclen = wclen_auto; - WCHAR *wc = wc_auto; + wchar_t *wc = wc_auto; int len; QString sp; bool prepend = false; @@ -288,7 +292,7 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv } else { wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, 0, 0); - wc = new WCHAR[wclen]; + wc = new wchar_t[wclen]; // and try again... } } else if (r == ERROR_NO_UNICODE_TRANSLATION) { @@ -354,7 +358,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le const char *next = 0; QString s; while((next = CharNextExA(CP_ACP, mb, 0)) != mb) { - WCHAR wc[2] ={0}; + wchar_t wc[2] ={0}; int charlength = next - mb; int len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, mb, charlength, wc, 2); if (len>0) { @@ -541,7 +545,7 @@ static void setupLocaleMapper() localeMapper = QTextCodec::codecForName("System"); #endif -#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) +#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF) if (!localeMapper) { char *charset = nl_langinfo (CODESET); if (charset) @@ -1059,16 +1063,10 @@ QList<int> QTextCodec::availableMibs() This might be needed for some applications that want to use their own mechanism for setting the locale. - Setting this codec is not supported on DOS based Windows. - \sa codecForLocale() */ void QTextCodec::setCodecForLocale(QTextCodec *c) { -#ifdef Q_WS_WIN - if (QSysInfo::WindowsVersion& QSysInfo::WV_DOS_based) - return; -#endif localeMapper = c; if (!localeMapper) setupLocaleMapper(); @@ -1555,9 +1553,13 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo } /*! - \overload + \overload - If the codec cannot be detected, this overload returns a Latin-1 QTextCodec. + Tries to detect the encoding of the provided snippet of HTML in + the given byte array, \a ba, by checking the BOM (Byte Order Mark) + and the content-type meta header and returns a QTextCodec instance + that is capable of decoding the html to unicode. If the codec cannot + be detected, this overload returns a Latin-1 QTextCodec. */ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba) { @@ -1569,10 +1571,13 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba) Tries to detect the encoding of the provided snippet \a ba by using the BOM (Byte Order Mark) and returns a QTextCodec instance - that is capable of decoding the text to unicode. If the codec + that is capable of decoding the text to unicode. If the codec cannot be detected from the content provided, \a defaultCodec is returned. + The behavior of this function is undefined if \a ba is not + encoded in unicode. + \sa codecForHtml() */ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec) @@ -1610,9 +1615,17 @@ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaul } /*! - \overload + \overload - If the codec cannot be detected, this overload returns a Latin-1 QTextCodec. + Tries to detect the encoding of the provided snippet \a ba by + using the BOM (Byte Order Mark) and returns a QTextCodec instance + that is capable of decoding the text to unicode. If the codec + cannot be detected, this overload returns a Latin-1 QTextCodec. + + The behavior of this function is undefined if \a ba is not + encoded in unicode. + + \sa codecForHtml() */ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba) { diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h index 499c0f9..5c82735 100644 --- a/src/corelib/codecs/qtextcodec_p.h +++ b/src/corelib/codecs/qtextcodec_p.h @@ -77,6 +77,33 @@ struct QTextCodecUnalignedPointer } }; +#else + +class QTextCodec +{ +public: + enum ConversionFlag { + DefaultConversion, + ConvertInvalidToNull = 0x80000000, + IgnoreHeader = 0x1, + FreeFunction = 0x2 + }; + Q_DECLARE_FLAGS(ConversionFlags, ConversionFlag) + + struct ConverterState { + ConverterState(ConversionFlags f = DefaultConversion) + : flags(f), remainingChars(0), invalidChars(0), d(0) { state_data[0] = state_data[1] = state_data[2] = 0; } + ~ConverterState() { } + ConversionFlags flags; + int remainingChars; + int invalidChars; + uint state_data[3]; + void *d; + private: + Q_DISABLE_COPY(ConverterState) + }; +}; + #endif //QT_NO_TEXTCODEC QT_END_NAMESPACE diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index abae6f7..abcc07c 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -44,23 +44,19 @@ #include "qendian.h" #include "qchar.h" -#ifndef QT_NO_TEXTCODEC - QT_BEGIN_NAMESPACE -QUtf8Codec::~QUtf8Codec() -{ -} +enum { Endian = 0, Data = 1 }; -QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +QByteArray QUtf8::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state) { uchar replacement = '?'; int rlen = 3*len; int surrogate_high = -1; if (state) { - if (state->flags & ConvertInvalidToNull) + if (state->flags & QTextCodec::ConvertInvalidToNull) replacement = 0; - if (!(state->flags & IgnoreHeader)) + if (!(state->flags & QTextCodec::IgnoreHeader)) rlen += 3; if (state->remainingChars) surrogate_high = state->state_data[0]; @@ -71,7 +67,7 @@ QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterSta uchar* cursor = (uchar*)rstr.data(); const QChar *ch = uc; int invalid = 0; - if (state && !(state->flags & IgnoreHeader)) { + if (state && !(state->flags & QTextCodec::IgnoreHeader)) { *cursor++ = 0xef; *cursor++ = 0xbb; *cursor++ = 0xbf; @@ -133,7 +129,7 @@ QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterSta rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; state->remainingChars = 0; if (surrogate_high >= 0) { state->remainingChars = 1; @@ -143,18 +139,18 @@ QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterSta return rstr; } -void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, ConverterState *state) const +QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state) { bool headerdone = false; - QChar replacement = QChar::ReplacementCharacter; + ushort replacement = QChar::ReplacementCharacter; int need = 0; int error = -1; uint uc = 0; uint min_uc = 0; if (state) { - if (state->flags & IgnoreHeader) + if (state->flags & QTextCodec::IgnoreHeader) headerdone = true; - if (state->flags & ConvertInvalidToNull) + if (state->flags & QTextCodec::ConvertInvalidToNull) replacement = QChar::Null; need = state->remainingChars; if (need) { @@ -170,40 +166,28 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C headerdone = true; } - int originalLength = target->length(); - QString &result = *target; - result.resize(originalLength + len + 1); // worst case - QChar *qch = result.data() + originalLength; + QString result(need + len + 1, Qt::Uninitialized); // worst case + ushort *qch = (ushort *)result.unicode(); uchar ch; int invalid = 0; - for (int i=0; i<len; i++) { + for (int i = 0; i < len; ++i) { ch = chars[i]; if (need) { if ((ch&0xc0) == 0x80) { uc = (uc << 6) | (ch & 0x3f); - need--; + --need; if (!need) { // utf-8 bom composes into 0xfeff code point if (!headerdone && uc == 0xfeff) { // dont do anything, just skip the BOM } else if (uc > 0xffff && uc < 0x110000) { // surrogate pair - uc -= 0x10000; - unsigned short high = uc/0x400 + 0xd800; - unsigned short low = uc%0x400 + 0xdc00; - - // resize if necessary - long where = qch - result.unicode(); - if (where + 2 >= result.length()) { - result.resize(where + 2); - qch = result.data() + where; - } - - *qch++ = QChar(high); - *qch++ = QChar(low); + Q_ASSERT((qch - (ushort*)result.unicode()) + 2 < result.length()); + *qch++ = QChar::highSurrogate(uc); + *qch++ = QChar::lowSurrogate(uc); } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) { - // error + // error: overlong sequence, UTF16 surrogate or BOM *qch++ = replacement; ++invalid; } else { @@ -221,7 +205,7 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C } } else { if (ch < 128) { - *qch++ = QLatin1Char(ch); + *qch++ = ushort(ch); headerdone = true; } else if ((ch & 0xe0) == 0xc0) { uc = ch & 0x1f; @@ -255,57 +239,35 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C ++invalid; } } - result.truncate(qch - result.unicode()); + result.truncate(qch - (ushort *)result.unicode()); if (state) { state->invalidChars += invalid; state->remainingChars = need; if (headerdone) - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; state->state_data[0] = need ? uc : 0; state->state_data[1] = need ? min_uc : 0; } -} - -QString QUtf8Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const -{ - QString result; - convertToUnicode(&result, chars, len, state); return result; } -QByteArray QUtf8Codec::name() const -{ - return "UTF-8"; -} - -int QUtf8Codec::mibEnum() const -{ - return 106; -} - -enum { Endian = 0, Data = 1 }; - -QUtf16Codec::~QUtf16Codec() -{ -} - -QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +QByteArray QUtf16::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state, DataEndianness e) { - Endianness endian = e; + DataEndianness endian = e; int length = 2*len; - if (!state || (!(state->flags & IgnoreHeader))) { + if (!state || (!(state->flags & QTextCodec::IgnoreHeader))) { length += 2; } - if (e == Detect) { - endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BE : LE; + if (e == DetectEndianness) { + endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness; } QByteArray d; d.resize(length); char *data = d.data(); - if (!state || !(state->flags & IgnoreHeader)) { + if (!state || !(state->flags & QTextCodec::IgnoreHeader)) { QChar bom(QChar::ByteOrderMark); - if (endian == BE) { + if (endian == BigEndianness) { data[0] = bom.row(); data[1] = bom.cell(); } else { @@ -314,7 +276,7 @@ QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt } data += 2; } - if (endian == BE) { + if (endian == BigEndianness) { for (int i = 0; i < len; ++i) { *(data++) = uc[i].row(); *(data++) = uc[i].cell(); @@ -328,35 +290,35 @@ QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt if (state) { state->remainingChars = 0; - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; } return d; } -QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const +QString QUtf16::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e) { - Endianness endian = e; + DataEndianness endian = e; bool half = false; uchar buf = 0; bool headerdone = false; if (state) { - headerdone = state->flags & IgnoreHeader; - if (endian == Detect) - endian = (Endianness)state->state_data[Endian]; + headerdone = state->flags & QTextCodec::IgnoreHeader; + if (endian == DetectEndianness) + endian = (DataEndianness)state->state_data[Endian]; if (state->remainingChars) { half = true; buf = state->state_data[Data]; } } - if (headerdone && endian == Detect) - endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BE : LE; + if (headerdone && endian == DetectEndianness) + endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness; QString result(len, Qt::Uninitialized); // worst case QChar *qch = (QChar *)result.unicode(); while (len--) { if (half) { QChar ch; - if (endian == LE) { + if (endian == LittleEndianness) { ch.setRow(*chars++); ch.setCell(buf); } else { @@ -364,17 +326,17 @@ QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState ch.setCell(*chars++); } if (!headerdone) { - if (endian == Detect) { - if (ch == QChar::ByteOrderSwapped && endian != BE) { - endian = LE; - } else if (ch == QChar::ByteOrderMark && endian != LE) { + if (endian == DetectEndianness) { + if (ch == QChar::ByteOrderSwapped && endian != BigEndianness) { + endian = LittleEndianness; + } else if (ch == QChar::ByteOrderMark && endian != LittleEndianness) { // ignore BOM - endian = BE; + endian = BigEndianness; } else { if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - endian = BE; + endian = BigEndianness; } else { - endian = LE; + endian = LittleEndianness; ch = QChar((ch.unicode() >> 8) | ((ch.unicode() & 0xff) << 8)); } *qch++ = ch; @@ -396,7 +358,7 @@ QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState if (state) { if (headerdone) - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; state->state_data[Endian] = endian; if (half) { state->remainingChars = 1; @@ -409,72 +371,21 @@ QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState return result; } -int QUtf16Codec::mibEnum() const -{ - return 1015; -} - -QByteArray QUtf16Codec::name() const -{ - return "UTF-16"; -} - -QList<QByteArray> QUtf16Codec::aliases() const -{ - return QList<QByteArray>(); -} - -int QUtf16BECodec::mibEnum() const -{ - return 1013; -} - -QByteArray QUtf16BECodec::name() const -{ - return "UTF-16BE"; -} - -QList<QByteArray> QUtf16BECodec::aliases() const -{ - QList<QByteArray> list; - return list; -} - -int QUtf16LECodec::mibEnum() const -{ - return 1014; -} - -QByteArray QUtf16LECodec::name() const -{ - return "UTF-16LE"; -} - -QList<QByteArray> QUtf16LECodec::aliases() const -{ - QList<QByteArray> list; - return list; -} - -QUtf32Codec::~QUtf32Codec() -{ -} - -QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +QByteArray QUtf32::convertFromUnicode(const QChar *uc, int len, QTextCodec::ConverterState *state, DataEndianness e) { - Endianness endian = e; + DataEndianness endian = e; int length = 4*len; - if (!state || (!(state->flags & IgnoreHeader))) { + if (!state || (!(state->flags & QTextCodec::IgnoreHeader))) { length += 4; } - if (e == Detect) { - endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BE : LE; + if (e == DetectEndianness) { + endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness; } QByteArray d(length, Qt::Uninitialized); char *data = d.data(); - if (!state || !(state->flags & IgnoreHeader)) { - if (endian == BE) { + if (!state || !(state->flags & QTextCodec::IgnoreHeader)) { + if (endian == BigEndianness) { data[0] = 0; data[1] = 0; data[2] = (char)0xfe; @@ -487,7 +398,7 @@ QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt } data += 4; } - if (endian == BE) { + if (endian == BigEndianness) { for (int i = 0; i < len; ++i) { uint cp = uc[i].unicode(); if (uc[i].isHighSurrogate() && i < len - 1) @@ -511,59 +422,59 @@ QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt if (state) { state->remainingChars = 0; - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; } return d; } -QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const +QString QUtf32::convertToUnicode(const char *chars, int len, QTextCodec::ConverterState *state, DataEndianness e) { - Endianness endian = e; + DataEndianness endian = e; uchar tuple[4]; int num = 0; bool headerdone = false; if (state) { - headerdone = state->flags & IgnoreHeader; - if (endian == Detect) { - endian = (Endianness)state->state_data[Endian]; + headerdone = state->flags & QTextCodec::IgnoreHeader; + if (endian == DetectEndianness) { + endian = (DataEndianness)state->state_data[Endian]; } num = state->remainingChars; memcpy(tuple, &state->state_data[Data], 4); } - if (headerdone && endian == Detect) - endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BE : LE; + if (headerdone && endian == DetectEndianness) + endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) ? BigEndianness : LittleEndianness; QString result; result.resize((num + len) >> 2 << 1); // worst case QChar *qch = (QChar *)result.unicode(); - + const char *end = chars + len; while (chars < end) { tuple[num++] = *chars++; if (num == 4) { if (!headerdone) { - if (endian == Detect) { - if (endian == Detect) { - if (tuple[0] == 0xff && tuple[1] == 0xfe && tuple[2] == 0 && tuple[3] == 0 && endian != BE) { - endian = LE; + if (endian == DetectEndianness) { + if (endian == DetectEndianness) { + if (tuple[0] == 0xff && tuple[1] == 0xfe && tuple[2] == 0 && tuple[3] == 0 && endian != BigEndianness) { + endian = LittleEndianness; num = 0; continue; - } else if (tuple[0] == 0 && tuple[1] == 0 && tuple[2] == 0xfe && tuple[3] == 0xff && endian != LE) { - endian = BE; + } else if (tuple[0] == 0 && tuple[1] == 0 && tuple[2] == 0xfe && tuple[3] == 0xff && endian != LittleEndianness) { + endian = BigEndianness; num = 0; continue; } else if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - endian = BE; + endian = BigEndianness; } else { - endian = LE; + endian = LittleEndianness; } } - } else if (((endian == BE) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple)) == QChar::ByteOrderMark) { + } else if (((endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple)) == QChar::ByteOrderMark) { num = 0; continue; } } - uint code = (endian == BE) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple); + uint code = (endian == BigEndianness) ? qFromBigEndian<quint32>(tuple) : qFromLittleEndian<quint32>(tuple); if (code >= 0x10000) { *qch++ = QChar::highSurrogate(code); *qch++ = QChar::lowSurrogate(code); @@ -574,10 +485,10 @@ QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState } } result.truncate(qch - result.unicode()); - + if (state) { if (headerdone) - state->flags |= IgnoreHeader; + state->flags |= QTextCodec::IgnoreHeader; state->state_data[Endian] = endian; state->remainingChars = num; memcpy(&state->state_data[Data], tuple, 4); @@ -585,6 +496,113 @@ QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState return result; } + +#ifndef QT_NO_TEXTCODEC + +QUtf8Codec::~QUtf8Codec() +{ +} + +QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +{ + return QUtf8::convertFromUnicode(uc, len, state); +} + +void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, ConverterState *state) const +{ + *target += QUtf8::convertToUnicode(chars, len, state); +} + +QString QUtf8Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const +{ + return QUtf8::convertToUnicode(chars, len, state); +} + +QByteArray QUtf8Codec::name() const +{ + return "UTF-8"; +} + +int QUtf8Codec::mibEnum() const +{ + return 106; +} + +QUtf16Codec::~QUtf16Codec() +{ +} + +QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +{ + return QUtf16::convertFromUnicode(uc, len, state, e); +} + +QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const +{ + return QUtf16::convertToUnicode(chars, len, state, e); +} + +int QUtf16Codec::mibEnum() const +{ + return 1015; +} + +QByteArray QUtf16Codec::name() const +{ + return "UTF-16"; +} + +QList<QByteArray> QUtf16Codec::aliases() const +{ + return QList<QByteArray>(); +} + +int QUtf16BECodec::mibEnum() const +{ + return 1013; +} + +QByteArray QUtf16BECodec::name() const +{ + return "UTF-16BE"; +} + +QList<QByteArray> QUtf16BECodec::aliases() const +{ + QList<QByteArray> list; + return list; +} + +int QUtf16LECodec::mibEnum() const +{ + return 1014; +} + +QByteArray QUtf16LECodec::name() const +{ + return "UTF-16LE"; +} + +QList<QByteArray> QUtf16LECodec::aliases() const +{ + QList<QByteArray> list; + return list; +} + +QUtf32Codec::~QUtf32Codec() +{ +} + +QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const +{ + return QUtf32::convertFromUnicode(uc, len, state, e); +} + +QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const +{ + return QUtf32::convertToUnicode(chars, len, state, e); +} + int QUtf32Codec::mibEnum() const { return 1017; @@ -633,7 +651,6 @@ QList<QByteArray> QUtf32LECodec::aliases() const return list; } +#endif //QT_NO_TEXTCODEC QT_END_NAMESPACE - -#endif //QT_NO_TEXTCODEC diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h index 749f5be..4f8f92e 100644 --- a/src/corelib/codecs/qutfcodec_p.h +++ b/src/corelib/codecs/qutfcodec_p.h @@ -54,9 +54,35 @@ // #include "QtCore/qtextcodec.h" +#include "private/qtextcodec_p.h" QT_BEGIN_NAMESPACE +enum DataEndianness +{ + DetectEndianness, + BigEndianness, + LittleEndianness +}; + +struct QUtf8 +{ + static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *); + static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *); +}; + +struct QUtf16 +{ + static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness); + static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness); +}; + +struct QUtf32 +{ + static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness); + static QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *, DataEndianness = DetectEndianness); +}; + #ifndef QT_NO_TEXTCODEC class QUtf8Codec : public QTextCodec { @@ -73,13 +99,8 @@ public: class QUtf16Codec : public QTextCodec { protected: - enum Endianness { - Detect, - BE, - LE - }; public: - QUtf16Codec() { e = Detect; } + QUtf16Codec() { e = DetectEndianness; } ~QUtf16Codec(); QByteArray name() const; @@ -90,12 +111,12 @@ public: QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const; protected: - Endianness e; + DataEndianness e; }; class QUtf16BECodec : public QUtf16Codec { public: - QUtf16BECodec() : QUtf16Codec() { e = BE; } + QUtf16BECodec() : QUtf16Codec() { e = BigEndianness; } QByteArray name() const; QList<QByteArray> aliases() const; int mibEnum() const; @@ -103,21 +124,15 @@ public: class QUtf16LECodec : public QUtf16Codec { public: - QUtf16LECodec() : QUtf16Codec() { e = LE; } + QUtf16LECodec() : QUtf16Codec() { e = LittleEndianness; } QByteArray name() const; QList<QByteArray> aliases() const; int mibEnum() const; }; class QUtf32Codec : public QTextCodec { -protected: - enum Endianness { - Detect, - BE, - LE - }; public: - QUtf32Codec() { e = Detect; } + QUtf32Codec() { e = DetectEndianness; } ~QUtf32Codec(); QByteArray name() const; @@ -128,12 +143,12 @@ public: QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const; protected: - Endianness e; + DataEndianness e; }; class QUtf32BECodec : public QUtf32Codec { public: - QUtf32BECodec() : QUtf32Codec() { e = BE; } + QUtf32BECodec() : QUtf32Codec() { e = BigEndianness; } QByteArray name() const; QList<QByteArray> aliases() const; int mibEnum() const; @@ -141,7 +156,7 @@ public: class QUtf32LECodec : public QUtf32Codec { public: - QUtf32LECodec() : QUtf32Codec() { e = LE; } + QUtf32LECodec() : QUtf32Codec() { e = LittleEndianness; } QByteArray name() const; QList<QByteArray> aliases() const; int mibEnum() const; diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h index 47015ee..f2db5ac 100644 --- a/src/corelib/concurrent/qfuture.h +++ b/src/corelib/concurrent/qfuture.h @@ -210,7 +210,7 @@ public: bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } -#ifndef QT_NO_MEMBER_TEMPLATES +#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(Q_CC_XLC) template <typename T> QFuture(const QFuture<T> &other) : d(other.d) diff --git a/src/corelib/concurrent/qfuturewatcher.h b/src/corelib/concurrent/qfuturewatcher.h index 948ecca..04d5680 100644 --- a/src/corelib/concurrent/qfuturewatcher.h +++ b/src/corelib/concurrent/qfuturewatcher.h @@ -59,7 +59,7 @@ class QFutureWatcherBasePrivate; class Q_CORE_EXPORT QFutureWatcherBase : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QFutureWatcherBase) + Q_DECLARE_PRIVATE(QFutureWatcherBase) public: QFutureWatcherBase(QObject *parent = 0); diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp index ffbb479..8b042d9 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.cpp +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.cpp @@ -42,22 +42,18 @@ #include "qtconcurrentiteratekernel.h" #if defined(Q_OS_MAC) - #include <mach/mach.h> #include <mach/mach_time.h> #include <unistd.h> - #elif defined(Q_OS_UNIX) - #include <time.h> #include <unistd.h> - #elif defined(Q_OS_WIN) - -#include <windows.h> - +#include <qt_windows.h> #endif +#include "private/qfunctions_p.h" + #ifndef QT_NO_CONCURRENT diff --git a/src/corelib/concurrent/qtconcurrentmap.cpp b/src/corelib/concurrent/qtconcurrentmap.cpp index b8c753a..797f335 100644 --- a/src/corelib/concurrent/qtconcurrentmap.cpp +++ b/src/corelib/concurrent/qtconcurrentmap.cpp @@ -41,13 +41,14 @@ /*! \namespace QtConcurrent + \inmodule QtCore \since 4.4 \brief The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded programs without using low-level threading primitives. See the \l {threads.html#qtconcurrent-intro}{Qt Concurrent} section in the \l{threads.html}{threading} documentation. - + \inheaderfile QtCore \ingroup thread */ diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.h b/src/corelib/concurrent/qtconcurrentthreadengine.h index 1f359fc..2f610de 100644 --- a/src/corelib/concurrent/qtconcurrentthreadengine.h +++ b/src/corelib/concurrent/qtconcurrentthreadengine.h @@ -238,9 +238,11 @@ protected: template <typename T> class ThreadEngineStarter : public ThreadEngineStarterBase<T> { + typedef ThreadEngineStarterBase<T> Base; + typedef ThreadEngine<T> TypedThreadEngine; public: - ThreadEngineStarter(ThreadEngine<T> *threadEngine) - :ThreadEngineStarterBase<T>(threadEngine) {} + ThreadEngineStarter(TypedThreadEngine *eng) + : Base(eng) { } T startBlocking() { diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h index dddf962..0ddefd1 100644 --- a/src/corelib/concurrent/qthreadpool.h +++ b/src/corelib/concurrent/qthreadpool.h @@ -58,7 +58,7 @@ class QThreadPoolPrivate; class Q_CORE_EXPORT QThreadPool : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QThreadPool) + Q_DECLARE_PRIVATE(QThreadPool) Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout) Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount) Q_PROPERTY(int activeThreadCount READ activeThreadCount) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 21cbd12..a6901d9 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -64,6 +64,10 @@ # endif #endif +#if defined(Q_OS_VXWORKS) +# include <envLib.h> +#endif + #if defined(Q_CC_MWERKS) && defined(Q_OS_MACX) #include <CoreServices/CoreServices.h> #endif @@ -922,7 +926,7 @@ QT_BEGIN_NAMESPACE \fn bool qt_winUnicode() \relates <QtGlobal> - Use QSysInfo::WindowsVersion and QSysInfo::WV_DOS_based instead. + This function always returns true. \sa QSysInfo */ @@ -1100,7 +1104,7 @@ bool qSharedBuild() \value WV_XP Windows XP (operating system version 5.1) \value WV_2003 Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition (operating system version 5.2) \value WV_VISTA Windows Vista, Windows Server 2008 (operating system version 6.0) - \value WV_WINDOWS7 Windows 7 (operating system version 6.1) + \value WV_WINDOWS7 Windows 7, Windows Server 2008 R2 (operating system version 6.1) Alternatively, you may use the following macros which correspond directly to the Windows operating system version number: @@ -1109,7 +1113,7 @@ bool qSharedBuild() \value WV_5_1 Operating system version 5.1, corresponds to Windows XP \value WV_5_2 Operating system version 5.2, corresponds to Windows Server 2003, Windows Server 2003 R2, Windows Home Server, and Windows XP Professional x64 Edition \value WV_6_0 Operating system version 6.0, corresponds to Windows Vista and Windows Server 2008 - \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 + \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 and Windows Server 2008 R2 CE-based versions: @@ -1397,14 +1401,7 @@ bool qSharedBuild() \macro Q_OS_QNX \relates <QtGlobal> - Defined on QNX. -*/ - -/*! - \macro Q_OS_QNX6 - \relates <QtGlobal> - - Defined on QNX RTP 6.1. + Defined on QNX Neutrino. */ /*! @@ -1673,15 +1670,11 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() if (winver) return winver; winver = QSysInfo::WV_NT; -#ifndef Q_OS_WINCE - OSVERSIONINFOA osver; - osver.dwOSVersionInfoSize = sizeof(osver); - GetVersionExA(&osver); -#else - DWORD qt_cever = 0; OSVERSIONINFOW osver; osver.dwOSVersionInfoSize = sizeof(osver); GetVersionEx(&osver); +#ifdef Q_OS_WINCE + DWORD qt_cever = 0; qt_cever = osver.dwMajorVersion * 100; qt_cever += osver.dwMinorVersion * 10; #endif @@ -1725,7 +1718,7 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() winver = QSysInfo::WV_WINDOWS7; } else { qWarning("Qt: Untested Windows version %d.%d detected!", - osver.dwMajorVersion, osver.dwMinorVersion); + int(osver.dwMajorVersion), int(osver.dwMinorVersion)); winver = QSysInfo::WV_NT_based; } } @@ -2058,34 +2051,21 @@ QString qt_error_string(int errorCode) break; default: { #ifdef Q_OS_WIN - QT_WA({ - unsigned short *string = 0; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&string, - 0, - NULL); - ret = QString::fromUtf16(string); - LocalFree((HLOCAL)string); - }, { - char *string = 0; - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&string, - 0, - NULL); - ret = QString::fromLocal8Bit(string); - LocalFree((HLOCAL)string); - }); + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + string, + 0, + NULL); + ret = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); -#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) +#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) QByteArray buf(1024, '\0'); strerror_r(errorCode, buf.data(), buf.size()); @@ -2685,6 +2665,62 @@ int qrand() */ /*! + \fn QString qtTrId(const char *id, int n = -1) + \relates <QtGlobal> + \reentrant + \since 4.6 + + Returns a translated string identified by \a id. + If no matching string is found, the id itself is returned. This + should not happen under normal conditions. + + If \a n >= 0, all occurrences of \c %n in the resulting string + are replaced with a decimal representation of \a n. In addition, + depending on \a n's value, the translation text may vary. + + Meta data and comments can be passed as documented for QObject::tr(). + In addition, it is possible to supply a source string template like that: + + \tt{//% <C string>} + + or + + \tt{\begincomment% <C string> \endcomment} + + Example: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp qttrid + + Creating QM files suitable for use with this function requires passing + the \c -idbased option to the \c lrelease tool. + + \warning This method is reentrant only if all translators are + installed \e before calling this method. Installing or removing + translators while performing translations is not supported. Doing + so will probably result in crashes or other undesirable behavior. + + \sa QObject::tr(), QCoreApplication::translate(), {Internationalization with Qt} +*/ + +/*! + \macro QT_TRID_NOOP(id) + \relates <QtGlobal> + \since 4.6 + + Marks \a id for dynamic translation. + The only purpose of this macro is to provide an anchor for attaching + meta data like to qtTrId(). + + The macro expands to \a id. + + Example: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp qttrid_noop + + \sa qtTrId(), {Internationalization with Qt} +*/ + +/*! \macro QT_POINTER_SIZE \relates <QtGlobal> diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 3493f13..19a24af 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -148,7 +148,7 @@ namespace QT_NAMESPACE {} MSDOS - MS-DOS and Windows OS2 - OS/2 OS2EMX - XFree86 on OS/2 (not PM) - WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) + WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008) WINCE - WinCE (Windows CE 5.0) CYGWIN - Cygwin SOLARIS - Sun Solaris @@ -244,8 +244,6 @@ namespace QT_NAMESPACE {} #elif defined(__DGUX__) # define Q_OS_DGUX #elif defined(__QNXNTO__) -# define Q_OS_QNX6 -#elif defined(__QNX__) # define Q_OS_QNX #elif defined(_SEQUENT_) # define Q_OS_DYNIX @@ -257,6 +255,8 @@ namespace QT_NAMESPACE {} # define Q_OS_UNIXWARE #elif defined(__INTEGRITY) # define Q_OS_INTEGRITY +#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */ +# define Q_OS_VXWORKS #elif defined(__MAKEDEPEND__) #else # error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" @@ -285,7 +285,7 @@ namespace QT_NAMESPACE {} # endif #endif -#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) +#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) #error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." #endif @@ -317,18 +317,11 @@ namespace QT_NAMESPACE {} # if !defined(MAC_OS_X_VERSION_10_6) # define MAC_OS_X_VERSION_10_6 MAC_OS_X_VERSION_10_5 + 1 # endif -# if (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_6) -# warning "Support for this version of Mac OS X is still preliminary" -# endif # if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6) -# error "This version of Mac OS X is unsupported" +# warning "This version of Mac OS X is unsupported" # endif #endif -#ifdef QT_MAC_USE_COCOA -#define QT_MAC_NO_QUICKDRAW 1 -#endif - #ifdef __LSB_VERSION__ # if __LSB_VERSION__ < 40 # error "This version of the Linux Standard Base is unsupported" @@ -440,25 +433,6 @@ namespace QT_NAMESPACE {} #elif defined(__WATCOMC__) # define Q_CC_WAT -# if defined(Q_OS_QNX4) -/* compiler flags */ -# define Q_TYPENAME -# define Q_NO_BOOL_TYPE -# define Q_CANNOT_DELETE_CONSTANT -# define mutable -/* ??? */ -# define Q_BROKEN_TEMPLATE_SPECIALIZATION -/* no template classes in QVariant */ -# define QT_NO_TEMPLATE_VARIANT -/* Wcc does not fill in functions needed by valuelists, maps, and - valuestacks implicitly */ -# define Q_FULL_TEMPLATE_INSTANTIATION -/* can we just compare the structures? */ -# define Q_FULL_TEMPLATE_INSTANTIATION_MEMCMP -/* these are not useful to our customers */ -# define QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_CURSOR -# endif /* Symbian GCCE */ #elif defined(__GCCE__) @@ -634,6 +608,13 @@ namespace QT_NAMESPACE {} # elif defined(__ghs) # define Q_CC_GHS +# elif defined(__DCC__) +# define Q_CC_DIAB +# undef Q_NO_BOOL_TYPE +# if !defined(__bool) +# define Q_NO_BOOL_TYPE +# endif + /* The UnixWare 7 UDK compiler is based on EDG and does define __EDG__ */ # elif defined(__USLC__) && defined(__SCO_VERSION__) # define Q_CC_USLC @@ -665,6 +646,11 @@ namespace QT_NAMESPACE {} # endif # endif +/* VxWorks' DIAB toolchain has an additional EDG type C++ compiler + (see __DCC__ above). This one is for C mode files (__EDG is not defined) */ +#elif defined(_DIAB_TOOL) +# define Q_CC_DIAB + /* Never tested! */ #elif defined(__HIGHC__) # define Q_CC_HIGHC @@ -676,15 +662,17 @@ namespace QT_NAMESPACE {} in which case _BOOL is not defined this is the default in 4.2 compatibility mode triggered by -compat=4 */ # if __SUNPRO_CC >= 0x500 -# if __SUNPRO_CC < 0x570 -# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -# endif +# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS /* see http://developers.sun.com/sunstudio/support/Ccompare.html */ # if __SUNPRO_CC >= 0x590 # define Q_ALIGNOF(type) __alignof__(type) # define Q_TYPEOF(expr) __typeof__(expr) # define Q_DECL_ALIGN(n) __attribute__((__aligned__(n))) -# define Q_DECL_EXPORT __attribute__((__visibility__("default"))) +// using CC 5.9: Warning: attribute visibility is unsupported and will be skipped.. +//# define Q_DECL_EXPORT __attribute__((__visibility__("default"))) +# endif +# if __SUNPRO_CC < 0x5a0 +# define Q_NO_TEMPLATE_FRIENDS # endif # if !defined(_BOOL) # define Q_NO_BOOL_TYPE @@ -724,7 +712,7 @@ namespace QT_NAMESPACE {} # define Q_DECL_ALIGNED(n) __attribute__((aligned(n))) # endif # if __HP_aCC-0 >= 062000 -# define Q_DECL_EXPORT __attribute__((visibility("default")) +# define Q_DECL_EXPORT __attribute__((visibility("default"))) # define Q_DECL_IMPORT Q_DECL_EXPORT # endif # else @@ -1152,6 +1140,15 @@ class QDataStream; # define QT_NO_COP #endif +#if defined(Q_OS_VXWORKS) +# define QT_NO_CRASHHANDLER // no popen +# define QT_NO_PROCESS // no exec*, no fork +# define QT_NO_LPR +# define QT_NO_SHAREDMEMORY // only POSIX, no SysV and in the end... +# define QT_NO_SYSTEMSEMAPHORE // not needed at all in a flat address space +# define QT_NO_QWS_MULTIPROCESS // no processes +#endif + # include <QtCore/qfeatures.h> #define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) @@ -1159,7 +1156,7 @@ class QDataStream; #ifndef Q_DECL_EXPORT # ifdef Q_OS_WIN # define Q_DECL_EXPORT __declspec(dllexport) -# elif defined(Q_CC_NOKIAX86) +# elif defined(Q_CC_NOKIAX86) || defined(Q_CC_RVCT) # define Q_DECL_EXPORT __declspec(dllexport) # elif defined(QT_VISIBILITY_AVAILABLE) # define Q_DECL_EXPORT __attribute__((visibility("default"))) @@ -1171,7 +1168,7 @@ class QDataStream; #ifndef Q_DECL_IMPORT # if defined(Q_OS_WIN) # define Q_DECL_IMPORT __declspec(dllimport) -# elif defined(Q_CC_NOKIAX86) +# elif defined(Q_CC_NOKIAX86) || defined(Q_CC_RVCT) # define Q_DECL_IMPORT __declspec(dllimport) # else # define Q_DECL_IMPORT @@ -1220,6 +1217,11 @@ class QDataStream; # else # define Q_OPENGL_EXPORT Q_DECL_IMPORT # endif +# if defined(QT_BUILD_MULTIMEDIA_LIB) +# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT +# else +# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT +# endif # if defined(QT_BUILD_OPENVG_LIB) # define Q_OPENVG_EXPORT Q_DECL_EXPORT # else @@ -1264,6 +1266,7 @@ class QDataStream; # define Q_SVG_EXPORT Q_DECL_IMPORT # define Q_CANVAS_EXPORT Q_DECL_IMPORT # define Q_OPENGL_EXPORT Q_DECL_IMPORT +# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT # define Q_OPENVG_EXPORT Q_DECL_IMPORT # define Q_XML_EXPORT Q_DECL_IMPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT @@ -1290,6 +1293,7 @@ class QDataStream; # define Q_NETWORK_EXPORT Q_DECL_EXPORT # define Q_SVG_EXPORT Q_DECL_EXPORT # define Q_OPENGL_EXPORT Q_DECL_EXPORT +# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT # define Q_OPENVG_EXPORT Q_DECL_EXPORT # define Q_XML_EXPORT Q_DECL_EXPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT @@ -1303,6 +1307,7 @@ class QDataStream; # define Q_NETWORK_EXPORT # define Q_SVG_EXPORT # define Q_OPENGL_EXPORT +# define Q_MULTIMEDIA_EXPORT # define Q_XML_EXPORT # define Q_XMLPATTERNS_EXPORT # define Q_SCRIPT_EXPORT @@ -1503,24 +1508,13 @@ inline QT3_SUPPORT bool qSysInfo(int *wordSize, bool *bigEndian) #if defined(Q_WS_WIN) || defined(Q_OS_CYGWIN) #if defined(QT3_SUPPORT) -inline QT3_SUPPORT bool qt_winUnicode() { return !(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based); } +inline QT3_SUPPORT bool qt_winUnicode() { return true; } inline QT3_SUPPORT int qWinVersion() { return QSysInfo::WindowsVersion; } #endif -#ifdef Q_OS_WINCE -#define QT_WA(uni, ansi) uni -#define QT_WA_INLINE(uni, ansi) (uni) -#elif defined(Q_CC_MWERKS) -#define QT_WA(uni, ansi) ansi -#define QT_WA_INLINE(uni, ansi) (ansi) -#elif defined(UNICODE) -#define QT_WA(uni, ansi) if (!(QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based)) { uni } else { ansi } +#define QT_WA(unicode, ansi) unicode +#define QT_WA_INLINE(unicode, ansi) (unicode) -#define QT_WA_INLINE(uni, ansi) (!(QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based) ? uni : ansi) -#else -#define QT_WA(uni, ansi) ansi -#define QT_WA_INLINE(uni, ansi) ansi -#endif #endif /* Q_WS_WIN */ #ifndef Q_OUTOFLINE_TEMPLATE @@ -1665,7 +1659,7 @@ Q_CORE_EXPORT void qBadAlloc(); template <typename T> inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } -#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) +#if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB) # define Q_FUNC_INFO __PRETTY_FUNCTION__ #elif defined(_MSC_VER) /* MSVC 2002 doesn't have __FUNCSIG__ nor can it handle QT_STRINGIFY. */ @@ -2173,7 +2167,7 @@ public: inline bool operator!() const { return !i; } - inline bool testFlag(Enum f) const { return (i & f) == f; } + inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == f ); } }; #define Q_DECLARE_FLAGS(Flags, Enum)\ @@ -2255,6 +2249,17 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk; \ --qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk) +#elif defined(Q_CC_DIAB) +// VxWorks DIAB generates unresolvable symbols, if container is a function call +# define Q_FOREACH(variable,container) \ + if(0){}else \ + for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \ + qForeachContainer(&_container_, (__typeof__(container) *) 0)->condition(); \ + ++qForeachContainer(&_container_, (__typeof__(container) *) 0)->i) \ + for (variable = *qForeachContainer(&_container_, (__typeof__(container) *) 0)->i; \ + qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk; \ + --qForeachContainer(&_container_, (__typeof__(container) *) 0)->brk) + #else # define Q_FOREACH(variable, container) \ for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \ @@ -2285,14 +2290,12 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase #endif #endif -#define Q_DECLARE_PRIVATE(Class) \ - inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \ - inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \ - friend class Class##Private; +template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; } +template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); } -#define Q_DECLARE_SCOPED_PRIVATE(Class) \ - inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr.data()); } \ - inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr.data()); } \ +#define Q_DECLARE_PRIVATE(Class) \ + inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \ + inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \ friend class Class##Private; #define Q_DECLARE_PRIVATE_D(Dptr, Class) \ @@ -2314,6 +2317,18 @@ inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase #define QT_TRANSLATE_NOOP_UTF8(scope, x) (x) #define QT_TRANSLATE_NOOP3(scope, x, comment) {x, comment} #define QT_TRANSLATE_NOOP3_UTF8(scope, x, comment) {x, comment} + +#ifndef QT_NO_TRANSLATION // ### This should enclose the NOOPs above + +// Defined in qcoreapplication.cpp +// The better name qTrId() is reserved for an upcoming function which would +// return a much more powerful QStringFormatter instead of a QString. +Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1); + +#define QT_TRID_NOOP(id) id + +#endif // QT_NO_TRANSLATION + #define QDOC_PROPERTY(text) /* @@ -2440,12 +2455,14 @@ Q_CORE_EXPORT int qt_exception2SymbianError(const std::exception& ex); #define QT_MODULE_DBUS 0x08000 #define QT_MODULE_SCRIPTTOOLS 0x10000 #define QT_MODULE_OPENVG 0x20000 +#define QT_MODULE_MULTIMEDIA 0x40000 /* Qt editions */ #define QT_EDITION_CONSOLE (QT_MODULE_CORE \ | QT_MODULE_NETWORK \ | QT_MODULE_SQL \ | QT_MODULE_SCRIPT \ + | QT_MODULE_MULTIMEDIA \ | QT_MODULE_XML \ | QT_MODULE_XMLPATTERNS \ | QT_MODULE_TEST \ @@ -2461,6 +2478,7 @@ Q_CORE_EXPORT int qt_exception2SymbianError(const std::exception& ex); | QT_MODULE_OPENGL \ | QT_MODULE_OPENVG \ | QT_MODULE_SQL \ + | QT_MODULE_MULTIMEDIA \ | QT_MODULE_XML \ | QT_MODULE_XMLPATTERNS \ | QT_MODULE_SCRIPT \ @@ -2512,6 +2530,9 @@ QT_LICENSED_MODULE(OpenVG) #if (QT_EDITION & QT_MODULE_SQL) QT_LICENSED_MODULE(Sql) #endif +#if (QT_EDITION & QT_MODULE_MULTIMEDIA) +QT_LICENSED_MODULE(Multimedia) +#endif #if (QT_EDITION & QT_MODULE_XML) QT_LICENSED_MODULE(Xml) #endif @@ -2553,32 +2574,30 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_QFUTURE #endif -/* - Turn off certain features for compilers that have problems parsing - the code. -*/ -#if (defined(Q_CC_HPACC) && defined(QT_ARCH_PARISC)) \ - || defined(Q_CC_MIPS) \ - || defined(Q_CC_XLC) -// HP aCC A.03.*, MIPSpro, and xlC cannot handle -// the template function declarations for the QtConcurrent functions -# define QT_NO_QFUTURE -# define QT_NO_CONCURRENT -#endif - -// MSVC 6.0, MSVC .NET 2002, and old versions of Sun CC can`t handle the map(), etc templates, +// MSVC 6.0 and MSVC .NET 2002, can`t handle the map(), etc templates, // but the QFuture class compiles. -#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) || (defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x590) +#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) # define QT_NO_CONCURRENT #endif -// Mingw uses a gcc 3 version which has problems with some of the -// map/filter overloads. So does IRIX and Solaris. -#if (defined(Q_OS_IRIX) || defined(Q_CC_MINGW) || defined (Q_OS_SOLARIS)) && (__GNUC__ < 4) +// gcc 3 version has problems with some of the +// map/filter overloads. +#if defined(Q_CC_GNU) && (__GNUC__ < 4) # define QT_NO_CONCURRENT_MAP # define QT_NO_CONCURRENT_FILTER #endif +#ifdef Q_OS_QNX +// QNX doesn't have SYSV style shared memory. Multiprocess QWS apps, +// shared fonts and QSystemSemaphore + QSharedMemory are not available +# define QT_NO_QWS_MULTIPROCESS +# define QT_NO_QWS_SHARE_FONTS +# define QT_NO_SYSTEMSEMAPHORE +# define QT_NO_SHAREDMEMORY +// QNX currently doesn't support forking in a thread, so disable QProcess +# define QT_NO_PROCESS +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index fdd7eee..ceec078 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1435,7 +1435,8 @@ public: ToolButtonIconOnly, ToolButtonTextOnly, ToolButtonTextBesideIcon, - ToolButtonTextUnderIcon + ToolButtonTextUnderIcon, + ToolButtonFollowStyle }; enum LayoutDirection { @@ -1589,18 +1590,6 @@ public: }; Q_DECLARE_FLAGS(TouchPointStates, TouchPointState) - enum GestureType - { - UnknownGesture, - TapGesture, - DoubleTapGesture, - TrippleTapGesture, - TapAndHoldGesture, - PanGesture, - PinchGesture - }; - - enum GestureState { NoGesture, @@ -1609,23 +1598,6 @@ public: GestureFinished = 3 }; - enum DirectionType - { - NoDirection = 0, - LeftDownDirection = 1, - DownLeftDirection = LeftDownDirection, - DownDirection = 2, - RightDownDirection = 3, - DownRightDirection = RightDownDirection, - LeftDirection = 4, - RightDirection = 6, - LeftUpDirection = 7, - UpLeftDirection = LeftUpDirection, - UpDirection = 8, - RightUpDirection = 9, - UpRightDirection = RightUpDirection - }; - } #ifdef Q_MOC_RUN ; diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h index 5df57e5..fc7d75e 100644 --- a/src/corelib/global/qt_windows.h +++ b/src/corelib/global/qt_windows.h @@ -53,6 +53,13 @@ #endif #endif +#if defined(Q_CC_MINGW) +// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation +#ifndef WINVER +#define WINVER 0x500 +#endif +#endif + #include <windows.h> #ifdef _WIN32_WCE @@ -60,7 +67,6 @@ #endif // already defined when compiled with WINVER >= 0x0500 -// and we only use them in Qt::WV_2000 and Qt::WV_98 #ifndef SPI_SETMENUANIMATION #define SPI_SETMENUANIMATION 0x1003 #endif @@ -100,6 +106,9 @@ #ifndef SPI_GETKEYBOARDCUES #define SPI_GETKEYBOARDCUES 0x100A #endif +#ifndef SPI_GETGRADIENTCAPTIONS +#define SPI_GETGRADIENTCAPTIONS 0x1008 +#endif #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif @@ -112,5 +121,31 @@ #ifndef ETO_PDY #define ETO_PDY 0x2000 #endif +#ifndef COLOR_GRADIENTACTIVECAPTION +#define COLOR_GRADIENTACTIVECAPTION 27 +#endif +#ifndef COLOR_GRADIENTINACTIVECAPTION +#define COLOR_GRADIENTINACTIVECAPTION 28 +#endif + +// already defined when compiled with WINVER >= 0x0600 +#ifndef SPI_GETFLATMENU +#define SPI_GETFLATMENU 0x1022 +#endif +#ifndef CS_DROPSHADOW +#define CS_DROPSHADOW 0x00020000 +#endif +#ifndef CLEARTYPE_QUALITY +#define CLEARTYPE_QUALITY 5 +#endif + +#ifdef Q_WS_WINCE +#ifndef LR_DEFAULTSIZE +#define LR_DEFAULTSIZE 0 +#endif +#ifndef LR_SHARED +#define LR_SHARED 0 +#endif +#endif // Q_WS_WINCE #endif // QT_WINDOWS_H diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index edbab9c..b49554e 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -66,7 +66,10 @@ win32 { SOURCES += io/qfsfileengine_iterator_unix.cpp symbian:SOURCES += io/qprocess_symbian.cpp else:SOURCES += io/qprocess_unix.cpp - mac:SOURCES += io/qsettings_mac.cpp + macx-*: { + HEADERS += io/qfilesystemwatcher_fsevents_p.h + SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp + } linux-*:{ SOURCES += \ diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index d2fb768..fbd838a 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -42,7 +42,7 @@ #include "qabstractfileengine.h" #include "private/qabstractfileengine_p.h" #include "qdatetime.h" -#include "qmutex.h" +#include "qreadwritelock.h" #include "qvariant.h" // built-in handlers #include "qfsfileengine.h" @@ -98,14 +98,14 @@ QT_BEGIN_NAMESPACE All application-wide handlers are stored in this list. The mutex must be acquired to ensure thread safety. */ -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fileEngineHandlerMutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, fileEngineHandlerMutex, (QReadWriteLock::Recursive)) static bool qt_abstractfileenginehandlerlist_shutDown = false; class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *> { public: ~QAbstractFileEngineHandlerList() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); qt_abstractfileenginehandlerlist_shutDown = true; } }; @@ -122,7 +122,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers) */ QAbstractFileEngineHandler::QAbstractFileEngineHandler() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); fileEngineHandlers()->prepend(this); } @@ -132,7 +132,7 @@ QAbstractFileEngineHandler::QAbstractFileEngineHandler() */ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); // Remove this handler from the handler list only if the list is valid. if (!qt_abstractfileenginehandlerlist_shutDown) fileEngineHandlers()->removeAll(this); @@ -166,12 +166,14 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - QMutexLocker locker(fileEngineHandlerMutex()); + { + QReadLocker locker(fileEngineHandlerMutex()); - // check for registered handlers that can load the file - for (int i = 0; i < fileEngineHandlers()->size(); i++) { - if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) - return ret; + // check for registered handlers that can load the file + for (int i = 0; i < fileEngineHandlers()->size(); i++) { + if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) + return ret; + } } #ifdef QT_BUILD_CORE_LIB diff --git a/src/corelib/io/qabstractfileengine.h b/src/corelib/io/qabstractfileengine.h index 07c92d2..54eb6de 100644 --- a/src/corelib/io/qabstractfileengine.h +++ b/src/corelib/io/qabstractfileengine.h @@ -196,7 +196,7 @@ protected: QScopedPointer<QAbstractFileEnginePrivate> d_ptr; private: - Q_DECLARE_SCOPED_PRIVATE(QAbstractFileEngine) + Q_DECLARE_PRIVATE(QAbstractFileEngine) Q_DISABLE_COPY(QAbstractFileEngine) }; diff --git a/src/corelib/io/qbuffer.h b/src/corelib/io/qbuffer.h index ce5f605..e078d05 100644 --- a/src/corelib/io/qbuffer.h +++ b/src/corelib/io/qbuffer.h @@ -96,7 +96,7 @@ protected: qint64 writeData(const char *data, qint64 len); private: - Q_DECLARE_SCOPED_PRIVATE(QBuffer) + Q_DECLARE_PRIVATE(QBuffer) Q_DISABLE_COPY(QBuffer) Q_PRIVATE_SLOT(d_func(), void _q_emitSignals()) diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 244299c..1023868 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -362,17 +362,19 @@ QDataStream::~QDataStream() /*! \fn QIODevice *QDataStream::device() const - Returns the I/O device currently set. + Returns the I/O device currently set, or 0 if no + device is currently set. - \sa setDevice(), unsetDevice() + \sa setDevice() */ /*! void QDataStream::setDevice(QIODevice *d) - Sets the I/O device to \a d. + Sets the I/O device to \a d, which can be 0 + to unset to current I/O device. - \sa device(), unsetDevice() + \sa device() */ void QDataStream::setDevice(QIODevice *d) diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 5ef4356..f54fbdc 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -60,7 +60,7 @@ class Q_CORE_EXPORT QDir protected: QScopedPointer<QDirPrivate> d_ptr; private: - Q_DECLARE_SCOPED_PRIVATE(QDir) + Q_DECLARE_PRIVATE(QDir) public: enum Filter { Dirs = 0x001, Files = 0x002, diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 12fe258..a91c112 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -118,26 +118,28 @@ public: QDir::Filters filters, QDirIterator::IteratorFlags flags); ~QDirIteratorPrivate(); - void pushSubDirectory(const QString &path, const QStringList &nameFilters, - QDir::Filters filters); void advance(); - bool shouldFollowDirectory(const QFileInfo &); + + void pushDirectory(const QFileInfo &fileInfo); + void checkAndPushDirectory(const QFileInfo &); bool matchesFilters(const QString &fileName, const QFileInfo &fi) const; - QSet<QString> visitedLinks; + const QString path; + const QStringList nameFilters; + const QDir::Filters filters; + const QDirIterator::IteratorFlags iteratorFlags; + +#ifndef QT_NO_REGEXP + QVector<QRegExp> nameRegExps; +#endif + QScopedPointer<QAbstractFileEngine> engine; QDirIteratorPrivateIteratorStack fileEngineIterators; - QString path; - QFileInfo nextFileInfo; - //This fileinfo is the current that we will return from the public API QFileInfo currentFileInfo; - QString currentFilePath; - QDirIterator::IteratorFlags iteratorFlags; - QDir::Filters filters; - QStringList nameFilters; - bool followNextDir; - bool first; - bool done; + QFileInfo nextFileInfo; + + // Loop protection + QSet<QString> visitedLinks; QDirIterator *q; }; @@ -147,15 +149,24 @@ public: */ QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, QDir::Filters filters, QDirIterator::IteratorFlags flags) - : path(path), nextFileInfo(path), iteratorFlags(flags), followNextDir(false), first(true), done(false) + : engine(QAbstractFileEngine::create(path)) + , path(path) + , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters) + , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters) + , iteratorFlags(flags) { - if (filters == QDir::NoFilter) - filters = QDir::AllEntries; - this->filters = filters; - this->nameFilters = nameFilters; +#ifndef QT_NO_REGEXP + nameRegExps.reserve(nameFilters.size()); + for (int i = 0; i < nameFilters.size(); ++i) + nameRegExps.append( + QRegExp(nameFilters.at(i), + (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, + QRegExp::Wildcard)); +#endif - pushSubDirectory(nextFileInfo.isSymLink() ? nextFileInfo.canonicalFilePath() : path, - nameFilters, filters); + // Populate fields for hasNext() and next() + pushDirectory(QFileInfo(path)); + advance(); } /*! @@ -168,24 +179,19 @@ QDirIteratorPrivate::~QDirIteratorPrivate() /*! \internal */ -void QDirIteratorPrivate::pushSubDirectory(const QString &path, const QStringList &nameFilters, - QDir::Filters filters) +void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo) { - if (iteratorFlags & QDirIterator::FollowSymlinks) { - if (nextFileInfo.filePath() != path) - nextFileInfo.setFile(path); - if (nextFileInfo.isSymLink()) { - visitedLinks << nextFileInfo.canonicalFilePath(); - } else { - visitedLinks << nextFileInfo.absoluteFilePath(); - } - } - - if (engine.isNull()) { - engine.reset(QAbstractFileEngine::create(this->path)); - } - - if (!engine.isNull()) { + QString path = fileInfo.filePath(); + +#ifdef Q_OS_WIN + if (fileInfo.isSymLink()) + path = fileInfo.canonicalFilePath(); +#endif + + if (iteratorFlags & QDirIterator::FollowSymlinks) + visitedLinks << fileInfo.canonicalFilePath(); + + if (engine) { engine->setFileName(path); QAbstractFileEngineIterator *it = engine->beginEntryList(filters, nameFilters); if (it) { @@ -202,95 +208,64 @@ void QDirIteratorPrivate::pushSubDirectory(const QString &path, const QStringLis */ void QDirIteratorPrivate::advance() { - // Store the current entry - if (!fileEngineIterators.isEmpty()) - currentFilePath = fileEngineIterators.top()->currentFilePath(); - - // Advance to the next entry - if (followNextDir) { - // Start by navigating into the current directory. - followNextDir = false; - - QAbstractFileEngineIterator *it = fileEngineIterators.top(); - - QString subDir = it->currentFilePath(); -#ifdef Q_OS_WIN - if (nextFileInfo.isSymLink()) - subDir = nextFileInfo.canonicalFilePath(); -#endif - pushSubDirectory(subDir, it->nameFilters(), it->filters()); - } - while (!fileEngineIterators.isEmpty()) { - QAbstractFileEngineIterator *it = fileEngineIterators.top(); // Find the next valid iterator that matches the filters. - bool foundDirectory = false; - while (it->hasNext()) { + while (fileEngineIterators.top()->hasNext()) { + QAbstractFileEngineIterator *it = fileEngineIterators.top(); it->next(); + const QFileInfo info = it->currentFileInfo(); + checkAndPushDirectory(it->currentFileInfo()); + if (matchesFilters(it->currentFileName(), info)) { currentFileInfo = nextFileInfo; nextFileInfo = info; - // Signal that we want to follow this entry. - followNextDir = shouldFollowDirectory(nextFileInfo); + //We found a matching entry. return; - - } else if (iteratorFlags & QDirIterator::Subdirectories) { - - if (!shouldFollowDirectory(info)) - continue; - QString subDir = it->currentFilePath(); -#ifdef Q_OS_WIN - if (info.isSymLink()) - subDir = info.canonicalFilePath(); -#endif - pushSubDirectory(subDir, it->nameFilters(), it->filters()); - - foundDirectory = true; - break; } } - if (!foundDirectory) - delete fileEngineIterators.pop(); + + delete fileEngineIterators.pop(); } + currentFileInfo = nextFileInfo; - done = true; + nextFileInfo = QFileInfo(); } /*! \internal */ -bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo) +void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo) { // If we're doing flat iteration, we're done. if (!(iteratorFlags & QDirIterator::Subdirectories)) - return false; - + return; + // Never follow non-directory entries if (!fileInfo.isDir()) - return false; + return; + // Follow symlinks only when asked + if (!(iteratorFlags & QDirIterator::FollowSymlinks) && fileInfo.isSymLink()) + return; // Never follow . and .. - if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String("..")) - return false; + QString fileName = fileInfo.fileName(); + if (QLatin1String(".") == fileName || QLatin1String("..") == fileName) + return; - - // Check symlinks - if (fileInfo.isSymLink() && !(iteratorFlags & QDirIterator::FollowSymlinks)) { - // Follow symlinks only if FollowSymlinks was passed - return false; - } + // No hidden directories unless requested + if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden()) + return; // Stop link loops if (visitedLinks.contains(fileInfo.canonicalFilePath())) - return false; - - return true; + return; + + pushDirectory(fileInfo); } - /*! \internal @@ -304,10 +279,7 @@ bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo) */ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const { - if (fileName.isEmpty()) { - // invalid entry - return false; - } + Q_ASSERT(!fileName.isEmpty()); // filter . and ..? const int fileNameSize = fileName.size(); @@ -318,16 +290,15 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf return false; // name filter -#ifndef QT_NO_REGEXP - const bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*"))); +#ifndef QT_NO_REGEXP // Pass all entries through name filters, except dirs if the AllDirs - if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) { + if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) { bool matched = false; - for (int i = 0; i < nameFilters.size(); ++i) { - QRegExp regexp(nameFilters.at(i), - (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, - QRegExp::Wildcard); - if (regexp.exactMatch(fileName)) { + for (QVector<QRegExp>::const_iterator iter = nameRegExps.constBegin(), + end = nameRegExps.constEnd(); + iter != end; ++iter) { + + if (iter->exactMatch(fileName)) { matched = true; break; } @@ -348,17 +319,11 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf || (!fi.exists() && fi.isSymLink()))) return false; - - if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink()) - || (!fi.exists() && fi.isSymLink()))) { - return false; - } - // skip directories const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs)); if (skipDirs && fi.isDir()) { - if (!(includeHidden && !dotOrDotDot && fi.isHidden()) - || (includeSystem && !fi.exists() && fi.isSymLink())) + if (!((includeHidden && !dotOrDotDot && fi.isHidden()) + || (includeSystem && !fi.exists() && fi.isSymLink()))) return false; } @@ -383,7 +348,7 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf || (doExecutable && !fi.isExecutable()))) { return false; } - + return true; } @@ -425,7 +390,7 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags) \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags)) + : d(new QDirIteratorPrivate(path, QStringList(), filters, flags)) { d->q = this; } @@ -443,7 +408,7 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags)) + : d(new QDirIteratorPrivate(path, QStringList(), QDir::NoFilter, flags)) { d->q = this; } @@ -460,7 +425,7 @@ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) passed to the flags. \warning This constructor expects \c flags to be left at its default value. Use the - constructors that do not take the \a filters argument instead. + constructors that do not take the \a filters argument instead. \sa hasNext(), next(), IteratorFlags */ @@ -490,8 +455,6 @@ QDirIterator::~QDirIterator() */ QString QDirIterator::next() { - if (!hasNext()) - return QString(); d->advance(); return filePath(); } @@ -504,22 +467,17 @@ QString QDirIterator::next() */ bool QDirIterator::hasNext() const { - if (d->first) { - d->first = false; - d->advance(); - } - return !d->done; + return !d->fileEngineIterators.isEmpty(); } /*! Returns the file name for the current directory entry, without the path - prepended. If the current entry is invalid (i.e., isValid() returns - false), a null QString is returned. + prepended. + + This function is convenient when iterating a single directory. When using + the QDirIterator::Subdirectories flag, you can use filePath() to get the + full path. - This function is provided for the convenience when iterating single - directories. For recursive iteration, you should call filePath() or - fileInfo() instead. - \sa filePath(), fileInfo() */ QString QDirIterator::fileName() const @@ -528,20 +486,17 @@ QString QDirIterator::fileName() const } /*! - Returns the full file path for the current directory entry. If the current - entry is invalid (i.e., isValid() returns false), a null QString is - returned. + Returns the full file path for the current directory entry. \sa fileInfo(), fileName() */ QString QDirIterator::filePath() const { - return d->currentFilePath; + return d->currentFileInfo.filePath(); } /*! - Returns a QFileInfo for the current directory entry. If the current entry - is invalid (i.e., isValid() returns false), a null QFileInfo is returned. + Returns a QFileInfo for the current directory entry. \sa filePath(), fileName() */ diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index 24ce617..f448609 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -64,7 +64,7 @@ class Q_CORE_EXPORT QFile : public QIODevice #ifndef QT_NO_QOBJECT Q_OBJECT #endif - Q_DECLARE_SCOPED_PRIVATE(QFile) + Q_DECLARE_PRIVATE(QFile) public: diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index afc7c31..c568369 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -117,11 +117,7 @@ bool QFileInfoPrivate::hasAccess(Access access) const if (access == ExecuteAccess) return getFileFlags(QAbstractFileEngine::ExeUserPerm); - QT_WA( { - return ::_waccess((TCHAR *)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0; - } , { - return QT_ACCESS(QFSFileEnginePrivate::win95Name(data->fileName), mode) == 0; - } ); + return ::_waccess((wchar_t*)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0; #endif return false; } diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index c73823a..5295b16 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -168,7 +168,7 @@ public: protected: QScopedPointer<QFileInfoPrivate> d_ptr; private: - Q_DECLARE_SCOPED_PRIVATE(QFileInfo) + Q_DECLARE_PRIVATE(QFileInfo) }; Q_DECLARE_TYPEINFO(QFileInfo, Q_MOVABLE_TYPE); diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 8f18df8..883a77a 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -58,6 +58,9 @@ # include "qfilesystemwatcher_inotify_p.h" # include "qfilesystemwatcher_dnotify_p.h" #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) +# include "qfilesystemwatcher_fsevents_p.h" +# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) # include "qfilesystemwatcher_kqueue_p.h" #elif defined(Q_OS_SYMBIAN) # include "qfilesystemwatcher_symbian_p.h" @@ -245,7 +248,12 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine() eng = QDnotifyFileSystemWatcherEngine::create(); return eng; #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) - return QKqueueFileSystemWatcherEngine::create(); +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) + return QFSEventsFileSystemWatcherEngine::create(); + else +# endif + return QKqueueFileSystemWatcherEngine::create(); #elif defined(Q_OS_SYMBIAN) return new QSymbianFileSystemWatcherEngine; #else @@ -380,15 +388,17 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re \note The act of monitoring files and directories for modifications consumes system resources. This implies there is a limit to the number of files and directories your process can - monitor simultaneously. On Mac OS and all BSD variants, for + monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for example, an open file descriptor is required for each monitored - file. The system limits the number of open file descriptors to 256 + file. Some system limits the number of open file descriptors to 256 by default. This means that addPath() and addPaths() will fail if your process tries to add more than 256 files or directories to the file system monitor. Also note that your process may have other file descriptors open in addition to the ones for files being monitored, and these other open descriptors also count in - the total. + the total. Mac OS X 10.5 and up use a different backend and do not + suffer from this issue. + \sa QFile, QDir */ diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h index 76a6c60..60458e5 100644 --- a/src/corelib/io/qfilesystemwatcher.h +++ b/src/corelib/io/qfilesystemwatcher.h @@ -57,7 +57,7 @@ class QFileSystemWatcherPrivate; class Q_CORE_EXPORT QFileSystemWatcher : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QFileSystemWatcher) + Q_DECLARE_PRIVATE(QFileSystemWatcher) public: QFileSystemWatcher(QObject *parent = 0); diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp index c68af85..6df3746 100644 --- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp @@ -59,6 +59,8 @@ #include <fcntl.h> #include <time.h> +#include "private/qcore_unix_p.h" + #ifdef QT_LINUXBASE /* LSB doesn't standardize these */ @@ -80,7 +82,7 @@ static void (*qfswd_old_sigio_handler)(int) = 0; static void (*qfswd_old_sigio_action)(int, siginfo_t *, void *) = 0; static void qfswd_sigio_monitor(int signum, siginfo_t *i, void *v) { - ::write(qfswd_fileChanged_pipe[1], &i->si_fd, sizeof(int)); + qt_safe_write(qfswd_fileChanged_pipe[1], reinterpret_cast<char*>(&i->si_fd), sizeof(int)); if (qfswd_old_sigio_handler && qfswd_old_sigio_handler != SIG_IGN) qfswd_old_sigio_handler(signum); @@ -121,9 +123,7 @@ QDnotifySignalThread::QDnotifySignalThread() { moveToThread(this); - ::pipe(qfswd_fileChanged_pipe); - ::fcntl(qfswd_fileChanged_pipe[0], F_SETFL, - ::fcntl(qfswd_fileChanged_pipe[0], F_GETFL) | O_NONBLOCK); + qt_safe_pipe(qfswd_fileChanged_pipe, O_NONBLOCK); struct sigaction oldAction; struct sigaction action; @@ -181,7 +181,7 @@ void QDnotifySignalThread::run() void QDnotifySignalThread::readFromDnotify() { int fd; - int readrv = ::read(qfswd_fileChanged_pipe[0], &fd,sizeof(int)); + int readrv = qt_safe_read(qfswd_fileChanged_pipe[0], reinterpret_cast<char*>(&fd), sizeof(int)); // Only expect EAGAIN or EINTR. Other errors are assumed to be impossible. if(readrv != -1) { Q_ASSERT(readrv == sizeof(int)); @@ -207,9 +207,9 @@ QDnotifyFileSystemWatcherEngine::~QDnotifyFileSystemWatcherEngine() for(QHash<int, Directory>::ConstIterator iter = fdToDirectory.constBegin(); iter != fdToDirectory.constEnd(); ++iter) { - ::close(iter->fd); + qt_safe_close(iter->fd); if(iter->parentFd) - ::close(iter->parentFd); + qt_safe_close(iter->parentFd); } } @@ -353,7 +353,7 @@ QStringList QDnotifyFileSystemWatcherEngine::removePaths(const QStringList &path if(!directory.isMonitored && directory.files.isEmpty()) { // No longer needed - ::close(directory.fd); + qt_safe_close(directory.fd); pathToFD.remove(directory.path); fdToDirectory.remove(fd); } @@ -419,9 +419,9 @@ void QDnotifyFileSystemWatcherEngine::refresh(int fd) } if(!directory.isMonitored && directory.files.isEmpty()) { - ::close(directory.fd); + qt_safe_close(directory.fd); if(directory.parentFd) { - ::close(directory.parentFd); + qt_safe_close(directory.parentFd); parentToFD.remove(directory.parentFd); } fdToDirectory.erase(iter); diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp new file mode 100644 index 0000000..cb276b7 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qplatformdefs.h> + +#include "qfilesystemwatcher.h" +#include "qfilesystemwatcher_fsevents_p.h" + +#include <qdebug.h> +#include <qfile.h> +#include <qdatetime.h> +#include <qfileinfo.h> +#include <qvarlengtharray.h> + +#include <mach/mach.h> +#include <sys/types.h> +#include <CoreFoundation/CFRunLoop.h> +#include <CoreFoundation/CFUUID.h> +#include <CoreServices/CoreServices.h> +#include <AvailabilityMacros.h> +#include <private/qcore_mac_p.h> + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Static operator overloading so for the sake of some convieniece. +// They only live in this compilation unit to avoid polluting Qt in general. +static bool operator==(const struct ::timespec &left, const struct ::timespec &right) +{ + return left.tv_sec == right.tv_sec + && left.tv_nsec == right.tv_nsec; +} + +static bool operator==(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return left.st_dev == right.st_dev + && left.st_mode == right.st_mode + && left.st_size == right.st_size + && left.st_ino == right.st_ino + && left.st_uid == right.st_uid + && left.st_gid == right.st_gid + && left.st_mtimespec == right.st_mtimespec + && left.st_ctimespec == right.st_ctimespec + && left.st_flags == right.st_flags; +} + +static bool operator!=(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return !(operator==(left, right)); +} + + +static void addPathToHash(PathHash &pathHash, const QString &key, const QFileInfo &fileInfo, + const QString &path) +{ + PathInfoList &list = pathHash[key]; + list.push_back(PathInfo(path, + fileInfo.absoluteFilePath().normalized(QString::NormalizationForm_D).toUtf8())); + pathHash.insert(key, list); +} + +static void removePathFromHash(PathHash &pathHash, const QString &key, const QString &path) +{ + PathInfoList &list = pathHash[key]; + // We make the assumption that the list contains unique paths + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + if (it->originalPath == path) { + list.erase(it); + break; + } + ++it; + } + if (list.isEmpty()) + pathHash.remove(key); +} + +static void stopFSStream(FSEventStreamRef stream) +{ + if (stream) { + FSEventStreamStop(stream); + FSEventStreamInvalidate(stream); + } +} + +static QString createFSStreamPath(const QString &absolutePath) +{ + // The path returned has a trailing slash, so ensure that here. + QString string = absolutePath; + string.reserve(string.size() + 1); + string.append(QLatin1Char('/')); + return string; +} + +static void cleanupFSStream(FSEventStreamRef stream) +{ + if (stream) + FSEventStreamRelease(stream); +} + +const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer /* | kFSEventStreamCreateFlagWatchRoot*/); + +const CFTimeInterval Latency = 0.033; // This will do updates 30 times a second which is probably more than you need. +#endif + +QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine() + : fsStream(0), pathsToWatch(0), threadsRunLoop(0) +{ +} + +QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // I assume that at this point, QFileSystemWatcher has already called stop + // on me, so I don't need to invalidate or stop my stream, simply + // release it. + cleanupFSStream(fsStream); + if (pathsToWatch) + CFRelease(pathsToWatch); +#endif +} + +QFSEventsFileSystemWatcherEngine *QFSEventsFileSystemWatcherEngine::create() +{ + return new QFSEventsFileSystemWatcherEngine(); +} + +QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + QStringList failedToAdd; + // if we have a running FSStreamEvent, we have to kill it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + // Brain-dead approach, but works. FSEvents actually can already read sub-trees, but since it's + // work to figure out if we are doing a double register, we just register it twice as FSEvents + // seems smart enough to only deliver one event. We also duplicate directory entries in here + // (e.g., if you watch five files in the same directory, you get that directory included in the + // array 5 times). This stupidity also makes remove work correctly though. I'll freely admit + // that we could make this a bit smarter. If you do, check the auto-tests, they should catch at + // least a couple of the issues. + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + for (int i = 0; i < paths.size(); ++i) { + const QString &path = paths.at(i); + + QFileInfo fileInfo(path); + if (!fileInfo.exists()) { + failedToAdd.append(path); + continue; + } + + if (fileInfo.isDir()) { + if (directories->contains(path)) { + failedToAdd.append(path); + continue; + } else { + directories->append(path); + // Full file path for dirs. + QCFString cfpath(createFSStreamPath(fileInfo.absoluteFilePath())); + addPathToHash(dirPathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } else { + if (files->contains(path)) { + failedToAdd.append(path); + continue; + } else { + // Just the absolute path (minus it's filename) for files. + QCFString cfpath(createFSStreamPath(fileInfo.absolutePath())); + files->append(path); + addPathToHash(filePathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } + } + if (CFArrayGetCount(tmpArray) > 0) { + if (pathsToWatch) { + CFArrayAppendArray(tmpArray, pathsToWatch, CFRangeMake(0, CFArrayGetCount(pathsToWatch))); + CFRelease(pathsToWatch); + } + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + } + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, + idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + + return failedToAdd; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::warmUpFSEvents() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // This function assumes that the mutex has already been grabbed before calling it. + // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-). + start(); + waitCondition.wait(&mutex); +#endif +} + +QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + // short circuit for smarties that call remove before add and we have nothing. + if (pathsToWatch == 0) + return paths; + QStringList failedToRemove; + // if we have a running FSStreamEvent, we have to stop it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + fsStream = 0; + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + CFIndex itemCount = CFArrayGetCount(pathsToWatch); + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, itemCount, + pathsToWatch); + CFRelease(pathsToWatch); + pathsToWatch = 0; + for (int i = 0; i < paths.size(); ++i) { + // Get the itemCount at the beginning to avoid any overruns during the iteration. + itemCount = CFArrayGetCount(tmpArray); + const QString &path = paths.at(i); + QFileInfo fi(path); + QCFString cfpath(createFSStreamPath(fi.absolutePath())); + + CFIndex index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + files->removeAll(path); + removePathFromHash(filePathInfoHash, cfpath, path); + } else { + // Could be a directory we are watching instead. + QCFString cfdirpath(createFSStreamPath(fi.absoluteFilePath())); + index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + directories->removeAll(path); + removePathFromHash(dirPathInfoHash, cfpath, path); + } else { + failedToRemove.append(path); + } + } + } + itemCount = CFArrayGetCount(tmpArray); + if (itemCount != 0) { + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + } + return failedToRemove; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals) +{ + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + struct ::stat64 newInfo; + if (::stat64(it->absolutePath, &newInfo) == 0) { + if (emitSignals) { + if (newInfo != it->savedInfo) { + it->savedInfo = newInfo; + if (directory) + emit directoryChanged(it->originalPath, false); + else + emit fileChanged(it->originalPath, false); + } + } else { + it->savedInfo = newInfo; + } + } else { + if (errno == ENOENT) { + if (emitSignals) { + if (directory) + emit directoryChanged(it->originalPath, true); + else + emit fileChanged(it->originalPath, true); + } + it = list.erase(it); + continue; + } else { + qWarning("%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s", + __FILE__, __LINE__, qPrintable(it->originalPath), strerror(errno)); + + } + } + ++it; + } +} + +void QFSEventsFileSystemWatcherEngine::updateHash(PathHash &pathHash) +{ + PathHash::iterator HashEnd = pathHash.end(); + PathHash::iterator it = pathHash.begin(); + const bool IsDirectory = (&pathHash == &dirPathInfoHash); + while (it != HashEnd) { + updateList(it.value(), IsDirectory, false); + if (it.value().isEmpty()) + it = pathHash.erase(it); + else + ++it; + } +} +#endif + +void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , + void *clientCallBackInfo, size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId []) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo); + QMutexLocker locker(&watcher->mutex); + CFArrayRef paths = static_cast<CFArrayRef>(eventPaths); + for (size_t i = 0; i < numEvents; ++i) { + const QString path = QCFString::toQString( + static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i))); + const FSEventStreamEventFlags pathFlags = eventFlags[i]; + // There are several flags that may be passed, but we really don't care about them ATM. + // Here they are and why we don't care. + // kFSEventStreamEventFlagHistoryDone--(very unlikely to be gotten, but even then, not much changes). + // kFSEventStreamEventFlagMustScanSubDirs--Likely means the data is very much out of date, we + // aren't coalescing our directories, so again not so much of an issue + // kFSEventStreamEventFlagRootChanged | kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount-- + // These three flags indicate something has changed, but the stat will likely show this, so + // there's not really much to worry about. + // (btw, FSEvents is not the correct way of checking for mounts/unmounts, + // there are real CarbonCore events for that.) + Q_UNUSED(pathFlags); + if (watcher->filePathInfoHash.contains(path)) + watcher->updateList(watcher->filePathInfoHash[path], false, true); + + if (watcher->dirPathInfoHash.contains(path)) + watcher->updateList(watcher->dirPathInfoHash[path], true, true); + } +#else + Q_UNUSED(clientCallBackInfo); + Q_UNUSED(numEvents); + Q_UNUSED(eventPaths); + Q_UNUSED(eventFlags); +#endif +} + +void QFSEventsFileSystemWatcherEngine::stop() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QMutexLocker locker(&mutex); + stopFSStream(fsStream); + if (threadsRunLoop) { + CFRunLoopStop(threadsRunLoop); + waitForStop.wait(&mutex); + } +#endif +} + +void QFSEventsFileSystemWatcherEngine::updateFiles() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QMutexLocker locker(&mutex); + updateHash(filePathInfoHash); + updateHash(dirPathInfoHash); + if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) { + // Everything disappeared before we got to start, don't bother. + stop(); + cleanupFSStream(fsStream); + } + waitCondition.wakeAll(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::run() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + threadsRunLoop = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode); + bool startedOK = FSEventStreamStart(fsStream); + // It's recommended by Apple that you only update the files after you've started + // the stream, because otherwise you might miss an update in between starting it. + updateFiles(); +#ifdef QT_NO_DEBUG + Q_UNUSED(startedOK); +#else + Q_ASSERT(startedOK); +#endif + // If for some reason we called stop up above (and invalidated our stream), this call will return + // immediately. + CFRunLoopRun(); + threadsRunLoop = 0; + QMutexLocker locker(&mutex); + waitForStop.wakeAll(); +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h new file mode 100644 index 0000000..ffc0c68 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef FILEWATCHER_FSEVENTS_P_H +#define FILEWATCHER_FSEVENTS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qfilesystemwatcher_p.h" + +#include <QtCore/qmutex.h> +#include <QtCore/qwaitcondition.h> +#include <QtCore/qthread.h> +#include <QtCore/QHash> +#include <QtCore/QLinkedList> +#include <private/qcore_mac_p.h> +#include <sys/stat.h> + +typedef struct __FSEventStream *FSEventStreamRef; +typedef const struct __FSEventStream *ConstFSEventStreamRef; +typedef const struct __CFArray *CFArrayRef; +typedef UInt32 FSEventStreamEventFlags; +typedef uint64_t FSEventStreamEventId; + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation +// details to be used as a long-standing record. Since I'm going to have to store this information, I can +// do the stat myself too. +struct PathInfo { + PathInfo(const QString &path, const QByteArray &absPath) + : originalPath(path), absolutePath(absPath) {} + QString originalPath; // The path we need to emit + QByteArray absolutePath; // The path we need to stat. + struct ::stat64 savedInfo; // All the info for the path so we can compare it. +}; +typedef QLinkedList<PathInfo> PathInfoList; +typedef QHash<QString, PathInfoList> PathHash; +#endif + +class QFSEventsFileSystemWatcherEngine : public QFileSystemWatcherEngine +{ + Q_OBJECT +public: + ~QFSEventsFileSystemWatcherEngine(); + + static QFSEventsFileSystemWatcherEngine *create(); + + QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); + QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); + + void stop(); + +private: + QFSEventsFileSystemWatcherEngine(); + void warmUpFSEvents(); + void updateFiles(); + + static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, + void *eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]); + void run(); + FSEventStreamRef fsStream; + CFArrayRef pathsToWatch; + CFRunLoopRef threadsRunLoop; + QMutex mutex; + QWaitCondition waitCondition; + QWaitCondition waitForStop; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + PathHash filePathInfoHash; + PathHash dirPathInfoHash; + void updateHash(PathHash &pathHash); + void updateList(PathInfoList &list, bool directory, bool emitSignals); +#endif +}; + +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 401e545..9d08228 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -44,6 +44,8 @@ #ifndef QT_NO_FILESYSTEMWATCHER +#include "private/qcore_unix_p.h" + #include <qdebug.h> #include <qfile.h> #include <qfileinfo.h> @@ -62,62 +64,80 @@ # define __NR_inotify_init 291 # define __NR_inotify_add_watch 292 # define __NR_inotify_rm_watch 293 +# define __NR_inotify_init1 332 #elif defined(__x86_64__) # define __NR_inotify_init 253 # define __NR_inotify_add_watch 254 # define __NR_inotify_rm_watch 255 +# define __NR_inotify_init1 294 #elif defined(__powerpc__) || defined(__powerpc64__) # define __NR_inotify_init 275 # define __NR_inotify_add_watch 276 # define __NR_inotify_rm_watch 277 +# define __NR_inotify_init1 318 #elif defined (__ia64__) # define __NR_inotify_init 1277 # define __NR_inotify_add_watch 1278 # define __NR_inotify_rm_watch 1279 +# define __NR_inotify_init1 1318 #elif defined (__s390__) || defined (__s390x__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 324 #elif defined (__alpha__) # define __NR_inotify_init 444 # define __NR_inotify_add_watch 445 # define __NR_inotify_rm_watch 446 +// no inotify_init1 for the Alpha #elif defined (__sparc__) || defined (__sparc64__) # define __NR_inotify_init 151 # define __NR_inotify_add_watch 152 # define __NR_inotify_rm_watch 156 +# define __NR_inotify_init1 322 #elif defined (__arm__) # define __NR_inotify_init 316 # define __NR_inotify_add_watch 317 # define __NR_inotify_rm_watch 318 +# define __NR_inotify_init1 360 #elif defined (__sh__) # define __NR_inotify_init 290 # define __NR_inotify_add_watch 291 # define __NR_inotify_rm_watch 292 +# define __NR_inotify_init1 332 #elif defined (__sh64__) # define __NR_inotify_init 318 # define __NR_inotify_add_watch 319 # define __NR_inotify_rm_watch 320 +# define __NR_inotify_init1 360 #elif defined (__mips__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 329 #elif defined (__hppa__) # define __NR_inotify_init 269 # define __NR_inotify_add_watch 270 # define __NR_inotify_rm_watch 271 +# define __NR_inotify_init1 314 #elif defined (__avr32__) # define __NR_inotify_init 240 # define __NR_inotify_add_watch 241 # define __NR_inotify_rm_watch 242 +// no inotify_init1 for AVR32 #elif defined (__mc68000__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 328 #else # error "This architecture is not supported. Please talk to qt-bugs@trolltech.com" #endif +#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1) +# define IN_CLOEXEC O_CLOEXEC +#endif + QT_BEGIN_NAMESPACE #ifdef QT_LINUXBASE @@ -140,6 +160,13 @@ static inline int inotify_rm_watch(int fd, __u32 wd) return syscall(__NR_inotify_rm_watch, fd, wd); } +#ifdef IN_CLOEXEC +static inline int inotify_init1(int flags) +{ + return syscall(__NR_inotify_init1, flags); +} +#endif + // the following struct and values are documented in linux/inotify.h extern "C" { @@ -185,9 +212,16 @@ QT_BEGIN_NAMESPACE QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create() { - int fd = inotify_init(); - if (fd <= 0) - return 0; + register int fd = -1; +#ifdef IN_CLOEXEC + fd = inotify_init1(IN_CLOEXEC); +#endif + if (fd == -1) { + fd = inotify_init(); + if (fd == -1) + return 0; + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + } return new QInotifyFileSystemWatcherEngine(fd); } diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index ed42c34..dfed6a4 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -43,6 +43,7 @@ #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_kqueue_p.h" +#include "private/qcore_unix_p.h" #include <qdebug.h> #include <qfile.h> @@ -124,9 +125,9 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, QString path = it.next(); int fd; #if defined(O_EVTONLY) - fd = ::open(QFile::encodeName(path), O_EVTONLY); + fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); #else - fd = ::open(QFile::encodeName(path), O_RDONLY); + fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); #endif if (fd == -1) { perror("QKqueueFileSystemWatcherEngine::addPaths: open"); diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h index 850e150..83be197 100644 --- a/src/corelib/io/qfilesystemwatcher_p.h +++ b/src/corelib/io/qfilesystemwatcher_p.h @@ -69,13 +69,14 @@ class QFileSystemWatcherEngine : public QThread Q_OBJECT protected: - inline QFileSystemWatcherEngine() + inline QFileSystemWatcherEngine(bool move = true) { - moveToThread(this); + if (move) + moveToThread(this); } public: - // fills \a files and \a directires with the \a paths it could + // fills \a files and \a directories with the \a paths it could // watch, and returns a list of paths this engine could not watch virtual QStringList addPaths(const QStringList &paths, QStringList *files, diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp index c8c1d82..49a5f34 100644 --- a/src/corelib/io/qfilesystemwatcher_symbian.cpp +++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/io/qfilesystemwatcher_symbian_p.h b/src/corelib/io/qfilesystemwatcher_symbian_p.h index 9919114..53b2b13 100644 --- a/src/corelib/io/qfilesystemwatcher_symbian_p.h +++ b/src/corelib/io/qfilesystemwatcher_symbian_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 9a3aeae..9eeef02 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -53,25 +53,268 @@ QT_BEGIN_NAMESPACE +void QWindowsFileSystemWatcherEngine::stop() +{ + foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) + thread->stop(); +} + QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine() - : msg(0) + : QFileSystemWatcherEngine(false) { - HANDLE h = QT_WA_INLINE(CreateEventW(0, false, false, 0), - CreateEventA(0, false, false, 0)); - if (h != INVALID_HANDLE_VALUE) { - handles.reserve(MAXIMUM_WAIT_OBJECTS); - handles.append(h); - } } QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine() { - if (handles.isEmpty()) + if (threads.isEmpty()) return; - stop(); - wait(); + foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) { + thread->stop(); + thread->wait(); + delete thread; + } +} + +QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ + // qDebug()<<"Adding"<<paths.count()<<"to existing"<<(files->count() + directories->count())<<"watchers"; + QStringList p = paths; + QMutableListIterator<QString> it(p); + while (it.hasNext()) { + QString path = it.next(); + QString normalPath = path; + if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) +#ifdef Q_OS_WINCE + && normalPath.size() > 1) +#else + ) +#endif + normalPath.chop(1); + QFileInfo fileInfo(normalPath.toLower()); + if (!fileInfo.exists()) + continue; + + bool isDir = fileInfo.isDir(); + if (isDir) { + if (directories->contains(path)) + continue; + } else { + if (files->contains(path)) + continue; + } + + // qDebug()<<"Looking for a thread/handle for"<<normalPath; + + const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath(); + const uint flags = isDir + ? (FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_FILE_NAME) + : (FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_FILE_NAME + | FILE_NOTIFY_CHANGE_ATTRIBUTES + | FILE_NOTIFY_CHANGE_SIZE + | FILE_NOTIFY_CHANGE_LAST_WRITE + | FILE_NOTIFY_CHANGE_SECURITY); + + QWindowsFileSystemWatcherEngine::PathInfo pathInfo; + pathInfo.absolutePath = absolutePath; + pathInfo.isDir = isDir; + pathInfo.path = path; + pathInfo = fileInfo; + + // Look for a thread + QWindowsFileSystemWatcherEngineThread *thread = 0; + QWindowsFileSystemWatcherEngine::Handle handle; + QList<QWindowsFileSystemWatcherEngineThread *>::const_iterator jt, end; + end = threads.constEnd(); + for(jt = threads.constBegin(); jt != end; ++jt) { + thread = *jt; + QMutexLocker locker(&(thread->mutex)); + + handle = thread->handleForDir.value(absolutePath); + if (handle.handle != INVALID_HANDLE_VALUE && handle.flags == flags) { + // found a thread now insert... + // qDebug()<<" Found a thread"<<thread; + + QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h + = thread->pathInfoForHandle[handle.handle]; + if (!h.contains(fileInfo.absoluteFilePath())) { + thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo); + if (isDir) + directories->append(path); + else + files->append(path); + } + it.remove(); + thread->wakeup(); + break; + } + } + + // no thread found, first create a handle + if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) { + // qDebug()<<" No thread found"; + // Volume and folder paths need a trailing slash for proper notification + // (e.g. "c:" -> "c:/"). + const QString effectiveAbsolutePath = + isDir ? (absolutePath + QLatin1Char('/')) : absolutePath; + + handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags); + handle.flags = flags; + if (handle.handle == INVALID_HANDLE_VALUE) + continue; + + // now look for a thread to insert + bool found = false; + foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) { + QMutexLocker(&(thread->mutex)); + if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) { + // qDebug() << " Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath(); + // qDebug()<< " to existing thread"<<thread; + thread->handles.append(handle.handle); + thread->handleForDir.insert(absolutePath, handle); + + thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo); + if (isDir) + directories->append(path); + else + files->append(path); + + it.remove(); + found = true; + thread->wakeup(); + break; + } + } + if (!found) { + QWindowsFileSystemWatcherEngineThread *thread = new QWindowsFileSystemWatcherEngineThread(); + //qDebug()<<" ###Creating new thread"<<thread<<"("<<(threads.count()+1)<<"threads)"; + thread->handles.append(handle.handle); + thread->handleForDir.insert(absolutePath, handle); + + thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo); + if (isDir) + directories->append(path); + else + files->append(path); + + connect(thread, SIGNAL(fileChanged(const QString &, bool)), + this, SIGNAL(fileChanged(const QString &, bool))); + connect(thread, SIGNAL(directoryChanged(const QString &, bool)), + this, SIGNAL(directoryChanged(const QString &, bool))); + + thread->msg = '@'; + thread->start(); + threads.append(thread); + it.remove(); + } + } + } + return p; +} + +QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ + // qDebug()<<"removePaths"<<paths; + QStringList p = paths; + QMutableListIterator<QString> it(p); + while (it.hasNext()) { + QString path = it.next(); + QString normalPath = path; + if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) + normalPath.chop(1); + QFileInfo fileInfo(normalPath.toLower()); + // qDebug()<<"removing"<<normalPath; + QString absolutePath = fileInfo.absoluteFilePath(); + QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end; + end = threads.end(); + for(jt = threads.begin(); jt!= end; ++jt) { + QWindowsFileSystemWatcherEngineThread *thread = *jt; + if (*jt == 0) + continue; + + QMutexLocker locker(&(thread->mutex)); + + QWindowsFileSystemWatcherEngine::Handle handle = thread->handleForDir.value(absolutePath); + if (handle.handle == INVALID_HANDLE_VALUE) { + // perhaps path is a file? + absolutePath = fileInfo.absolutePath(); + handle = thread->handleForDir.value(absolutePath); + } + if (handle.handle != INVALID_HANDLE_VALUE) { + QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = + thread->pathInfoForHandle[handle.handle]; + if (h.remove(fileInfo.absoluteFilePath())) { + // ### + files->removeAll(path); + directories->removeAll(path); + + if (h.isEmpty()) { + // qDebug() << "Closing handle" << handle.handle; + FindCloseChangeNotification(handle.handle); // This one might generate a notification + + int indexOfHandle = thread->handles.indexOf(handle.handle); + Q_ASSERT(indexOfHandle != -1); + thread->handles.remove(indexOfHandle); + + thread->handleForDir.remove(absolutePath); + // h is now invalid + + it.remove(); + + if (thread->handleForDir.isEmpty()) { + // qDebug()<<"Stopping thread "<<thread; + locker.unlock(); + thread->stop(); + thread->wait(); + locker.relock(); + // We can't delete the thread until the mutex locker is + // out of scope + } + } + } + // Found the file, go to next one + break; + } + } + } + + // Remove all threads that we stopped + QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end; + end = threads.end(); + for(jt = threads.begin(); jt != end; ++jt) { + if (!(*jt)->isRunning()) { + delete *jt; + *jt = 0; + } + } + + threads.removeAll(0); + return p; +} + +/////////// +// QWindowsFileSystemWatcherEngineThread +/////////// +QWindowsFileSystemWatcherEngineThread::QWindowsFileSystemWatcherEngineThread() + : msg(0) +{ + if (HANDLE h = CreateEvent(0, false, false, 0)) { + handles.reserve(MAXIMUM_WAIT_OBJECTS); + handles.append(h); + } + moveToThread(this); +} + + +QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread() +{ CloseHandle(handles.at(0)); handles[0] = INVALID_HANDLE_VALUE; @@ -82,13 +325,13 @@ QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine() } } -void QWindowsFileSystemWatcherEngine::run() +void QWindowsFileSystemWatcherEngineThread::run() { QMutexLocker locker(&mutex); forever { QVector<HANDLE> handlesCopy = handles; locker.unlock(); - // qDebug() << "QWindowsFileSystemWatcherEngine: waiting on" << handlesCopy.count() << "handles"; + // qDebug() << "QWindowsFileSystemWatcherThread"<<this<<"waiting on" << handlesCopy.count() << "handles"; DWORD r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE); locker.relock(); do { @@ -96,7 +339,7 @@ void QWindowsFileSystemWatcherEngine::run() int m = msg; msg = 0; if (m == 'q') { - // qDebug() << "thread told to quit"; + // qDebug() << "thread"<<this<<"told to quit"; return; } if (m != '@') { @@ -111,15 +354,15 @@ void QWindowsFileSystemWatcherEngine::run() // When removing a path, FindCloseChangeNotification might actually fire a notification // for some reason, so we must check if the handle exist in the handles vector if (handles.contains(handle)) { - // qDebug("Acknowledged handle: %d, %p", at, handle); + // qDebug()<<"thread"<<this<<"Acknowledged handle:"<<at<<handle; if (!FindNextChangeNotification(handle)) { - qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed"); + qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed!!"); } - QHash<QString, PathInfo> &h = pathInfoForHandle[handle]; - QMutableHashIterator<QString, PathInfo> it(h); + QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle]; + QMutableHashIterator<QString, QWindowsFileSystemWatcherEngine::PathInfo> it(h); while (it.hasNext()) { - QHash<QString, PathInfo>::iterator x = it.next(); + QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo>::iterator x = it.next(); QString absolutePath = x.value().absolutePath; QFileInfo fileInfo(x.value().path); // qDebug() << "checking" << x.key(); @@ -164,166 +407,14 @@ void QWindowsFileSystemWatcherEngine::run() } } -QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, - QStringList *files, - QStringList *directories) -{ - if (handles.isEmpty() || handles.count() == MAXIMUM_WAIT_OBJECTS) - return paths; - - QMutexLocker locker(&mutex); - - QStringList p = paths; - QMutableListIterator<QString> it(p); - while (it.hasNext()) { - QString path = it.next(); - QString normalPath = path; - if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) -#ifdef Q_OS_WINCE - && normalPath.size() > 1) -#else - ) -#endif - normalPath.chop(1); - QFileInfo fileInfo(normalPath.toLower()); - if (!fileInfo.exists()) - continue; - - bool isDir = fileInfo.isDir(); - if (isDir) { - if (directories->contains(path)) - continue; - } else { - if (files->contains(path)) - continue; - } - - const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath(); - const uint flags = isDir - ? (FILE_NOTIFY_CHANGE_DIR_NAME - | FILE_NOTIFY_CHANGE_FILE_NAME) - : (FILE_NOTIFY_CHANGE_DIR_NAME - | FILE_NOTIFY_CHANGE_FILE_NAME - | FILE_NOTIFY_CHANGE_ATTRIBUTES - | FILE_NOTIFY_CHANGE_SIZE - | FILE_NOTIFY_CHANGE_LAST_WRITE - | FILE_NOTIFY_CHANGE_SECURITY); - - Handle handle = handleForDir.value(absolutePath); - if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) { - // Volume and folder paths need a trailing slash for proper notification - // (e.g. "c:" -> "c:/"). - const QString effectiveAbsolutePath = - isDir ? (absolutePath + QLatin1Char('/')) : absolutePath; - - QT_WA({ - handle.handle = FindFirstChangeNotificationW((TCHAR *) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), - false, flags); - },{ - handle.handle = FindFirstChangeNotificationA(QDir::toNativeSeparators(effectiveAbsolutePath).toLocal8Bit(), - false, flags); - }) - handle.flags = flags; - if (handle.handle == INVALID_HANDLE_VALUE) - continue; - // qDebug() << "Added handle" << handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath(); - handles.append(handle.handle); - handleForDir.insert(absolutePath, handle); - } - - PathInfo pathInfo; - pathInfo.absolutePath = absolutePath; - pathInfo.isDir = isDir; - pathInfo.path = path; - pathInfo = fileInfo; - QHash<QString, PathInfo> &h = pathInfoForHandle[handle.handle]; - if (!h.contains(fileInfo.absoluteFilePath())) { - pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo); - if (isDir) - directories->append(path); - else - files->append(path); - } - - it.remove(); - } - - if (!isRunning()) { - msg = '@'; - start(); - } else { - wakeup(); - } - - return p; -} - -QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths, - QStringList *files, - QStringList *directories) -{ - QMutexLocker locker(&mutex); - - QStringList p = paths; - QMutableListIterator<QString> it(p); - while (it.hasNext()) { - QString path = it.next(); - QString normalPath = path; - if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) - normalPath.chop(1); - QFileInfo fileInfo(normalPath.toLower()); - - QString absolutePath = fileInfo.absoluteFilePath(); - Handle handle = handleForDir.value(absolutePath); - if (handle.handle == INVALID_HANDLE_VALUE) { - // perhaps path is a file? - absolutePath = fileInfo.absolutePath(); - handle = handleForDir.value(absolutePath); - if (handle.handle == INVALID_HANDLE_VALUE) - continue; - } - - QHash<QString, PathInfo> &h = pathInfoForHandle[handle.handle]; - if (h.remove(fileInfo.absoluteFilePath())) { - // ### - files->removeAll(path); - directories->removeAll(path); - - if (h.isEmpty()) { - // qDebug() << "Closing handle" << handle; - FindCloseChangeNotification(handle.handle); // This one might generate a notification - - int indexOfHandle = handles.indexOf(handle.handle); - Q_ASSERT(indexOfHandle != -1); - handles.remove(indexOfHandle); - - handleForDir.remove(absolutePath); - // h is now invalid - - it.remove(); - } - } - } - - if (handleForDir.isEmpty()) { - stop(); - locker.unlock(); - wait(); - locker.relock(); - } else { - wakeup(); - } - - return p; -} -void QWindowsFileSystemWatcherEngine::stop() +void QWindowsFileSystemWatcherEngineThread::stop() { msg = 'q'; SetEvent(handles.at(0)); } -void QWindowsFileSystemWatcherEngine::wakeup() +void QWindowsFileSystemWatcherEngineThread::wakeup() { msg = '@'; SetEvent(handles.at(0)); diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h index d0eecfc..405d255 100644 --- a/src/corelib/io/qfilesystemwatcher_win_p.h +++ b/src/corelib/io/qfilesystemwatcher_win_p.h @@ -57,7 +57,7 @@ #ifndef QT_NO_FILESYSTEMWATCHER -#include <windows.h> +#include <qt_windows.h> #include <QtCore/qdatetime.h> #include <QtCore/qfile.h> @@ -68,27 +68,24 @@ QT_BEGIN_NAMESPACE +class QWindowsFileSystemWatcherEngineThread; + +// Even though QWindowsFileSystemWatcherEngine is derived of QThread +// via QFileSystemWatcher, it does not start a thread. +// Instead QWindowsFileSystemWatcher creates QWindowsFileSystemWatcherEngineThreads +// to do the actually watching. class QWindowsFileSystemWatcherEngine : public QFileSystemWatcherEngine { Q_OBJECT - public: QWindowsFileSystemWatcherEngine(); ~QWindowsFileSystemWatcherEngine(); - void run(); - QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); void stop(); -private: - void wakeup(); - - QMutex mutex; - QVector<HANDLE> handles; - int msg; class Handle { @@ -97,13 +94,12 @@ private: uint flags; Handle() - : handle(INVALID_HANDLE_VALUE), flags(0u) + : handle(INVALID_HANDLE_VALUE), flags(0u) { } Handle(const Handle &other) - : handle(other.handle), flags(other.flags) + : handle(other.handle), flags(other.flags) { } }; - QHash<QString, Handle> handleForDir; class PathInfo { public: @@ -118,7 +114,7 @@ private: QDateTime lastModified; PathInfo &operator=(const QFileInfo &fileInfo) - { + { ownerId = fileInfo.ownerId(); groupId = fileInfo.groupId(); permissions = fileInfo.permissions(); @@ -134,8 +130,35 @@ private: || lastModified != fileInfo.lastModified()); } }; - QHash<HANDLE, QHash<QString, PathInfo> > pathInfoForHandle; +private: + QList<QWindowsFileSystemWatcherEngineThread *> threads; + +}; + +class QWindowsFileSystemWatcherEngineThread : public QThread +{ + Q_OBJECT + +public: + QWindowsFileSystemWatcherEngineThread(); + ~QWindowsFileSystemWatcherEngineThread(); + void run(); + void stop(); + void wakeup(); + + QMutex mutex; + QVector<HANDLE> handles; + int msg; + + QHash<QString, QWindowsFileSystemWatcherEngine::Handle> handleForDir; + + QHash<HANDLE, QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> > pathInfoForHandle; + +Q_SIGNALS: + void fileChanged(const QString &path, bool removed); + void directoryChanged(const QString &path, bool removed); }; + #endif // QT_NO_FILESYSTEMWATCHER QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index e32b818..3a43ec7 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -44,12 +44,16 @@ #include "qdatetime.h" #include "qdiriterator.h" #include "qset.h" +#include <QtCore/qdebug.h> #ifndef QT_NO_FSFILEENGINE #if !defined(Q_OS_WINCE) #include <errno.h> #endif +#if defined(Q_OS_UNIX) +#include "private/qcore_unix_p.h" +#endif #include <stdio.h> QT_BEGIN_NAMESPACE @@ -568,7 +572,7 @@ bool QFSFileEnginePrivate::seekFdFh(qint64 pos) } else { // Unbuffered stdio mode. if (QT_LSEEK(fd, pos, SEEK_SET) == -1) { - qWarning("QFile::at: Cannot set file position %lld", pos); + qWarning() << "QFile::at: Cannot set file position" << pos; q->setError(QFile::PositionError, qt_error_string(errno)); return false; } diff --git a/src/corelib/io/qfsfileengine.h b/src/corelib/io/qfsfileengine.h index 0fd87a4..feca09b 100644 --- a/src/corelib/io/qfsfileengine.h +++ b/src/corelib/io/qfsfileengine.h @@ -56,7 +56,7 @@ class QFSFileEnginePrivate; class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine { - Q_DECLARE_SCOPED_PRIVATE(QFSFileEngine) + Q_DECLARE_PRIVATE(QFSFileEngine) public: QFSFileEngine(); explicit QFSFileEngine(const QString &file); diff --git a/src/corelib/io/qfsfileengine_iterator_win.cpp b/src/corelib/io/qfsfileengine_iterator_win.cpp index 2336542..dd4ddf3 100644 --- a/src/corelib/io/qfsfileengine_iterator_win.cpp +++ b/src/corelib/io/qfsfileengine_iterator_win.cpp @@ -79,11 +79,7 @@ void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName() it->currentEntry = uncShares.at(uncShareIndex - 1); } else { // Local directory - QT_WA({ - it->currentEntry = QString::fromUtf16((unsigned short *)findData.cFileName); - } , { - it->currentEntry = QString::fromLocal8Bit((const char *)findData.cFileName); - }); + it->currentEntry = QString::fromWCharArray(findData.cFileName); } } @@ -97,17 +93,10 @@ void QFSFileEngineIterator::advance() if (platform->uncFallback) { ++platform->uncShareIndex; } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) { - QT_WA({ - if (!FindNextFile(platform->findFileHandle, &platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - } , { - if (!FindNextFileA(platform->findFileHandle, (WIN32_FIND_DATAA *)&platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - }); + if (!FindNextFile(platform->findFileHandle, &platform->findData)) { + platform->done = true; + FindClose(platform->findFileHandle); + } } } @@ -141,15 +130,8 @@ bool QFSFileEngineIterator::hasNext() const path.append(QLatin1Char('/')); path.append(QLatin1String("*.*")); - QT_WA({ - QString fileName = QFSFileEnginePrivate::longFileName(path); - platform->findFileHandle = FindFirstFileW((TCHAR *)fileName.utf16(), - &platform->findData); - }, { - // Cast is safe, since char is at end of WIN32_FIND_DATA - platform->findFileHandle = FindFirstFileA(QFSFileEnginePrivate::win95Name(path), - (WIN32_FIND_DATAA*)&platform->findData); - }); + QString fileName = QFSFileEnginePrivate::longFileName(path); + platform->findFileHandle = FindFirstFile((const wchar_t *)fileName.utf16(), &platform->findData); if (platform->findFileHandle == INVALID_HANDLE_VALUE) { if (path.startsWith(QLatin1String("//"))) { diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 5aef229..864599f 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -72,7 +72,6 @@ class QFSFileEnginePrivate : public QAbstractFileEnginePrivate public: #ifdef Q_WS_WIN - static QByteArray win95Name(const QString &path); static QString longFileName(const QString &path); #endif static QString canonicalized(const QString &path); @@ -151,8 +150,7 @@ public: #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) static void resolveLibs(); - static bool resolveUNCLibs_NT(); - static bool resolveUNCLibs_9x(); + static bool resolveUNCLibs(); static bool uncListSharesOnServer(const QString &server, QStringList *list); #endif diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 2421282..fa2aaf7 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -42,6 +42,7 @@ #include "qplatformdefs.h" #include "qabstractfileengine.h" #include "private/qfsfileengine_p.h" +#include "private/qcore_unix_p.h" #ifndef QT_NO_FSFILEENGINE @@ -110,6 +111,12 @@ static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString & if (flags & QIODevice::ReadOnly) mode += '+'; } + +#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207 + // must be glibc >= 2.7 + mode += 'e'; +#endif + return mode; } @@ -138,12 +145,6 @@ static int openModeToOpenFlags(QIODevice::OpenMode mode) oflags |= QT_OPEN_TRUNC; } -#ifdef O_CLOEXEC - // supported on Linux >= 2.6.23; avoids one extra system call - // and avoids a race condition: if another thread forks, we could - // end up leaking a file descriptor... - oflags |= O_CLOEXEC; -#endif return oflags; } @@ -197,11 +198,6 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) } } -#ifndef O_CLOEXEC - // not needed on Linux >= 2.6.23 - setCloseOnExec(fd); // ignore failure -#endif - // Seek to the end when in Append mode. if (flags & QFile::Append) { int ret; @@ -468,7 +464,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con if (QT_STAT(chunk, &st) != -1) { if ((st.st_mode & S_IFMT) != S_IFDIR) return false; - } else if (::mkdir(chunk, 0777) != 0) { + } else if (QT_MKDIR(chunk, 0777) != 0) { return false; } } @@ -479,7 +475,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con if (dirName[dirName.length() - 1] == QLatin1Char('/')) dirName = dirName.left(dirName.length() - 1); #endif - return (::mkdir(QFile::encodeName(dirName), 0777) == 0); + return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0); } bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const @@ -521,7 +517,7 @@ bool QFSFileEngine::caseSensitive() const bool QFSFileEngine::setCurrentPath(const QString &path) { int r; - r = ::chdir(QFile::encodeName(path)); + r = QT_CHDIR(QFile::encodeName(path)); return r >= 0; } diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 3b2bc60..68eef5f 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -109,9 +109,9 @@ static QString qfsPrivateCurrentDir = QLatin1String(""); QT_BEGIN_INCLUDE_NAMESPACE typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0; -typedef DECLSPEC_IMPORT BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE); +typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE); static PtrLookupAccountSidW ptrLookupAccountSidW = 0; -typedef DECLSPEC_IMPORT BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); +typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); static PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = 0; typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID); static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0; @@ -119,7 +119,7 @@ typedef VOID (WINAPI *PtrBuildTrusteeWithNameW)(PTRUSTEE_W, unsigned short*); static PtrBuildTrusteeWithNameW ptrBuildTrusteeWithNameW = 0; typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK); static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0; -typedef DECLSPEC_IMPORT PVOID (WINAPI *PtrFreeSid)(PSID); +typedef PVOID (WINAPI *PtrFreeSid)(PSID); static PtrFreeSid ptrFreeSid = 0; static TRUSTEE_W currentUserTrusteeW; @@ -152,66 +152,64 @@ void QFSFileEnginePrivate::resolveLibs() triedResolve = true; #if !defined(Q_OS_WINCE) - if(QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) { - HINSTANCE advapiHnd = LoadLibraryW(L"advapi32"); - if (advapiHnd) { - ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); - ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); - ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); - ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); - ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW"); - ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); - ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); - } - if (ptrBuildTrusteeWithNameW) { - HINSTANCE versionHnd = LoadLibraryW(L"version"); - if (versionHnd) { - typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPWSTR lptstrFilename,LPDWORD lpdwHandle); - PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW"); - typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData); - PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW"); - typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen); - PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW"); - if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) { - DWORD fakeHandle; - DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle); - if(versionSize) { - LPVOID versionData; - versionData = malloc(versionSize); - if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) { - UINT puLen; - VS_FIXEDFILEINFO *pLocalInfo; - if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) { - WORD wVer1, wVer2, wVer3, wVer4; - wVer1 = HIWORD(pLocalInfo->dwFileVersionMS); - wVer2 = LOWORD(pLocalInfo->dwFileVersionMS); - wVer3 = HIWORD(pLocalInfo->dwFileVersionLS); - wVer4 = LOWORD(pLocalInfo->dwFileVersionLS); - // It will not work with secur32.dll version 5.0.2195.2862 - if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) { - HINSTANCE userHnd = LoadLibraryW(L"secur32"); - if (userHnd) { - typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize); - PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW"); - if(ptrGetUserNameExW) { - static TCHAR buffer[258]; - DWORD bufferSize = 257; - ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize); - ptrBuildTrusteeWithNameW(¤tUserTrusteeW, (ushort*)buffer); - } - FreeLibrary(userHnd); + HINSTANCE advapiHnd = LoadLibraryW(L"advapi32"); + if (advapiHnd) { + ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); + ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); + ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); + ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); + ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW"); + ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); + ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); + } + if (ptrBuildTrusteeWithNameW) { + HINSTANCE versionHnd = LoadLibraryW(L"version"); + if (versionHnd) { + typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPCWSTR lptstrFilename,LPDWORD lpdwHandle); + PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW"); + typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPCWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData); + PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW"); + typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPCWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen); + PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW"); + if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) { + DWORD fakeHandle; + DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle); + if(versionSize) { + LPVOID versionData; + versionData = malloc(versionSize); + if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) { + UINT puLen; + VS_FIXEDFILEINFO *pLocalInfo; + if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) { + WORD wVer1, wVer2, wVer3, wVer4; + wVer1 = HIWORD(pLocalInfo->dwFileVersionMS); + wVer2 = LOWORD(pLocalInfo->dwFileVersionMS); + wVer3 = HIWORD(pLocalInfo->dwFileVersionLS); + wVer4 = LOWORD(pLocalInfo->dwFileVersionLS); + // It will not work with secur32.dll version 5.0.2195.2862 + if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) { + HINSTANCE userHnd = LoadLibraryW(L"secur32"); + if (userHnd) { + typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize); + PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW"); + if(ptrGetUserNameExW) { + static wchar_t buffer[258]; + DWORD bufferSize = 257; + ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize); + ptrBuildTrusteeWithNameW(¤tUserTrusteeW, (ushort*)buffer); } + FreeLibrary(userHnd); } } } - free(versionData); } + free(versionData); } - FreeLibrary(versionHnd); } + FreeLibrary(versionHnd); } ptrOpenProcessToken = (PtrOpenProcessToken)GetProcAddress(advapiHnd, "OpenProcessToken"); - HINSTANCE userenvHnd = LoadLibraryW(L"userenv"); + HINSTANCE userenvHnd = LoadLibraryW(L"userenv"); if (userenvHnd) { ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); } @@ -225,120 +223,60 @@ void QFSFileEnginePrivate::resolveLibs() #endif // QT_NO_LIBRARY // UNC functions NT -typedef DWORD (WINAPI *PtrNetShareEnum_NT)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); -static PtrNetShareEnum_NT ptrNetShareEnum_NT = 0; -typedef DWORD (WINAPI *PtrNetApiBufferFree_NT)(LPVOID); -static PtrNetApiBufferFree_NT ptrNetApiBufferFree_NT = 0; -typedef struct _SHARE_INFO_1_NT { +typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); +static PtrNetShareEnum ptrNetShareEnum = 0; +typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID); +static PtrNetApiBufferFree ptrNetApiBufferFree = 0; +typedef struct _SHARE_INFO_1 { LPWSTR shi1_netname; DWORD shi1_type; LPWSTR shi1_remark; -} SHARE_INFO_1_NT; +} SHARE_INFO_1; -bool QFSFileEnginePrivate::resolveUNCLibs_NT() +bool QFSFileEnginePrivate::resolveUNCLibs() { static bool triedResolve = false; if (!triedResolve) { #ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); if (triedResolve) { - return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT; + return ptrNetShareEnum && ptrNetApiBufferFree; } #endif triedResolve = true; #if !defined(Q_OS_WINCE) HINSTANCE hLib = LoadLibraryW(L"Netapi32"); if (hLib) { - ptrNetShareEnum_NT = (PtrNetShareEnum_NT)GetProcAddress(hLib, "NetShareEnum"); - if (ptrNetShareEnum_NT) - ptrNetApiBufferFree_NT = (PtrNetApiBufferFree_NT)GetProcAddress(hLib, "NetApiBufferFree"); - } -#endif - } - return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT; -} - -// UNC functions 9x -typedef DWORD (WINAPI *PtrNetShareEnum_9x)(const char FAR *, short, char FAR *, unsigned short, unsigned short FAR *, unsigned short FAR *); -static PtrNetShareEnum_9x ptrNetShareEnum_9x = 0; -#ifdef LM20_NNLEN -# define LM20_NNLEN_9x LM20_NNLEN -#else -# define LM20_NNLEN_9x 12 -#endif -typedef struct _SHARE_INFO_1_9x { - char shi1_netname[LM20_NNLEN_9x+1]; - char shi1_pad1; - unsigned short shi1_type; - char FAR* shi1_remark; -} SHARE_INFO_1_9x; - -bool QFSFileEnginePrivate::resolveUNCLibs_9x() -{ - static bool triedResolve = false; - if (!triedResolve) { -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - if (triedResolve) { - return ptrNetShareEnum_9x; + ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); + if (ptrNetShareEnum) + ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); } #endif - triedResolve = true; -#if !defined(Q_OS_WINCE) - HINSTANCE hLib = LoadLibraryA("Svrapi"); - if (hLib) - ptrNetShareEnum_9x = (PtrNetShareEnum_9x)GetProcAddress(hLib, "NetShareEnum"); -#endif } - return ptrNetShareEnum_9x; + return ptrNetShareEnum && ptrNetApiBufferFree; } bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringList *list) { - if (resolveUNCLibs_NT()) { - SHARE_INFO_1_NT *BufPtr, *p; + if (resolveUNCLibs()) { + SHARE_INFO_1 *BufPtr, *p; DWORD res; DWORD er=0,tr=0,resume=0, i; do { - res = ptrNetShareEnum_NT((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); + res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { p=BufPtr; for (i = 1; i <= er; ++i) { if (list && p->shi1_type == 0) - list->append(QString::fromUtf16((unsigned short *)p->shi1_netname)); + list->append(QString::fromWCharArray(p->shi1_netname)); p++; } } - ptrNetApiBufferFree_NT(BufPtr); + ptrNetApiBufferFree(BufPtr); } while (res==ERROR_MORE_DATA); return res == ERROR_SUCCESS; - } else if (resolveUNCLibs_9x()) { - SHARE_INFO_1_9x *pBuf = 0; - short cbBuffer; - unsigned short nEntriesRead = 0; - unsigned short nTotalEntries = 0; - short numBuffs = 20; - DWORD nStatus = 0; - do { - cbBuffer = numBuffs * sizeof(SHARE_INFO_1_9x); - pBuf = (SHARE_INFO_1_9x *)malloc(cbBuffer); - if (pBuf) { - nStatus = ptrNetShareEnum_9x(server.toLocal8Bit().constData(), 1, (char FAR *)pBuf, cbBuffer, &nEntriesRead, &nTotalEntries); - if ((nStatus == ERROR_SUCCESS)) { - for (int i = 0; i < nEntriesRead; ++i) { - if (list && pBuf[i].shi1_type == 0) - list->append(QString::fromLocal8Bit(pBuf[i].shi1_netname)); - } - free(pBuf); - break; - } - free(pBuf); - numBuffs *=2; - } - } while (nStatus == ERROR_MORE_DATA); - return nStatus == ERROR_SUCCESS; } return false; } @@ -399,39 +337,19 @@ static bool uncShareExists(const QString &server) return false; } -#if !defined(Q_OS_WINCE) -// If you change this function, remember to also change the UNICODE version -static QString nativeAbsoluteFilePathA(const QString &path) -{ - QString ret; - QVarLengthArray<char, MAX_PATH> buf(MAX_PATH); - char *fileName = 0; - QByteArray ba = path.toLocal8Bit(); - DWORD retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName); - if (retLen > (DWORD)buf.size()) { - buf.resize(retLen); - retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName); - } - if (retLen != 0) - ret = QString::fromLocal8Bit(buf.data(), retLen); - return ret; -} -#endif - -// If you change this function, remember to also change the NON-UNICODE version -static QString nativeAbsoluteFilePathW(const QString &path) +static QString nativeAbsoluteFilePathCore(const QString &path) { QString ret; #if !defined(Q_OS_WINCE) QVarLengthArray<wchar_t, MAX_PATH> buf(MAX_PATH); wchar_t *fileName = 0; - DWORD retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); if (retLen > (DWORD)buf.size()) { buf.resize(retLen); - retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); } if (retLen != 0) - ret = QString::fromUtf16((unsigned short *)buf.data(), retLen); + ret = QString::fromWCharArray(buf.data(), retLen); #else if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) ret = QDir::toNativeSeparators(path); @@ -443,7 +361,7 @@ static QString nativeAbsoluteFilePathW(const QString &path) static QString nativeAbsoluteFilePath(const QString &path) { - QString absPath = QT_WA_INLINE(nativeAbsoluteFilePathW(path), nativeAbsoluteFilePathA(path)); + QString absPath = nativeAbsoluteFilePathCore(path); // This is really ugly, but GetFullPathName strips off whitespace at the end. // If you for instance write ". " in the lineedit of QFileDialog, // (which is an invalid filename) this function will strip the space off and viola, @@ -461,26 +379,6 @@ static QString nativeAbsoluteFilePath(const QString &path) return absPath; } -QByteArray QFSFileEnginePrivate::win95Name(const QString &path) -{ - QString ret(path); - if(path.length() > 1 && path[0] == QLatin1Char('/') && path[1] == QLatin1Char('/')) { - // Win95 cannot handle slash-slash needs slosh-slosh. - ret[0] = QLatin1Char('\\'); - ret[1] = QLatin1Char('\\'); - int n = ret.indexOf(QLatin1Char('/')); - if(n >= 0) - ret[n] = QLatin1Char('\\'); - } else if(path.length() > 3 && path[2] == QLatin1Char('/') && path[3] == QLatin1Char('/')) { - ret[2] = QLatin1Char('\\'); - ret.remove(3, 1); - int n = ret.indexOf(QLatin1Char('/')); - if(n >= 0) - ret[n] = QLatin1Char('\\'); - } - return ret.toLocal8Bit(); -} - /*! \internal */ @@ -507,13 +405,8 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) */ void QFSFileEnginePrivate::nativeInitFileName() { - QT_WA({ - QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath))); - nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1); - }, { - QString path = fixIfRelativeUncPath(filePath); - nativeFilePath = win95Name(path).replace('/', '\\'); - }); + QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath))); + nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1); } /* @@ -539,23 +432,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. - QT_WA({ - fileHandle = CreateFileW((TCHAR *)nativeFilePath.constData(), - accessRights, - shareMode, - &securityAtts, - creationDisp, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - fileHandle = CreateFileA(nativeFilePath.constData(), - accessRights, - shareMode, - &securityAtts, - creationDisp, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + fileHandle = CreateFile((const wchar_t*)nativeFilePath.constData(), + accessRights, + shareMode, + &securityAtts, + creationDisp, + FILE_ATTRIBUTE_NORMAL, + NULL); // Bail out on error. if (fileHandle == INVALID_HANDLE_VALUE) { @@ -641,15 +524,31 @@ qint64 QFSFileEnginePrivate::nativeSize() const // Not-open mode, where the file name is known: We'll check the // file system directly. if (openMode == QIODevice::NotOpen && !nativeFilePath.isEmpty()) { - bool ok = false; WIN32_FILE_ATTRIBUTE_DATA attribData; - QT_WA({ - ok = ::GetFileAttributesExW((TCHAR *)nativeFilePath.constData(), + bool ok = ::GetFileAttributesEx((const wchar_t*)nativeFilePath.constData(), GetFileExInfoStandard, &attribData); - } , { - ok = ::GetFileAttributesExA(nativeFilePath.constData(), - GetFileExInfoStandard, &attribData); - }); + if (!ok) { + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + QByteArray path = nativeFilePath; + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith('\\')) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(':')) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((const wchar_t*)path.constData(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + ok = true; + attribData.nFileSizeHigh = findData.nFileSizeHigh; + attribData.nFileSizeLow = findData.nFileSizeLow; + } + } + } + } if (ok) { qint64 size = attribData.nFileSizeHigh; size <<= 32; @@ -711,28 +610,28 @@ qint64 QFSFileEnginePrivate::nativePos() const if (fileHandle == INVALID_HANDLE_VALUE) return 0; -#if !defined(QT_NO_LIBRARY) +#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE) QFSFileEnginePrivate::resolveLibs(); if (!ptrSetFilePointerEx) { #endif - DWORD newFilePointer = SetFilePointer(fileHandle, 0, NULL, FILE_CURRENT); - if (newFilePointer == 0xFFFFFFFF) { + LARGE_INTEGER filepos; + filepos.HighPart = 0; + DWORD newFilePointer = SetFilePointer(fileHandle, 0, &filepos.HighPart, FILE_CURRENT); + if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) { thatQ->setError(QFile::UnspecifiedError, qt_error_string()); return 0; } - // Note: returns <4GB; does not work with large files. This is the - // case for MOC, UIC, qmake and other bootstrapped tools, and for - // Win9x/ME. - return qint64(newFilePointer); -#if !defined(QT_NO_LIBRARY) + // Note: This is the case for MOC, UIC, qmake and other + // bootstrapped tools, and for Windows CE. + filepos.LowPart = newFilePointer; + return filepos.QuadPart; +#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE) } - // This approach supports large files. LARGE_INTEGER currentFilePos; LARGE_INTEGER offset; - offset.LowPart = 0; - offset.HighPart = 0; + offset.QuadPart = 0; if (!ptrSetFilePointerEx(fileHandle, offset, ¤tFilePos, FILE_CURRENT)) { thatQ->setError(QFile::UnspecifiedError, qt_error_string()); return 0; @@ -755,28 +654,27 @@ bool QFSFileEnginePrivate::nativeSeek(qint64 pos) return seekFdFh(pos); } -#if !defined(QT_NO_LIBRARY) +#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE) QFSFileEnginePrivate::resolveLibs(); if (!ptrSetFilePointerEx) { #endif - LONG seekToPos = LONG(pos); // <- lossy - DWORD newFilePointer = SetFilePointer(fileHandle, seekToPos, NULL, FILE_BEGIN); - if (newFilePointer == 0xFFFFFFFF) { - thatQ->setError(QFile::UnspecifiedError, qt_error_string()); + DWORD newFilePointer; + LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER*>(&pos); + newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN); + if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) { + thatQ->setError(QFile::PositionError, qt_error_string()); return false; } - // Note: does not work with large files. This is the case for MOC, - // UIC, qmake and other bootstrapped tools, and for Win9x/ME. + // Note: This is the case for MOC, UIC, qmake and other + // bootstrapped tools, and for Windows CE. return true; -#if !defined(QT_NO_LIBRARY) +#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE) } - // This approach supports large files. LARGE_INTEGER currentFilePos; LARGE_INTEGER offset; - offset.LowPart = (unsigned int)(quint64(pos) & Q_UINT64_C(0xffffffff)); - offset.HighPart = (unsigned int)((quint64(pos) >> 32) & Q_UINT64_C(0xffffffff)); + offset.QuadPart = pos; if (ptrSetFilePointerEx(fileHandle, offset, ¤tFilePos, FILE_BEGIN) == 0) { thatQ->setError(QFile::UnspecifiedError, qt_error_string()); return false; @@ -949,35 +847,21 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - QT_WA({ - return ::DeleteFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; - } , { - return ::DeleteFileA(QFSFileEnginePrivate::win95Name(d->filePath)) != 0; - }); + return ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; } bool QFSFileEngine::copy(const QString ©Name) { Q_D(QFSFileEngine); - QT_WA({ - return ::CopyFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (TCHAR*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; - } , { - return ::CopyFileA(QFSFileEnginePrivate::win95Name(d->filePath), - QFSFileEnginePrivate::win95Name(copyName), true) != 0; - }); + return ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - QT_WA({ - return ::MoveFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (TCHAR*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; - } , { - return ::MoveFileA(QFSFileEnginePrivate::win95Name(d->filePath), - QFSFileEnginePrivate::win95Name(newName)) != 0; - }); + return ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; } static inline bool mkDir(const QString &path) @@ -1001,20 +885,12 @@ static inline bool mkDir(const QString &path) if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256) return false; #endif - QT_WA({ - return ::CreateDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); - } , { - return ::CreateDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath()), 0); - }); + return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); } static inline bool rmDir(const QString &path) { - QT_WA({ - return ::RemoveDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16()); - } , { - return ::RemoveDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath())); - }); + return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); } static inline bool isDirPath(const QString &dirPath, bool *existed) @@ -1023,12 +899,26 @@ static inline bool isDirPath(const QString &dirPath, bool *existed) if (path.length() == 2 &&path.at(1) == QLatin1Char(':')) path += QLatin1Char('\\'); - DWORD fileAttrib = INVALID_FILE_ATTRIBUTES; - QT_WA({ - fileAttrib = ::GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16()); - } , { - fileAttrib = ::GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath())); - }); + DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); + if (fileAttrib == INVALID_FILE_ATTRIBUTES) { + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + fileAttrib = findData.dwFileAttributes; + } + } + } + } if (existed) *existed = fileAttrib != INVALID_FILE_ATTRIBUTES; @@ -1110,16 +1000,10 @@ bool QFSFileEngine::setCurrentPath(const QString &path) return false; #if !defined(Q_OS_WINCE) - int r; - QT_WA({ - r = ::SetCurrentDirectoryW((WCHAR*)path.utf16()); - } , { - r = ::SetCurrentDirectoryA(QFSFileEnginePrivate::win95Name(path)); - }); - return r != 0; + return ::SetCurrentDirectory((wchar_t*)path.utf16()) != 0; #else - qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path); - return true; + qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path); + return true; #endif } @@ -1132,48 +1016,34 @@ QString QFSFileEngine::currentPath(const QString &fileName) fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':')) { int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1; if (_getdrive() != drv) { - QT_WA({ - TCHAR buf[PATH_MAX]; - ::_wgetdcwd(drv, buf, PATH_MAX); - ret.setUtf16((ushort*)buf, uint(::wcslen(buf))); - }, { - char buf[PATH_MAX]; - ::_getdcwd(drv, buf, PATH_MAX); - ret = QString::fromLatin1(buf); - }); + wchar_t buf[PATH_MAX]; + ::_wgetdcwd(drv, buf, PATH_MAX); + ret = QString::fromWCharArray(buf); } } if (ret.isEmpty()) { //just the pwd - QT_WA({ - DWORD size = 0; - WCHAR currentName[PATH_MAX]; - size = ::GetCurrentDirectoryW(PATH_MAX, currentName); - if (size !=0) { - if (size > PATH_MAX) { - WCHAR * newCurrentName = new WCHAR[size]; - if (::GetCurrentDirectoryW(PATH_MAX, newCurrentName) != 0) - ret = QString::fromUtf16((ushort*)newCurrentName); - delete [] newCurrentName; - } else { - ret = QString::fromUtf16((ushort*)currentName); - } + DWORD size = 0; + wchar_t currentName[PATH_MAX]; + size = ::GetCurrentDirectory(PATH_MAX, currentName); + if (size != 0) { + if (size > PATH_MAX) { + wchar_t *newCurrentName = new wchar_t[size]; + if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0) + ret = QString::fromWCharArray(newCurrentName); + delete [] newCurrentName; + } else { + ret = QString::fromWCharArray(currentName); } - } , { - DWORD size = 0; - char currentName[PATH_MAX]; - size = ::GetCurrentDirectoryA(PATH_MAX, currentName); - if (size !=0) - ret = QString::fromLocal8Bit(currentName); - }); + } } if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return QDir::fromNativeSeparators(ret); #else - Q_UNUSED(fileName); - if (qfsPrivateCurrentDir.isEmpty()) - qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); + Q_UNUSED(fileName); + if (qfsPrivateCurrentDir.isEmpty()) + qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); return QDir::fromNativeSeparators(qfsPrivateCurrentDir); #endif @@ -1183,35 +1053,27 @@ QString QFSFileEngine::homePath() { QString ret; #if !defined(QT_NO_LIBRARY) - QT_WA ( - { - QFSFileEnginePrivate::resolveLibs(); - if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) { - HANDLE hnd = ::GetCurrentProcess(); - HANDLE token = 0; - BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token); - if (ok) { - DWORD dwBufferSize = 0; - // First call, to determine size of the strings (with '\0'). - ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); - if (!ok && dwBufferSize != 0) { // We got the required buffer size - wchar_t *userDirectory = new wchar_t[dwBufferSize]; - // Second call, now we can fill the allocated buffer. - ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); - if (ok) - ret = QString::fromUtf16((ushort*)userDirectory); - - delete [] userDirectory; - } - ::CloseHandle(token); - } - } - } - , - { - // GetUserProfileDirectory is only available from NT 4.0, - // so fall through for Win98 and friends version. - }) + QFSFileEnginePrivate::resolveLibs(); + if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) { + HANDLE hnd = ::GetCurrentProcess(); + HANDLE token = 0; + BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token); + if (ok) { + DWORD dwBufferSize = 0; + // First call, to determine size of the strings (with '\0'). + ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); + if (!ok && dwBufferSize != 0) { // We got the required buffer size + wchar_t *userDirectory = new wchar_t[dwBufferSize]; + // Second call, now we can fill the allocated buffer. + ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); + if (ok) + ret = QString::fromWCharArray(userDirectory); + + delete [] userDirectory; + } + ::CloseHandle(token); + } + } #endif if(ret.isEmpty() || !QFile::exists(ret)) { ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData()); @@ -1251,17 +1113,10 @@ QString QFSFileEngine::rootPath() QString QFSFileEngine::tempPath() { - QString ret; - int success; - QT_WA({ - wchar_t tempPath[MAX_PATH]; - success = GetTempPathW(MAX_PATH, tempPath); - ret = QString::fromUtf16((ushort*)tempPath); - } , { - char tempPath[MAX_PATH]; - success = GetTempPathA(MAX_PATH, tempPath); - ret = QString::fromLocal8Bit(tempPath); - }); + wchar_t tempPath[MAX_PATH]; + int success = GetTempPath(MAX_PATH, tempPath); + QString ret = QString::fromWCharArray(tempPath); + if (ret.isEmpty() || !success) { #if !defined(Q_OS_WINCE) ret = QString::fromLatin1("c:/tmp"); @@ -1285,7 +1140,7 @@ QFileInfoList QFSFileEngine::drives() #elif defined(Q_OS_OS2EMX) quint32 driveBits, cur; if(DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR) - exit(1); + exit(1); driveBits &= 0x3ffffff; #endif char driveName[] = "A:/"; @@ -1327,18 +1182,34 @@ bool QFSFileEnginePrivate::doStat() const } } #else - DWORD tmpAttributes = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16()); + DWORD tmpAttributes = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); if (tmpAttributes != -1) { fileAttrib = tmpAttributes; could_stat = true; } #endif } else { - QT_WA({ - fileAttrib = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16()); - } , { - fileAttrib = GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(fname).absoluteFilePath())); - }); + fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); + if (fileAttrib == INVALID_FILE_ATTRIBUTES) { + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + QString path = QDir::toNativeSeparators(fname); + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + fileAttrib = findData.dwFileAttributes; + } + } + } + } could_stat = fileAttrib != INVALID_FILE_ATTRIBUTES; if (!could_stat) { #if !defined(Q_OS_WINCE) @@ -1398,74 +1269,39 @@ static QString readLink(const QString &link) #if !defined(Q_OS_WINCE) #if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS) QString ret; - QT_WA({ - bool neededCoInit = false; - IShellLink *psl; // pointer to IShellLink i/f - HRESULT hres; - WIN32_FIND_DATA wfd; - TCHAR szGotPath[MAX_PATH]; - // Get pointer to the IShellLink interface. - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&psl); - } - if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if(SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) - ret = QString::fromUtf16((ushort*)szGotPath); - } - ppf->Release(); - } - psl->Release(); - } - if(neededCoInit) - CoUninitialize(); - } , { - bool neededCoInit = false; - IShellLinkA *psl; // pointer to IShellLink i/f - HRESULT hres; - WIN32_FIND_DATAA wfd; - char szGotPath[MAX_PATH]; - // Get pointer to the IShellLink interface. + bool neededCoInit = false; + IShellLink *psl; // pointer to IShellLink i/f + WIN32_FIND_DATA wfd; + wchar_t szGotPath[MAX_PATH]; - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLinkA, (LPVOID *)&psl); + // Get pointer to the IShellLink interface. + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLinkA, (LPVOID *)&psl); - } - if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if(SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)QFileInfo(link).absoluteFilePath().utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - if (psl->GetPath((char*)szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) - ret = QString::fromLocal8Bit(szGotPath); - } - ppf->Release(); + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID *)&psl); + } + if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); + if(SUCCEEDED(hres)) { + hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ); + //The original path of the link is retrieved. If the file/folder + //was moved, the return value still have the old path. + if(SUCCEEDED(hres)) { + if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) + ret = QString::fromWCharArray(szGotPath); } - psl->Release(); + ppf->Release(); } - if(neededCoInit) - CoUninitialize(); - }); + psl->Release(); + } + if (neededCoInit) + CoUninitialize(); + return ret; #else Q_UNUSED(link); @@ -1475,7 +1311,7 @@ static QString readLink(const QString &link) wchar_t target[MAX_PATH]; QString result; if (SHGetShortcutTarget((wchar_t*)QFileInfo(link).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) { - result = QString::fromUtf16(reinterpret_cast<const ushort *> (target)); + result = QString::fromWCharArray(target); if (result.startsWith(QLatin1Char('"'))) result.remove(0,1); if (result.endsWith(QLatin1Char('"'))) @@ -1502,76 +1338,37 @@ bool QFSFileEngine::link(const QString &newName) QString linkName = newName; //### assume that they add .lnk - QT_WA({ - HRESULT hres; - IShellLink *psl; - bool neededCoInit = false; + IShellLink *psl; + bool neededCoInit = false; - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } - if (SUCCEEDED(hres)) { - hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); - if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); - if (SUCCEEDED(hres)) { - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Save((TCHAR*)linkName.utf16(), TRUE); - if (SUCCEEDED(hres)) - ret = true; - ppf->Release(); - } - } - } - psl->Release(); - } - if(neededCoInit) - CoUninitialize(); - } , { - // the SetPath() call _sometimes_ changes the current path and when it does it sometimes - // does not let us change it back unless we call currentPath() many times. - QString cwd = currentPath(); - HRESULT hres; - IShellLinkA *psl; - bool neededCoInit = false; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } + } + + if (SUCCEEDED(hres)) { + hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { - currentPath(); - hres = psl->SetPath((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsoluteName))).utf16()); - currentPath(); + hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsolutePathName))).utf16()); - currentPath(); + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); if (SUCCEEDED(hres)) { - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); - if (SUCCEEDED(hres)) { - currentPath(); - hres = ppf->Save((LPCOLESTR)linkName.utf16(), TRUE); - currentPath(); - if (SUCCEEDED(hres)) - ret = true; - ppf->Release(); - } + hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE); + if (SUCCEEDED(hres)) + ret = true; + ppf->Release(); } - psl->Release(); } } - if(neededCoInit) + psl->Release(); + } + if(neededCoInit) CoUninitialize(); - setCurrentPath(cwd); - }); + return ret; #else Q_UNUSED(newName); @@ -1598,9 +1395,9 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const #if !defined(QT_NO_LIBRARY) if((qt_ntfs_permission_lookup > 0) && ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_NT)) { - PSID pOwner = 0; - PSID pGroup = 0; - PACL pDacl; + PSID pOwner = 0; + PSID pGroup = 0; + PACL pDacl; PSECURITY_DESCRIPTOR pSD; ACCESS_MASK access_mask; @@ -1610,42 +1407,42 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - &pOwner, &pGroup, &pDacl, 0, &pSD); + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &pOwner, &pGroup, &pDacl, 0, &pSD); if(res == ERROR_SUCCESS) { TRUSTEE_W trustee; { //user if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadUserPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteUserPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeUserPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadUserPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteUserPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeUserPerm; } { //owner ptrBuildTrusteeWithSidW(&trustee, pOwner); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOwnerPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOwnerPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOwnerPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadOwnerPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteOwnerPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeOwnerPerm; } { //group ptrBuildTrusteeWithSidW(&trustee, pGroup); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadGroupPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteGroupPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeGroupPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadGroupPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteGroupPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeGroupPerm; } { //other (world) // Create SID for Everyone (World) @@ -1655,12 +1452,12 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const ptrBuildTrusteeWithSidW(&trustee, pWorld); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; // ### - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOtherPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOtherPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOtherPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadOtherPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteOtherPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeOtherPerm; } ptrFreeSid(pWorld); } @@ -1670,13 +1467,13 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const } else #endif { - //### what to do with permissions if we don't use ntfs or are not on a NT system - // for now just add all permissions and what about exe missions ?? - // also qt_ntfs_permission_lookup is now not set by defualt ... should it ? - ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm - | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm - | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm - | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm; + //### what to do with permissions if we don't use NTFS + // for now just add all permissions and what about exe missions ?? + // also qt_ntfs_permission_lookup is now not set by defualt ... should it ? + ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm + | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm + | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm + | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm; } if (doStat()) { @@ -1783,8 +1580,8 @@ QString QFSFileEngine::fileName(FileName file) const if (!isRelativePath()) { #if !defined(Q_OS_WINCE) - if (d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') - && d->filePath.at(2) != QLatin1Char('/') || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt + if ((d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') + && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt d->filePath.startsWith(QLatin1Char('/')) // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt ) { ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath)); @@ -1911,13 +1708,9 @@ bool QFSFileEngine::setPermissions(uint perms) return false; #if !defined(Q_OS_WINCE) - QT_WA({ - ret = ::_wchmod((TCHAR*)d->filePath.utf16(), mode) == 0; - } , { - ret = ::_chmod(d->filePath.toLocal8Bit(), mode) == 0; - }); + ret = ::_wchmod((wchar_t*)d->filePath.utf16(), mode) == 0; #else - ret = ::_wchmod((TCHAR*)d->longFileName(d->filePath).utf16(), mode); + ret = ::_wchmod((wchar_t*)d->longFileName(d->filePath).utf16(), mode); #endif return ret; } @@ -1960,34 +1753,33 @@ bool QFSFileEngine::setSize(qint64 size) static inline QDateTime fileTimeToQDateTime(const FILETIME *time) { QDateTime ret; - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) { - // SystemTimeToTzSpecificLocalTime is not available on Win98/ME so we have to pull it off ourselves. - SYSTEMTIME systime; - FILETIME ftime; - systime.wYear = 1970; - systime.wMonth = 1; - systime.wDay = 1; - systime.wHour = 0; - systime.wMinute = 0; - systime.wSecond = 0; - systime.wMilliseconds = 0; - systime.wDayOfWeek = 4; - SystemTimeToFileTime(&systime, &ftime); - unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; - FileTimeToSystemTime(time, &systime); - unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; - unsigned __int64 difftime = acttime - time1970; - difftime /= 10000000; - ret.setTime_t((unsigned int)difftime); - } else { -#ifndef Q_OS_WINCE - SYSTEMTIME sTime, lTime; - FileTimeToSystemTime(time, &sTime); - SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); - ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); - ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); + +#if defined(Q_OS_WINCE) + SYSTEMTIME systime; + FILETIME ftime; + systime.wYear = 1970; + systime.wMonth = 1; + systime.wDay = 1; + systime.wHour = 0; + systime.wMinute = 0; + systime.wSecond = 0; + systime.wMilliseconds = 0; + systime.wDayOfWeek = 4; + SystemTimeToFileTime(&systime, &ftime); + unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; + FileTimeToSystemTime(time, &systime); + unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; + unsigned __int64 difftime = acttime - time1970; + difftime /= 10000000; + ret.setTime_t((unsigned int)difftime); +#else + SYSTEMTIME sTime, lTime; + FileTimeToSystemTime(time, &sTime); + SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); + ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); + ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); #endif - } + return ret; } @@ -2011,13 +1803,31 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const } #endif } else { - bool ok = false; WIN32_FILE_ATTRIBUTE_DATA attribData; - QT_WA({ - ok = ::GetFileAttributesExW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); - } , { - ok = ::GetFileAttributesExA(QFSFileEnginePrivate::win95Name(QFileInfo(d->filePath).absoluteFilePath()), GetFileExInfoStandard, &attribData); - }); + bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); + if (!ok) { + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + QString path = QDir::toNativeSeparators(d->filePath); + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + ok = true; + attribData.ftCreationTime = findData.ftCreationTime; + attribData.ftLastWriteTime = findData.ftLastWriteTime; + attribData.ftLastAccessTime = findData.ftLastAccessTime; + } + } + } + } if (ok) { if(time == CreationTime) ret = fileTimeToQDateTime(&attribData.ftCreationTime); @@ -2037,11 +1847,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, Q_UNUSED(flags); if (openMode == QFile::NotOpen) { q->setError(QFile::PermissionsError, qt_error_string()); - return 0; + return 0; } if (offset == 0 && size == 0) { q->setError(QFile::UnspecifiedError, qt_error_string()); - return 0; + return 0; } @@ -2054,7 +1864,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, #ifdef Q_USE_DEPRECATED_MAP_API nativeClose(); if (fileMapHandle == INVALID_HANDLE_VALUE) { - fileMapHandle = CreateFileForMappingW((TCHAR *)nativeFilePath.constData(), + fileMapHandle = CreateFileForMapping((const wchar_t*)nativeFilePath.constData(), GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0), 0, NULL, @@ -2069,21 +1879,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, #endif // first create the file mapping handle - HANDLE mapHandle = 0; DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; - QT_WA({ - mapHandle = ::CreateFileMappingW(handle, 0, protection, - 0, 0, 0); - },{ - mapHandle = ::CreateFileMappingA(handle, 0, protection, - 0, 0, 0); - }); + HANDLE mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); if (mapHandle == NULL) { q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API mapHandleClose(); #endif - return 0; + return 0; } // setup args to map @@ -2112,7 +1915,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, switch(GetLastError()) { case ERROR_ACCESS_DENIED: q->setError(QFile::PermissionsError, qt_error_string()); - break; + break; case ERROR_INVALID_PARAMETER: // size are out of bounds default: diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h index d8237a7..866fa72 100644 --- a/src/corelib/io/qiodevice.h +++ b/src/corelib/io/qiodevice.h @@ -165,7 +165,7 @@ protected: #endif private: - Q_DECLARE_SCOPED_PRIVATE(QIODevice) + Q_DECLARE_PRIVATE(QIODevice) Q_DISABLE_COPY(QIODevice) #ifdef QT3_SUPPORT diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 03ae1fe..871ea63 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -310,7 +310,7 @@ void QProcessPrivate::Channel::clear() writes to its standard output and standard error will be written to the standard output and standard error of the main process. - \sa setReadChannelMode() + \sa setProcessChannelMode() */ /*! @@ -878,7 +878,7 @@ void QProcess::setReadChannelMode(ProcessChannelMode mode) Returns the channel mode of the QProcess standard output and standard error channels. - \sa setReadChannelMode(), ProcessChannelMode, setReadChannel() + \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel() */ QProcess::ProcessChannelMode QProcess::processChannelMode() const { @@ -895,7 +895,7 @@ QProcess::ProcessChannelMode QProcess::processChannelMode() const \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0 - \sa readChannelMode(), ProcessChannelMode, setReadChannel() + \sa processChannelMode(), ProcessChannelMode, setReadChannel() */ void QProcess::setProcessChannelMode(ProcessChannelMode mode) { diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index a4025a1..bff5f7e 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -191,7 +191,7 @@ protected: qint64 writeData(const char *data, qint64 len); private: - Q_DECLARE_SCOPED_PRIVATE(QProcess) + Q_DECLARE_PRIVATE(QProcess) Q_DISABLE_COPY(QProcess) Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput()) diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 7da6a1d..64519f6 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 49869a4..607b734 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -84,6 +84,7 @@ QT_END_NAMESPACE #include "qprocess.h" #include "qprocess_p.h" +#include "private/qcore_unix_p.h" #ifdef Q_OS_MAC #include <private/qcore_mac_p.h> @@ -114,78 +115,11 @@ static inline char *strdup(const char *data) } #endif -static qint64 qt_native_read(int fd, char *data, qint64 maxlen) -{ - qint64 ret = 0; - do { - ret = ::read(fd, data, maxlen); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static qint64 qt_native_write(int fd, const char *data, qint64 len) -{ - qint64 ret = 0; - do { - ret = ::write(fd, data, len); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static void qt_native_close(int fd) -{ - int ret; - do { - ret = ::close(fd); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_dup2(int oldfd, int newfd) -{ - int ret; - do { - ret = ::dup2(oldfd, newfd); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_chdir(const char *path) -{ - int ret; - do { - ret = ::chdir(path); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execve(const char *filename, char *const argv[], - char *const envp[]) -{ - int ret; - do { - ret = ::execve(filename, argv, envp); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execv(const char *path, char *const argv[]) -{ - int ret; - do { - ret = ::execv(path, argv); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execvp(const char *file, char *const argv[]) -{ - int ret; - do { - ret = ::execvp(file, argv); - } while (ret == -1 && errno == EINTR); -} - static int qt_qprocess_deadChild_pipe[2]; static void (*qt_sa_old_sigchld_handler)(int) = 0; static void qt_sa_sigchld_handler(int signum) { - qt_native_write(qt_qprocess_deadChild_pipe[1], "", 1); + qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1); #if defined (QPROCESS_DEBUG) fprintf(stderr, "*** SIGCHLD\n"); #endif @@ -194,6 +128,13 @@ static void qt_sa_sigchld_handler(int signum) qt_sa_old_sigchld_handler(signum); } +static inline void add_fd(int &nfds, int fd, fd_set *fdset) +{ + FD_SET(fd, fdset); + if ((fd) > nfds) + nfds = fd; +} + struct QProcessInfo { QProcess *process; int deathPipe; @@ -231,13 +172,7 @@ QProcessManager::QProcessManager() // initialize the dead child pipe and make it non-blocking. in the // extremely unlikely event that the pipe fills up, we do not under any // circumstances want to block. - ::pipe(qt_qprocess_deadChild_pipe); - ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFD, FD_CLOEXEC); - ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFL, - ::fcntl(qt_qprocess_deadChild_pipe[0], F_GETFL) | O_NONBLOCK); - ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFL, - ::fcntl(qt_qprocess_deadChild_pipe[1], F_GETFL) | O_NONBLOCK); + qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK); // set up the SIGCHLD handler, which writes a single byte to the dead // child pipe every time a child dies. @@ -254,13 +189,13 @@ QProcessManager::QProcessManager() QProcessManager::~QProcessManager() { // notify the thread that we're shutting down. - qt_native_write(qt_qprocess_deadChild_pipe[1], "@", 1); - qt_native_close(qt_qprocess_deadChild_pipe[1]); + qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1); + qt_safe_close(qt_qprocess_deadChild_pipe[1]); wait(); // on certain unixes, closing the reading end of the pipe will cause // select in run() to block forever, rather than return with EBADF. - qt_native_close(qt_qprocess_deadChild_pipe[0]); + qt_safe_close(qt_qprocess_deadChild_pipe[0]); qt_qprocess_deadChild_pipe[0] = -1; qt_qprocess_deadChild_pipe[1] = -1; @@ -304,7 +239,7 @@ void QProcessManager::run() // signals may have been delivered in the meantime, to avoid race // conditions. char c; - if (qt_native_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@') + if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@') break; // catch any and all children that we can. @@ -323,7 +258,7 @@ void QProcessManager::catchDeadChildren() // notify all children that they may have died. they need to run // waitpid() in their own thread. QProcessInfo *info = it.value(); - qt_native_write(info->deathPipe, "", 1); + qt_safe_write(info->deathPipe, "", 1); #if defined (QPROCESS_DEBUG) qDebug() << "QProcessManager::run() sending death notice to" << info->process; @@ -382,25 +317,23 @@ void QProcessManager::unlock() static void qt_create_pipe(int *pipe) { if (pipe[0] != -1) - qt_native_close(pipe[0]); + qt_safe_close(pipe[0]); if (pipe[1] != -1) - qt_native_close(pipe[1]); - if (::pipe(pipe) != 0) { + qt_safe_close(pipe[1]); + if (qt_safe_pipe(pipe) != 0) { qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s", pipe, qPrintable(qt_error_string(errno))); } - ::fcntl(pipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(pipe[1], F_SETFD, FD_CLOEXEC); } void QProcessPrivate::destroyPipe(int *pipe) { if (pipe[1] != -1) { - qt_native_close(pipe[1]); + qt_safe_close(pipe[1]); pipe[1] = -1; } if (pipe[0] != -1) { - qt_native_close(pipe[0]); + qt_safe_close(pipe[0]); pipe[0] = -1; } } @@ -453,7 +386,7 @@ bool QProcessPrivate::createChannel(Channel &channel) if (&channel == &stdinChannel) { // try to open in read-only mode channel.pipe[1] = -1; - if ( (channel.pipe[0] = QT_OPEN(fname, O_RDONLY)) != -1) + if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1) return true; // success q->setErrorString(QProcess::tr("Could not open input redirection for reading")); @@ -465,7 +398,7 @@ bool QProcessPrivate::createChannel(Channel &channel) mode |= O_TRUNC; channel.pipe[0] = -1; - if ( (channel.pipe[1] = QT_OPEN(fname, mode, 0666)) != -1) + if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1) return true; // success q->setErrorString(QProcess::tr("Could not open output redirection for writing")); @@ -586,8 +519,6 @@ void QProcessPrivate::startProcess() return; qt_create_pipe(childStartedPipe); qt_create_pipe(deathPipe); - ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC); if (threadData->eventDispatcher) { startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], @@ -728,11 +659,11 @@ void QProcessPrivate::startProcess() // parent // close the ends we don't use and make all pipes non-blocking ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); - qt_native_close(childStartedPipe[1]); + qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; if (stdinChannel.pipe[0] != -1) { - qt_native_close(stdinChannel.pipe[0]); + qt_safe_close(stdinChannel.pipe[0]); stdinChannel.pipe[0] = -1; } @@ -740,7 +671,7 @@ void QProcessPrivate::startProcess() ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); if (stdoutChannel.pipe[1] != -1) { - qt_native_close(stdoutChannel.pipe[1]); + qt_safe_close(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = -1; } @@ -748,7 +679,7 @@ void QProcessPrivate::startProcess() ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); if (stderrChannel.pipe[1] != -1) { - qt_native_close(stderrChannel.pipe[1]); + qt_safe_close(stderrChannel.pipe[1]); stderrChannel.pipe[1] = -1; } if (stderrChannel.pipe[0] != -1) @@ -761,35 +692,34 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); - // copy the stdin socket - qt_native_dup2(stdinChannel.pipe[0], fileno(stdin)); + // copy the stdin socket (without closing on exec) + qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { - qt_native_dup2(stdoutChannel.pipe[1], fileno(stdout)); + qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_native_dup2(fileno(stdout), fileno(stderr)); + qt_safe_dup2(fileno(stdout), fileno(stderr), 0); } else { - qt_native_dup2(stderrChannel.pipe[1], fileno(stderr)); + qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); } } // make sure this fd is closed if execvp() succeeds - qt_native_close(childStartedPipe[0]); - ::fcntl(childStartedPipe[1], F_SETFD, FD_CLOEXEC); + qt_safe_close(childStartedPipe[0]); // enter the working directory if (workingDir) - qt_native_chdir(workingDir); + QT_CHDIR(workingDir); // this is a virtual call, and it base behavior is to do nothing. q->setupChildProcess(); // execute the process if (!envp) { - qt_native_execvp(argv[0], argv); + qt_safe_execvp(argv[0], argv); } else { if (path) { char **arg = path; @@ -798,14 +728,14 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]); #endif - qt_native_execve(argv[0], argv, envp); + qt_safe_execve(argv[0], argv, envp); ++arg; } } else { #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]); #endif - qt_native_execve(argv[0], argv, envp); + qt_safe_execve(argv[0], argv, envp); } } @@ -813,21 +743,21 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() failed, notifying parent process\n"); #endif - qt_native_write(childStartedPipe[1], "", 1); - qt_native_close(childStartedPipe[1]); + qt_safe_write(childStartedPipe[1], "", 1); + qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; } bool QProcessPrivate::processStarted() { char c; - int i = qt_native_read(childStartedPipe[0], &c, 1); + int i = qt_safe_read(childStartedPipe[0], &c, 1); if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); startupSocketNotifier->deleteLater(); startupSocketNotifier = 0; } - qt_native_close(childStartedPipe[0]); + qt_safe_close(childStartedPipe[0]); childStartedPipe[0] = -1; #if defined (QPROCESS_DEBUG) @@ -862,7 +792,7 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) { - qint64 bytesRead = qt_native_read(stdoutChannel.pipe[0], data, maxlen); + qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); @@ -872,7 +802,7 @@ qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) { - qint64 bytesRead = qt_native_read(stderrChannel.pipe[0], data, maxlen); + qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); @@ -896,7 +826,7 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) { qt_ignore_sigpipe(); - qint64 written = qt_native_write(stdinChannel.pipe[1], data, maxlen); + qint64 written = qt_safe_write(stdinChannel.pipe[1], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); @@ -922,17 +852,15 @@ void QProcessPrivate::killProcess() ::kill(pid_t(pid), SIGKILL); } -static int qt_native_select(fd_set *fdread, fd_set *fdwrite, int timeout) +static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) { + if (timeout < 0) + return qt_safe_select(nfds, fdread, fdwrite, 0, 0); + struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - - int ret; - do { - ret = select(FD_SETSIZE, fdread, fdwrite, 0, timeout < 0 ? 0 : &tv); - } while (ret < 0 && (errno == EINTR)); - return ret; + return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); } /* @@ -960,11 +888,7 @@ bool QProcessPrivate::waitForStarted(int msecs) fd_set fds; FD_ZERO(&fds); FD_SET(childStartedPipe[0], &fds); - int ret; - do { - ret = qt_native_select(&fds, 0, msecs); - } while (ret < 0 && errno == EINTR); - if (ret == 0) { + if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); #if defined (QPROCESS_DEBUG) @@ -997,24 +921,23 @@ bool QProcessPrivate::waitForReadyRead(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); + int nfds = deathPipe[0]; + FD_SET(deathPipe[0], &fdread); + if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); - - FD_SET(deathPipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } if (ret == 0) { @@ -1070,24 +993,24 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); + int nfds = deathPipe[0]; + FD_SET(deathPipe[0], &fdread); + if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); - FD_SET(deathPipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } @@ -1133,29 +1056,28 @@ bool QProcessPrivate::waitForFinished(int msecs) forever { fd_set fdread; fd_set fdwrite; + int nfds = -1; FD_ZERO(&fdread); FD_ZERO(&fdwrite); if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); if (processState == QProcess::Running) - FD_SET(deathPipe[0], &fdread); + add_fd(nfds, deathPipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } if (ret == 0) { @@ -1190,12 +1112,7 @@ bool QProcessPrivate::waitForWrite(int msecs) fd_set fdwrite; FD_ZERO(&fdwrite); FD_SET(stdinChannel.pipe[1], &fdwrite); - - int ret; - do { - ret = qt_native_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; - } while (ret < 0 && errno == EINTR); - return ret == 1; + return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; } void QProcessPrivate::findExitCode() @@ -1210,15 +1127,11 @@ bool QProcessPrivate::waitForDeadChild() // read a byte from the death pipe char c; - qt_native_read(deathPipe[0], &c, 1); + qt_safe_read(deathPipe[0], &c, 1); // check if our process is dead int exitStatus; - pid_t waitResult = 0; - do { - waitResult = waitpid(pid_t(pid), &exitStatus, WNOHANG); - } while ((waitResult == -1 && errno == EINTR)); - if (waitResult > 0) { + if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) { processManager()->remove(q); crashed = !WIFEXITED(exitStatus); exitCode = WEXITSTATUS(exitStatus); @@ -1248,10 +1161,10 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // To catch the startup of the child int startedPipe[2]; - ::pipe(startedPipe); + qt_safe_pipe(startedPipe); // To communicate the pid of the child int pidPipe[2]; - ::pipe(pidPipe); + qt_safe_pipe(pidPipe); pid_t childPid = qt_fork(); if (childPid == 0) { @@ -1262,16 +1175,15 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a ::setsid(); - qt_native_close(startedPipe[0]); - qt_native_close(pidPipe[0]); + qt_safe_close(startedPipe[0]); + qt_safe_close(pidPipe[0]); pid_t doubleForkPid = qt_fork(); if (doubleForkPid == 0) { - ::fcntl(startedPipe[1], F_SETFD, FD_CLOEXEC); - qt_native_close(pidPipe[1]); + qt_safe_close(pidPipe[1]); if (!encodedWorkingDirectory.isEmpty()) - qt_native_chdir(encodedWorkingDirectory.constData()); + QT_CHDIR(encodedWorkingDirectory.constData()); char **argv = new char *[arguments.size() + 2]; for (int i = 0; i < arguments.size(); ++i) { @@ -1292,13 +1204,13 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a if (!tmp.endsWith('/')) tmp += '/'; tmp += QFile::encodeName(program); argv[0] = tmp.data(); - qt_native_execv(argv[0], argv); + qt_safe_execv(argv[0], argv); } } } else { QByteArray tmp = QFile::encodeName(program); argv[0] = tmp.data(); - qt_native_execv(argv[0], argv); + qt_safe_execv(argv[0], argv); } struct sigaction noaction; @@ -1308,8 +1220,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // '\1' means execv failed char c = '\1'; - qt_native_write(startedPipe[1], &c, 1); - qt_native_close(startedPipe[1]); + qt_safe_write(startedPipe[1], &c, 1); + qt_safe_close(startedPipe[1]); ::_exit(1); } else if (doubleForkPid == -1) { struct sigaction noaction; @@ -1319,40 +1231,39 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // '\2' means internal error char c = '\2'; - qt_native_write(startedPipe[1], &c, 1); + qt_safe_write(startedPipe[1], &c, 1); } - qt_native_close(startedPipe[1]); - qt_native_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t)); - qt_native_chdir("/"); + qt_safe_close(startedPipe[1]); + qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t)); + QT_CHDIR("/"); ::_exit(1); } - qt_native_close(startedPipe[1]); - qt_native_close(pidPipe[1]); + qt_safe_close(startedPipe[1]); + qt_safe_close(pidPipe[1]); if (childPid == -1) { - qt_native_close(startedPipe[0]); - qt_native_close(pidPipe[0]); + qt_safe_close(startedPipe[0]); + qt_safe_close(pidPipe[0]); return false; } char reply = '\0'; - int startResult = qt_native_read(startedPipe[0], &reply, 1); + int startResult = qt_safe_read(startedPipe[0], &reply, 1); int result; - qt_native_close(startedPipe[0]); - while (::waitpid(childPid, &result, 0) == -1 && errno == EINTR) - { } + qt_safe_close(startedPipe[0]); + qt_safe_waitpid(childPid, &result, 0); bool success = (startResult != -1 && reply == '\0'); if (success && pid) { pid_t actualPid = 0; - if (qt_native_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { + if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { *pid = actualPid; } else { *pid = 0; } } - qt_native_close(pidPipe[0]); + qt_safe_close(pidPipe[0]); return success; } diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index d028df1..eae17b4 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -54,7 +54,7 @@ #include <private/qthread_p.h> #include <qdebug.h> -#include "private/qfsfileengine_p.h" // for longFileName and win95FileName +#include "private/qfsfileengine_p.h" // for longFileName #ifndef QT_NO_PROCESS @@ -122,25 +122,15 @@ bool QProcessPrivate::createChannel(Channel &channel) if (&channel == &stdinChannel) { // try to open in read-only mode channel.pipe[1] = INVALID_Q_PIPE; - QT_WA({ - channel.pipe[0] = - CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - channel.pipe[0] = - CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + channel.pipe[0] = + CreateFile((const wchar_t*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &secAtt, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (channel.pipe[0] != INVALID_Q_PIPE) return true; @@ -148,31 +138,15 @@ bool QProcessPrivate::createChannel(Channel &channel) } else { // open in write mode channel.pipe[0] = INVALID_Q_PIPE; - DWORD creation; - if (channel.append) - creation = OPEN_ALWAYS; - else - creation = CREATE_ALWAYS; - - QT_WA({ - channel.pipe[1] = - CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - creation, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - channel.pipe[1] = - CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - creation, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + channel.pipe[1] = + CreateFile((const wchar_t *)QFSFileEnginePrivate::longFileName(channel.file).utf16(), + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &secAtt, + channel.append ? OPEN_ALWAYS : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (channel.pipe[1] != INVALID_Q_PIPE) { if (channel.append) { SetFilePointer(channel.pipe[1], 0, NULL, FILE_END); @@ -327,56 +301,37 @@ static QByteArray qt_create_environment(const QHash<QString, QString> *environme int pos = 0; QHash<QString, QString>::ConstIterator it = copy.constBegin(), end = copy.constEnd(); -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { - static const TCHAR equal = L'='; - static const TCHAR nul = L'\0'; - - for ( ; it != end; ++it) { - uint tmpSize = sizeof(TCHAR) * (it.key().length() + it.value().length() + 2); - // ignore empty strings - if (tmpSize == sizeof(TCHAR)*2) - continue; - envlist.resize(envlist.size() + tmpSize); - - tmpSize = it.key().length() * sizeof(TCHAR); - memcpy(envlist.data()+pos, it.key().utf16(), tmpSize); - pos += tmpSize; - - memcpy(envlist.data()+pos, &equal, sizeof(TCHAR)); - pos += sizeof(TCHAR); - - tmpSize = it.value().length() * sizeof(TCHAR); - memcpy(envlist.data()+pos, it.value().utf16(), tmpSize); - pos += tmpSize; - - memcpy(envlist.data()+pos, &nul, sizeof(TCHAR)); - pos += sizeof(TCHAR); - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - } else -#endif // UNICODE - { - for ( ; it != end; it++) { - QByteArray tmp = it.key().toLocal8Bit(); - tmp.append('='); - tmp.append(it.value().toLocal8Bit()); - - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the terminating 0 (actually 2, just to be on the safe side) - envlist.resize(envlist.size()+2); - envlist[pos++] = 0; - envlist[pos++] = 0; + + static const wchar_t equal = L'='; + static const wchar_t nul = L'\0'; + + for ( ; it != end; ++it) { + uint tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2); + // ignore empty strings + if (tmpSize == sizeof(wchar_t) * 2) + continue; + envlist.resize(envlist.size() + tmpSize); + + tmpSize = it.key().length() * sizeof(wchar_t); + memcpy(envlist.data()+pos, it.key().utf16(), tmpSize); + pos += tmpSize; + + memcpy(envlist.data()+pos, &equal, sizeof(wchar_t)); + pos += sizeof(wchar_t); + + tmpSize = it.value().length() * sizeof(wchar_t); + memcpy(envlist.data()+pos, it.value().utf16(), tmpSize); + pos += tmpSize; + + memcpy(envlist.data()+pos, &nul, sizeof(wchar_t)); + pos += sizeof(wchar_t); } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize( envlist.size()+4 ); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; } return envlist; } @@ -417,58 +372,33 @@ void QProcessPrivate::startProcess() qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); #endif - DWORD dwCreationFlags = 0; - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) - dwCreationFlags |= CREATE_NO_WINDOW; + DWORD dwCreationFlags = CREATE_NO_WINDOW; -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { #if defined(Q_OS_WINCE) QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath(); fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); - success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), - (WCHAR*)args.utf16(), - 0, 0, false, 0, 0, 0, 0, pid); + success = CreateProcess((wchar_t*)fullPathProgram.utf16(), + (wchar_t*)args.utf16(), + 0, 0, false, 0, 0, 0, 0, pid); #else dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] + (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, + 0, 0, 0, + STARTF_USESTDHANDLES, + 0, 0, 0, + stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] }; - success = CreateProcessW(0, (WCHAR*)args.utf16(), - 0, 0, TRUE, dwCreationFlags, - environment ? envlist.data() : 0, - workingDirectory.isEmpty() ? 0 - : (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(), - &startupInfo, pid); -#endif - } else -#endif // UNICODE - { -#ifndef Q_OS_WINCE - STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] - }; - - success = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, TRUE, dwCreationFlags, environment ? envlist.data() : 0, - workingDirectory.isEmpty() ? 0 - : QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(), - &startupInfo, pid); -#endif // Q_OS_WINCE - } -#ifndef Q_OS_WINCE + success = CreateProcess(0, (wchar_t*)args.utf16(), + 0, 0, TRUE, dwCreationFlags, + environment ? envlist.data() : 0, + workingDirectory.isEmpty() ? 0 + : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), + &startupInfo, pid); + if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { CloseHandle(stdinChannel.pipe[0]); stdinChannel.pipe[0] = INVALID_Q_PIPE; @@ -508,7 +438,7 @@ void QProcessPrivate::startProcess() } // give the process a chance to start ... - Sleep(SLEEPMIN*2); + Sleep(SLEEPMIN * 2); _q_startupNotification(); } @@ -882,42 +812,25 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a PROCESS_INFORMATION pinfo; -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { #if defined(Q_OS_WINCE) QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/'))); fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); - success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), - (WCHAR*)args.utf16(), - 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo); + success = CreateProcess((wchar_t*)fullPathProgram.utf16(), + (wchar_t*)args.utf16(), + 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo); #else STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - success = CreateProcessW(0, (WCHAR*)args.utf16(), - 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, - workingDir.isEmpty() ? (const WCHAR *)0 : (const WCHAR *)workingDir.utf16(), - &startupInfo, &pinfo); -#endif - } else -#endif // UNICODE - { -#ifndef Q_OS_WINCE - STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - success = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, - workingDir.isEmpty() ? (LPCSTR)0 : workingDir.toLocal8Bit().constData(), + success = CreateProcess(0, (wchar_t*)args.utf16(), + 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, + workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(), &startupInfo, &pinfo); #endif // Q_OS_WINCE - } if (success) { CloseHandle(pinfo.hThread); diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index f59be7b..e15fcf2 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -56,8 +56,21 @@ #include <qplatformdefs.h> #include "private/qabstractfileengine_p.h" +#ifdef Q_OS_UNIX +# include "private/qcore_unix_p.h" +#endif + //#define DEBUG_RESOURCE_MATCH +#if defined(Q_OS_VXWORKS) +# if defined(m_data) +# undef m_data +# endif +# if defined(m_len) +# undef m_len +# endif +#endif + QT_BEGIN_NAMESPACE @@ -568,7 +581,7 @@ QResource::addSearchPath(const QString &path) Returns the current search path list. This list is consulted when creating a relative resource. - \sa addSearchPath() + \sa QDir::addSearchPath() QDir::setSearchPaths() */ QStringList diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h index 49dacea..0bf9660 100644 --- a/src/corelib/io/qresource.h +++ b/src/corelib/io/qresource.h @@ -94,7 +94,7 @@ protected: QScopedPointer<QResourcePrivate> d_ptr; private: - Q_DECLARE_SCOPED_PRIVATE(QResource) + Q_DECLARE_PRIVATE(QResource) }; QT_END_NAMESPACE diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp index e97ac59..11f4acf 100644 --- a/src/corelib/io/qresource_iterator.cpp +++ b/src/corelib/io/qresource_iterator.cpp @@ -73,13 +73,11 @@ bool QResourceFileEngineIterator::hasNext() const return false; // Initialize and move to the next entry. - QResourceFileEngineIterator *that = const_cast<QResourceFileEngineIterator *>(this); - that->entries = resource.children(); - if (!that->entries.isEmpty()) - that->index = 0; + entries = resource.children(); + index = 0; } - return index <= entries.size(); + return index < entries.size(); } QString QResourceFileEngineIterator::currentFileName() const diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h index b5e8382..5165157 100644 --- a/src/corelib/io/qresource_iterator_p.h +++ b/src/corelib/io/qresource_iterator_p.h @@ -71,8 +71,8 @@ public: QString currentFileName() const; private: - QStringList entries; - int index; + mutable QStringList entries; + mutable int index; }; QT_END_NAMESPACE diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h index 452d8e1..f58f9a2 100644 --- a/src/corelib/io/qresource_p.h +++ b/src/corelib/io/qresource_p.h @@ -61,7 +61,7 @@ class QResourceFileEnginePrivate; class QResourceFileEngine : public QAbstractFileEngine { private: - Q_DECLARE_SCOPED_PRIVATE(QResourceFileEngine) + Q_DECLARE_PRIVATE(QResourceFileEngine) public: explicit QResourceFileEngine(const QString &path); ~QResourceFileEngine(); diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 1650526..7df6eee 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -74,6 +74,10 @@ #endif // Q_OS_WIN #endif // QT_NO_QOBJECT +#ifdef Q_OS_VXWORKS +# include <ioLib.h> +#endif + #include <stdlib.h> #ifndef CSIDL_COMMON_APPDATA @@ -167,7 +171,7 @@ static bool isLikelyToBeNfs(int handle) } #elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \ - || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_QNX6) || defined(Q_OS_SCO) \ + || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \ || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD) QT_BEGIN_INCLUDE_NAMESPACE # include <sys/statvfs.h> @@ -1042,33 +1046,16 @@ static QString windowsConfigPath(int type) // This only happens when bootstrapping qmake. #ifndef Q_OS_WINCE QLibrary library(QLatin1String("shell32")); - QT_WA( { - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - if (SHGetSpecialFolderPath) { - TCHAR path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromUtf16((ushort*)path); - } - } , { - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA"); - if (SHGetSpecialFolderPath) { - char path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromLocal8Bit(path); - } - } ); #else QLibrary library(QLatin1String("coredll")); - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPath"); +#endif // Q_OS_WINCE + typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); + GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); if (SHGetSpecialFolderPath) { wchar_t path[MAX_PATH]; SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromUtf16((ushort*)path); + result = QString::fromWCharArray(path); } -#endif // Q_OS_WINCE #endif // QT_NO_QOBJECT @@ -1466,11 +1453,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); - QT_WA( { - writeSemaphore = CreateSemaphoreW(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); - } , { - writeSemaphore = CreateSemaphoreA(0, 1, 1, writeSemName.toLocal8Bit()); - } ); + writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); if (writeSemaphore) { WaitForSingleObject(writeSemaphore, INFINITE); @@ -1486,11 +1469,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString readSemName(QLatin1String("QSettingsReadSem ")); readSemName.append(file.fileName()); - QT_WA( { - readSemaphore = CreateSemaphoreW(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); - } , { - readSemaphore = CreateSemaphoreA(0, FileLockSemMax, FileLockSemMax, readSemName.toLocal8Bit()); - } ); + readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h index a082d6a..0d382b66 100644 --- a/src/corelib/io/qsettings.h +++ b/src/corelib/io/qsettings.h @@ -80,7 +80,7 @@ class Q_CORE_EXPORT QSettings #else QScopedPointer<QSettingsPrivate> d_ptr; #endif - Q_DECLARE_SCOPED_PRIVATE(QSettings) + Q_DECLARE_PRIVATE(QSettings) public: enum Status { diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index 0cbcc10..1e1509d 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -130,24 +130,13 @@ static void mergeKeySets(NameSet *dest, const QStringList &src) static QString errorCodeToString(DWORD errorCode) { - QString result; - QT_WA({ - wchar_t *data = 0; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - 0, errorCode, 0, - data, 0, 0); - result = QString::fromUtf16(reinterpret_cast<const ushort *> (data)); - if (data != 0) - LocalFree(data); - }, { - char *data = 0; - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - 0, errorCode, 0, - (char *)&data, 0, 0); - result = QString::fromLocal8Bit(data); - if (data != 0) - LocalFree(data); - }) + wchar_t *data = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0); + QString result = QString::fromWCharArray(data); + + if (data != 0) + LocalFree(data); + if (result.endsWith(QLatin1Char('\n'))) result.truncate(result.length() - 1); @@ -158,15 +147,8 @@ static QString errorCodeToString(DWORD errorCode) static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey) { HKEY resultHandle = 0; - - LONG res; - QT_WA( { - res = RegOpenKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), - 0, perms, &resultHandle); - } , { - res = RegOpenKeyExA(parentHandle, rSubKey.toLocal8Bit(), + LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, perms, &resultHandle); - } ); if (res == ERROR_SUCCESS) return resultHandle; @@ -183,14 +165,8 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub return resultHandle; // try to create it - LONG res; - QT_WA( { - res = RegCreateKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0, - REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0); - } , { - res = RegCreateKeyExA(parentHandle, rSubKey.toLocal8Bit(), 0, 0, + LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0, REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0); - } ); if (res == ERROR_SUCCESS) return resultHandle; @@ -225,20 +201,14 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec) { QStringList result; - LONG res; DWORD numKeys; DWORD maxKeySize; DWORD numSubgroups; DWORD maxSubgroupSize; // Find the number of keys and subgroups, as well as the max of their lengths. - QT_WA( { - res = RegQueryInfoKeyW(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, + LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, &numKeys, &maxKeySize, 0, 0, 0); - }, { - res = RegQueryInfoKeyA(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, - &numKeys, &maxKeySize, 0, 0, 0); - } ); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data()); @@ -258,36 +228,21 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS m = maxSubgroupSize; } - /* Windows NT/2000/XP: The size does not include the terminating null character. - Windows Me/98/95: The size includes the terminating null character. */ + /* The size does not include the terminating null character. */ ++m; // Get the list - QByteArray buff(m*sizeof(ushort), 0); + QByteArray buff(m * sizeof(wchar_t), 0); for (int i = 0; i < n; ++i) { QString item; - QT_WA( { - DWORD l = buff.size() / sizeof(ushort); - if (spec == QSettingsPrivate::ChildKeys) { - res = RegEnumValueW(parentHandle, i, - reinterpret_cast<wchar_t *>(buff.data()), - &l, 0, 0, 0, 0); - } else { - res = RegEnumKeyExW(parentHandle, i, - reinterpret_cast<wchar_t *>(buff.data()), - &l, 0, 0, 0, 0); - } - if (res == ERROR_SUCCESS) - item = QString::fromUtf16(reinterpret_cast<ushort*>(buff.data()), l); - }, { - DWORD l = buff.size(); - if (spec == QSettingsPrivate::ChildKeys) - res = RegEnumValueA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0); - else - res = RegEnumKeyExA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0); - if (res == ERROR_SUCCESS) - item = QString::fromLocal8Bit(buff.data(), l); - } ); + DWORD l = buff.size() / sizeof(wchar_t); + if (spec == QSettingsPrivate::ChildKeys) { + res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0); + } else { + res = RegEnumKeyEx(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0); + } + if (res == ERROR_SUCCESS) + item = QString::fromWCharArray((const wchar_t *)buff.constData(), l); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data()); @@ -342,12 +297,7 @@ static void deleteChildGroups(HKEY parentHandle) RegCloseKey(childGroupHandle); // delete group itself - LONG res; - QT_WA( { - res = RegDeleteKeyW(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16())); - }, { - res = RegDeleteKeyA(parentHandle, group.toLocal8Bit()); - } ); + LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s", group.toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -519,12 +469,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa // get the size and type of the value DWORD dataType; DWORD dataSize; - LONG res; - QT_WA( { - res = RegQueryValueExW(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize); - } ); + LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return false; @@ -532,13 +477,8 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa // get the value QByteArray data(dataSize, 0); - QT_WA( { - res = RegQueryValueExW(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0, - reinterpret_cast<unsigned char*>(data.data()), &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0, - reinterpret_cast<unsigned char*>(data.data()), &dataSize); - } ); + res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0, + reinterpret_cast<unsigned char*>(data.data()), &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return false; @@ -549,11 +489,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa case REG_SZ: { QString s; if (dataSize) { - QT_WA( { - s = QString::fromUtf16(((const ushort*)data.constData())); - }, { - s = QString::fromLocal8Bit(data.constData()); - } ); + s = QString::fromWCharArray(((const wchar_t *)data.constData())); } if (value != 0) *value = stringToVariant(s); @@ -565,12 +501,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa if (dataSize) { int i = 0; for (;;) { - QString s; - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData() + i); - }, { - s = QString::fromLocal8Bit(data.constData() + i); - } ); + QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i); i += s.length() + 1; if (s.isEmpty()) @@ -587,11 +518,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa case REG_BINARY: { QString s; if (dataSize) { - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData(), data.size()/2); - }, { - s = QString::fromLocal8Bit(data.constData(), data.size()); - } ); + s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2); } if (value != 0) *value = stringToVariant(s); @@ -635,13 +562,8 @@ QWinSettingsPrivate::~QWinSettingsPrivate() #if defined(Q_OS_WINCE) remove(regList.at(0).key()); #else - DWORD res; QString emptyKey; - QT_WA( { - res = RegDeleteKeyW(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16())); - }, { - res = RegDeleteKeyA(writeHandle(), emptyKey.toLocal8Bit()); - } ); + DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: Failed to delete key \"%s\": %s", regList.at(0).key().toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -666,11 +588,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) LONG res; HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey)); if (handle != 0) { - QT_WA( { - res = RegDeleteValueW(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16())); - }, { - res = RegDeleteValueA(handle, keyName(rKey).toLocal8Bit()); - } ); + res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16())); RegCloseKey(handle); } @@ -685,12 +603,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) for (int i = 0; i < childKeys.size(); ++i) { QString group = childKeys.at(i); - LONG res; - QT_WA( { - res = RegDeleteValueW(handle, reinterpret_cast<const wchar_t *>(group.utf16())); - }, { - res = RegDeleteValueA(handle, group.toLocal8Bit()); - } ); + LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s", group.toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -701,11 +614,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) // For WinCE always Close the handle first. RegCloseKey(handle); #endif - QT_WA( { - res = RegDeleteKeyW(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16())); - }, { - res = RegDeleteKeyA(writeHandle(), rKey.toLocal8Bit()); - } ); + res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s", @@ -761,27 +670,15 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) if (type == REG_BINARY) { QString s = variantToString(value); - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length()); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2); } else { QStringList::const_iterator it = l.constBegin(); for (; it != l.constEnd(); ++it) { const QString &s = *it; - QT_WA( { - regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1)*2); - }, { - regValueBuff += QByteArray((const char*)s.toLocal8Bit(), s.length() + 1); - } ); + regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2); } - QT_WA( { - regValueBuff.append((char)0); - regValueBuff.append((char)0); - }, { - regValueBuff.append((char)0); - } ); + regValueBuff.append((char)0); + regValueBuff.append((char)0); } break; } @@ -794,21 +691,6 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) } case QVariant::ByteArray: - // On Win95/98/Me QString::toLocal8Bit() fails to handle chars > 0x7F. So we don't go through variantToString() at all. - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - QByteArray ba = value.toByteArray(); - regValueBuff = "@ByteArray("; - regValueBuff += ba; - regValueBuff += ')'; - if (ba.contains('\0')) { - type = REG_BINARY; - } else { - type = REG_SZ; - regValueBuff += '\0'; - } - - break; - } // fallthrough intended default: { @@ -817,33 +699,18 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) QString s = variantToString(value); type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ; if (type == REG_BINARY) { - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length()); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2); } else { - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1)*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length() + 1); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2); } break; } } // set the value - LONG res; - QT_WA( { - res = RegSetValueExW(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type, - reinterpret_cast<const unsigned char*>(regValueBuff.constData()), - regValueBuff.size()); - }, { - res = RegSetValueExA(handle, keyName(rKey).toLocal8Bit(), 0, type, + LONG res = RegSetValueEx(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type, reinterpret_cast<const unsigned char*>(regValueBuff.constData()), regValueBuff.size()); - } ); if (res == ERROR_SUCCESS) { deleteWriteHandleOnExit = false; diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index cd8d36d..ccc753a 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -60,6 +60,10 @@ #include <time.h> #include <ctype.h> +#if defined(Q_OS_UNIX) +# include "private/qcore_unix_p.h" // overrides QT_OPEN +#endif + #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) # include <process.h> # if defined(_MSC_VER) && _MSC_VER >= 1400 @@ -69,9 +73,11 @@ #if defined(Q_OS_WINCE) # include <types.h> -# include "qfunctions_wince.h" #endif +#if defined(Q_OS_VXWORKS) +# include <taskLib.h> +#endif QT_BEGIN_NAMESPACE @@ -130,6 +136,8 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) } #if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 pid = _getpid(); +#elif defined(Q_OS_VXWORKS) + pid = (pid_t) taskIdCurrent; #else pid = getpid(); #endif @@ -208,8 +216,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) if ((*doopen = QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR # else // CE + // this is Unix or older MSVC if ((*doopen = - open(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR + QT_OPEN(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR # endif # ifdef QT_LARGEFILE_SUPPORT |QT_OPEN_LARGEFILE @@ -219,18 +228,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) # elif defined(Q_OS_WIN) |O_BINARY # endif -# ifdef O_CLOEXEC - // supported on Linux >= 2.6.23; avoids one extra system call - // and avoids a race condition: if another thread forks, we could - // end up leaking a file descriptor... - |O_CLOEXEC -# endif , 0600)) >= 0) #endif // WIN && !CE { -#if defined(Q_OS_UNIX) && !defined(O_CLOEXEC) - fcntl(*doopen, F_SETFD, FD_CLOEXEC); -#endif return 1; } if (errno != EEXIST) @@ -239,7 +239,7 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) #ifdef Q_OS_WIN if (QT_MKDIR(path) == 0) #else - if (mkdir(path, 0700) == 0) + if (QT_MKDIR(path, 0700) == 0) #endif return 1; if (errno != EEXIST) @@ -289,7 +289,7 @@ static int qt_mkstemps(char *path, int slen) //************* QTemporaryFileEngine class QTemporaryFileEngine : public QFSFileEngine { - Q_DECLARE_SCOPED_PRIVATE(QFSFileEngine) + Q_DECLARE_PRIVATE(QFSFileEngine) public: QTemporaryFileEngine(const QString &file, bool fileIsTemplate = true) : QFSFileEngine(file), filePathIsTemplate(fileIsTemplate) diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h index c0b41bb..a597a93 100644 --- a/src/corelib/io/qtemporaryfile.h +++ b/src/corelib/io/qtemporaryfile.h @@ -64,7 +64,7 @@ class Q_CORE_EXPORT QTemporaryFile : public QFile #ifndef QT_NO_QOBJECT Q_OBJECT #endif - Q_DECLARE_SCOPED_PRIVATE(QTemporaryFile) + Q_DECLARE_PRIVATE(QTemporaryFile) public: QTemporaryFile(); diff --git a/src/corelib/io/qtextstream.h b/src/corelib/io/qtextstream.h index 9d4b3d0..fc4794e 100644 --- a/src/corelib/io/qtextstream.h +++ b/src/corelib/io/qtextstream.h @@ -72,7 +72,7 @@ class QTextDecoder; class QTextStreamPrivate; class Q_CORE_EXPORT QTextStream // text stream class { - Q_DECLARE_SCOPED_PRIVATE(QTextStream) + Q_DECLARE_PRIVATE(QTextStream) public: enum RealNumberNotation { diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 180e9ec..79cd2f0 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -2336,12 +2336,12 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { { 0x1D7BB, { 0x03C3, 0x0000, 0x0000, 0x0000 } } }; -static void mapToLowerCase(QString *str) +static void mapToLowerCase(QString *str, int from) { int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); QChar *d = 0; - for (int i = 0; i < str->size(); ++i) { + for (int i = from; i < str->size(); ++i) { int uc = str->at(i).unicode(); if (uc < 0x80) { if (uc <= 'Z' && uc >= 'A') { @@ -2388,11 +2388,11 @@ static bool isMappedToNothing(const QChar &ch) } -static void stripProhibitedOutput(QString *str) +static void stripProhibitedOutput(QString *str, int from) { - ushort *out = (ushort *)str->data(); + ushort *out = (ushort *)str->data() + from; const ushort *in = out; - const ushort *end = out + str->size(); + const ushort *end = (ushort *)str->data() + str->size(); while (in < end) { ushort uc = *in; if (uc < 0x80 || @@ -2901,66 +2901,99 @@ static bool isBidirectionalL(const QChar &ch) return false; } +#ifdef QT_BUILD_INTERNAL +// export for tst_qurl.cpp +Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from); +Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len); +#else +// non-test build, keep the symbols for ourselves +static void qt_nameprep(QString *source, int from); +static bool qt_check_std3rules(const QChar *uc, int len); +#endif -Q_AUTOTEST_EXPORT QString qt_nameprep(const QString &source) +void qt_nameprep(QString *source, int from) { - QString mapped = source; - - bool simple = true; - for (int i = 0; i < mapped.size(); ++i) { - ushort uc = mapped.at(i).unicode(); + QChar *src = source->data(); // causes a detach, so we're sure the only one using it + QChar *out = src + from; + const QChar *e = src + source->size(); + + for ( ; out < e; ++out) { + register ushort uc = out->unicode(); if (uc > 0x80) { - simple = false; break; } else if (uc >= 'A' && uc <= 'Z') { - mapped[i] = QChar(uc | 0x20); + *out = QChar(uc | 0x20); } } - if (simple) - return mapped; - + if (out == e) + return; // everything was mapped easily (lowercased, actually) + int firstNonAscii = out - src; + // Characters commonly mapped to nothing are simply removed // (Table B.1) - QChar *out = mapped.data(); const QChar *in = out; - const QChar *e = in + mapped.size(); while (in < e) { if (!isMappedToNothing(*in)) *out++ = *in; ++in; } if (out != in) - mapped.truncate(out - mapped.constData()); + source->truncate(out - src); // Map to lowercase (Table B.2) - mapToLowerCase(&mapped); + mapToLowerCase(source, firstNonAscii); // Normalize to Unicode 3.2 form KC - mapped = mapped.normalized(QString::NormalizationForm_KC, QChar::Unicode_3_2); + extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, + QChar::UnicodeVersion version, int from); + qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); // Strip prohibited output - stripProhibitedOutput(&mapped); + stripProhibitedOutput(source, firstNonAscii); // Check for valid bidirectional characters bool containsLCat = false; bool containsRandALCat = false; - for (int j = 0; j < mapped.size() && (!containsLCat || !containsRandALCat); ++j) { - if (isBidirectionalL(mapped.at(j))) + src = source->data(); + e = src + source->size(); + for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { + if (isBidirectionalL(*in)) containsLCat = true; - else if (isBidirectionalRorAL(mapped.at(j))) + else if (isBidirectionalRorAL(*in)) containsRandALCat = true; } if (containsRandALCat) { - if (containsLCat || (!isBidirectionalRorAL(mapped.at(0)) - || !isBidirectionalRorAL(mapped.at(mapped.size() - 1)))) - mapped.clear(); + if (containsLCat || (!isBidirectionalRorAL(src[from]) + || !isBidirectionalRorAL(e[-1]))) + source->resize(from); // not allowed, clear the label } +} + +bool qt_check_std3rules(const QChar *uc, int len) +{ + if (len > 63) + return false; - return mapped; + for (int i = 0; i < len; ++i) { + register ushort c = uc[i].unicode(); + if (c == '-' && (i == 0 || i == len - 1)) + return false; + + // verifying the absence of LDH is the same as verifying that + // only LDH is present + if (c == '-' || (c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')) + continue; + + return false; + } + + return true; } -static inline char encodeDigit(uint digit) +static inline uint encodeDigit(uint digit) { return digit + 22 + 75 * (digit < 26); } @@ -2977,7 +3010,7 @@ static inline uint adapt(uint delta, uint numpoints, bool firsttime) return k + (((base - tmin + 1) * delta) / (delta + skew)); } -static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uint& b, uint& h) +static inline void appendEncode(QString* output, uint& delta, uint& bias, uint& b, uint& h) { uint qq; uint k; @@ -2991,17 +3024,17 @@ static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uin t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias; if (qq < t) break; - *output += encodeDigit(t + (qq - t) % (base - t)); + *output += QChar(encodeDigit(t + (qq - t) % (base - t))); qq = (qq - t) / (base - t); } - *output += encodeDigit(qq); + *output += QChar(encodeDigit(qq)); bias = adapt(delta, h + 1, h == b); delta = 0; ++h; } -static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) +static void toPunycodeHelper(const QChar *s, int ucLength, QString *output) { uint n = initial_n; uint delta = 0; @@ -3010,7 +3043,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) int outLen = output->length(); output->resize(outLen + ucLength); - char *d = output->data() + outLen; + QChar *d = output->data() + outLen; bool skipped = false; // copy all basic code points verbatim to output. for (uint j = 0; j < (uint) ucLength; ++j) { @@ -3035,7 +3068,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) // if basic code points were copied, add the delimiter character. if (h > 0) - *output += 0x2d; + *output += QChar(0x2d); // while there are still unprocessed non-basic code points left in // the input string... @@ -3083,7 +3116,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) } // prepend ACE prefix - output->insert(outLen, "xn--"); + output->insert(outLen, QLatin1String("xn--")); return; } @@ -3144,11 +3177,15 @@ static bool qt_is_idn_enabled(const QString &domain) int idx = domain.lastIndexOf(QLatin1Char('.')); if (idx == -1) return false; - const QChar *tld = domain.constData() + idx + 1; + int len = domain.size() - idx - 1; + QString tldString(domain.constData() + idx + 1, len); + qt_nameprep(&tldString, 0); + + const QChar *tld = tldString.constData(); if (user_idn_whitelist) - return user_idn_whitelist->contains(QString(tld, len)); + return user_idn_whitelist->contains(tldString); int l = 0; int r = sizeof(idn_whitelist)/sizeof(const char *) - 1; @@ -3164,46 +3201,127 @@ static bool qt_is_idn_enabled(const QString &domain) return equal(tld, len, idn_whitelist[i]); } -static QString qt_from_ACE(const QString &domainMC) +static inline bool isDotDelimiter(ushort uc) { - QString domain = domainMC.toLower(); - int idx = domain.indexOf(QLatin1Char('.')); - if (idx != -1) { - if (!domain.contains(QLatin1String("xn--"))) { - bool simple = true; - for (int i = 0; i < domain.size(); ++i) { - ushort ch = domain.at(i).unicode(); - if (ch > 'z' || ch < '-' || ch == '/' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a')) { + // IDNA / rfc3490 describes these four delimiters used for + // separating labels in unicode international domain + // names. + return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61; +} + +static int nextDotDelimiter(const QString &domain, int from = 0) +{ + const QChar *b = domain.unicode(); + const QChar *ch = b + from; + const QChar *e = b + domain.length(); + while (ch < e) { + if (isDotDelimiter(ch->unicode())) + break; + else + ++ch; + } + return ch - b; +} + +enum AceOperation { ToAceOnly, NormalizeAce }; +static QString qt_ACE_do(const QString &domain, AceOperation op) +{ + if (domain.isEmpty()) + return domain; + + QString result; + result.reserve(domain.length()); + + const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false; + int lastIdx = 0; + QString aceForm; // this variable is here for caching + + while (1) { + int idx = nextDotDelimiter(domain, lastIdx); + int labelLength = idx - lastIdx; + if (labelLength == 0) + return QString(); // two delimiters in a row -- empty label not allowed + + // RFC 3490 says, about the ToASCII operation: + // 3. If the UseSTD3ASCIIRules flag is set, then perform these checks: + // + // (a) Verify the absence of non-LDH ASCII code points; that is, the + // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F. + // + // (b) Verify the absence of leading and trailing hyphen-minus; that + // is, the absence of U+002D at the beginning and end of the + // sequence. + // and: + // 8. Verify that the number of code points is in the range 1 to 63 + // inclusive. + + // copy the label to the destination, which also serves as our scratch area, lowercasing it + int prevLen = result.size(); + bool simple = true; + result.resize(prevLen + labelLength); + { + QChar *out = result.data() + prevLen; + const QChar *in = domain.constData() + lastIdx; + const QChar *e = in + labelLength; + for (; in < e; ++in, ++out) { + register ushort uc = in->unicode(); + if (uc > 0x7f) simple = false; - break; - } + if (uc >= 'A' && uc <= 'Z') + *out = QChar(uc | 0x20); + else + *out = *in; } - if (simple) - return domain; } - - const bool isIdnEnabled = qt_is_idn_enabled(domain); - int lastIdx = 0; - QString result; - while (1) { - // Nameprep the host. If the labels in the hostname are Punycode - // encoded, we decode them immediately, then nameprep them. - QByteArray label; - toPunycodeHelper(domain.constData() + lastIdx, idx - lastIdx, &label); - result += qt_nameprep(isIdnEnabled ? QUrl::fromPunycode(label) : QString::fromLatin1(label)); - lastIdx = idx + 1; - if (lastIdx < domain.size() + 1) - result += QLatin1Char('.'); - else - break; - idx = domain.indexOf(QLatin1Char('.'), lastIdx); - if (idx == -1) - idx = domain.size(); + + if (simple && labelLength > 6) { + // ACE form domains contain only ASCII characters, but we can't consider them simple + // is this an ACE form? + // the shortest valid ACE domain is 6 characters long (U+0080 would be 1, but it's not allowed) + static const ushort acePrefixUtf16[] = { 'x', 'n', '-', '-' }; + if (memcmp(result.constData() + prevLen, acePrefixUtf16, sizeof acePrefixUtf16) == 0) + simple = false; } - return result; - } else { - return qt_nameprep(domain); + + if (simple) { + // fastest case: this is the common case (non IDN-domains) + // so we're done + if (!qt_check_std3rules(result.constData() + prevLen, labelLength)) + return QString(); + } else { + // Punycode encoding and decoding cannot be done in-place + // That means we need one or two temporaries + qt_nameprep(&result, prevLen); + labelLength = result.length() - prevLen; + register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes + if (toReserve > aceForm.capacity()) + aceForm.reserve(toReserve); + toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm); + + // We use resize()+memcpy() here because we're overwriting the data we've copied + if (isIdnEnabled) { + QString tmp = QUrl::fromPunycode(aceForm.toLatin1()); + if (tmp.isEmpty()) + return QString(); // shouldn't happen, since we've just punycode-encoded it + result.resize(prevLen + tmp.size()); + memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); + } else { + result.resize(prevLen + aceForm.size()); + memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar)); + } + + if (!qt_check_std3rules(aceForm.constData(), aceForm.size())) + return QString(); + } + + + lastIdx = idx + 1; + if (lastIdx < domain.size() + 1) + result += QLatin1Char('.'); + else + break; } + return result; } @@ -3246,12 +3364,27 @@ QUrlPrivate::QUrlPrivate(const QUrlPrivate ©) QString QUrlPrivate::canonicalHost() const { - if (QURL_HASFLAG(stateFlags, HostCanonicalized)) + if (QURL_HASFLAG(stateFlags, HostCanonicalized) || host.isEmpty()) return host; QUrlPrivate *that = const_cast<QUrlPrivate *>(this); QURL_SETFLAG(that->stateFlags, HostCanonicalized); - that->host = qt_from_ACE(host); + if (host.contains(QLatin1Char(':'))) { + // This is an IP Literal, use _IPLiteral to validate + QByteArray ba = host.toLatin1(); + if (!ba.startsWith('[')) { + // surround the IP Literal with [ ] if it's not already done so + ba.reserve(ba.length() + 2); + ba.prepend('['); + ba.append(']'); + } + + const char *ptr = ba.constData(); + if (!_IPLiteral(&ptr)) + that->host.clear(); + } else { + that->host = qt_ACE_do(host, NormalizeAce); + } return that->host; } @@ -3737,7 +3870,10 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const } } - url += QUrl::toAce(host); + if (host.startsWith(QLatin1Char('['))) + url += host.toLatin1(); + else + url += QUrl::toAce(host); if (!(options & QUrl::RemovePort) && port != -1) { url += ':'; url += QString::number(port).toAscii(); @@ -4412,8 +4548,6 @@ void QUrl::setHost(const QString &host) QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized); d->host = host; - if (d->host.contains(QLatin1Char(':'))) - d->host = QLatin1Char('[') + d->host + QLatin1Char(']'); } /*! @@ -5425,9 +5559,9 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu */ QByteArray QUrl::toPunycode(const QString &uc) { - QByteArray output; + QString output; toPunycodeHelper(uc.constData(), uc.size(), &output); - return output; + return output.toLatin1(); } /*! @@ -5528,7 +5662,7 @@ QString QUrl::fromPunycode(const QByteArray &pc) */ QString QUrl::fromAce(const QByteArray &domain) { - return qt_from_ACE(QString::fromLatin1(domain)); + return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce); } /*! @@ -5545,26 +5679,8 @@ QString QUrl::fromAce(const QByteArray &domain) */ QByteArray QUrl::toAce(const QString &domain) { - // IDNA / rfc3490 describes these four delimiters used for - // separating labels in unicode international domain - // names. - QString nameprepped = qt_nameprep(domain); - int lastIdx = 0; - QByteArray result; - for (int i = 0; i < nameprepped.size(); ++i) { - ushort uc = nameprepped.at(i).unicode(); - if (uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61) { - if (lastIdx) - result += '.'; - toPunycodeHelper(nameprepped.constData() + lastIdx, i - lastIdx, &result); - lastIdx = i + 1; - } - } - if (lastIdx) - result += '.'; - toPunycodeHelper(nameprepped.constData() + lastIdx, nameprepped.size() - lastIdx, &result); - - return result; + QString result = qt_ACE_do(domain, ToAceOnly); + return result.toLatin1(); } /*! diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index f7d4208..124b2b3 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -32,7 +32,8 @@ HEADERS += \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ kernel/qsystemsemaphore_p.h \ - kernel/qfunctions_p.h + kernel/qfunctions_p.h \ + kernel/qguard_p.h SOURCES += \ kernel/qabstracteventdispatcher.cpp \ @@ -54,7 +55,7 @@ SOURCES += \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ - kernel/qpointer.cpp + kernel/qpointer.cpp win32 { SOURCES += \ @@ -86,10 +87,14 @@ mac { kernel/qcore_mac.cpp } -unix { +unix:!symbian { SOURCES += \ - kernel/qcrashhandler.cpp + kernel/qcore_unix.cpp \ + kernel/qcrashhandler.cpp \ + kernel/qsharedmemory_unix.cpp \ + kernel/qsystemsemaphore_unix.cpp HEADERS += \ + kernel/qcore_unix_p.h \ kernel/qcrashhandler_p.h contains(QT_CONFIG, glib) { @@ -100,25 +105,34 @@ unix { QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB LIBS +=$$QT_LIBS_GLIB } - - symbian { SOURCES += \ + kernel/qeventdispatcher_unix.cpp + HEADERS += \ + kernel/qeventdispatcher_unix_p.h + + contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) +} + +symbian { + SOURCES += \ + kernel/qcore_unix.cpp \ + kernel/qcrashhandler.cpp \ kernel/qeventdispatcher_symbian.cpp \ kernel/qcore_symbian_p.cpp \ kernel/qsharedmemory_symbian.cpp \ kernel/qsystemsemaphore_symbian.cpp - HEADERS += \ + + HEADERS += \ + kernel/qcore_unix_p.h \ + kernel/qcrashhandler_p.h \ kernel/qeventdispatcher_symbian_p.h \ kernel/qcore_symbian_p.h - } else { - SOURCES += \ - kernel/qeventdispatcher_unix.cpp \ - kernel/qsharedmemory_unix.cpp \ - kernel/qsystemsemaphore_unix.cpp - HEADERS += \ - kernel/qeventdispatcher_unix_p.h - } +} - contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) +vxworks { + SOURCES += \ + kernel/qfunctions_vxworks.cpp + HEADERS += \ + kernel/qfunctions_vxworks.h } diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index a98d005..e2682f5 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -398,20 +398,23 @@ void QAbstractEventDispatcher::closingDown() */ /*! - Sets the event filter \a filter. Returns a pointer to the filter - function previously defined. - - The event filter is a function that receives all messages taken - from the system event loop before the event is dispatched to the - respective target. This includes messages that are not sent to Qt + Replaces the event filter function for this + QAbstractEventDispatcher with \a filter and returns the replaced + event filter function. Only the current event filter function is + called. If you want to use both filter functions, save the + replaced EventFilter in a place where yours can call it. + + The event filter function set here is called for all messages + taken from the system event loop before the event is dispatched to + the respective target, including the messages not meant for Qt objects. - The function can return true to stop the event to be processed by - Qt, or false to continue with the standard event processing. + The event filter function should return true if the message should + be filtered, (i.e. stopped). It should return false to allow + processing the message to continue. - Only one filter can be defined, but the filter can use the return - value to call the previously set event filter. By default, no - filter is set (i.e. the function returns 0). + By default, no event filter function is set (i.e., this function + returns a null EventFilter the first time it is called). */ QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter) { diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index 93815f6..0550dde 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -58,7 +58,7 @@ template <typename T1, typename T2> struct QPair; class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QAbstractEventDispatcher) + Q_DECLARE_PRIVATE(QAbstractEventDispatcher) public: typedef QPair<int, int> TimerInfo; diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 914f44f..5d5d4cc 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,27 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +namespace { + struct DefaultRoleNames : public QHash<int, QByteArray> + { + DefaultRoleNames() { + (*this)[Qt::DisplayRole] = "display"; + (*this)[Qt::DecorationRole] = "decoration"; + (*this)[Qt::EditRole] = "edit"; + (*this)[Qt::ToolTipRole] = "toolTip"; + (*this)[Qt::StatusTipRole] = "statusTip"; + (*this)[Qt::WhatsThisRole] = "whatsThis"; + } + }; +} + +Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames) + +const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames() +{ + return *qDefaultRoleNames(); +} + /*! \internal return true if \a value contains a numerical type @@ -1407,7 +1428,7 @@ QMap<int, QVariant> QAbstractItemModel::itemData(const QModelIndex &index) const QMap<int, QVariant> roles; for (int i = 0; i < Qt::UserRole; ++i) { QVariant variantData = data(index, i); - if (variantData.type() != QVariant::Invalid) + if (variantData.isValid()) roles.insert(i, variantData); } return roles; @@ -1863,6 +1884,37 @@ QSize QAbstractItemModel::span(const QModelIndex &) const } /*! + \since 4.6 + + Sets the model's role names to \a roleNames. + + This function is provided to allow mapping of role identifiers to + role property names in Declarative UI. This function must be called + before the model is used. Modifying the role names after the model + has been set may result in undefined behaviour. + + \sa roleNames() +*/ +void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames) +{ + Q_D(QAbstractItemModel); + d->roleNames = roleNames; +} + +/*! + \since 4.6 + + Returns the model's role names. + + \sa setRoleNames() +*/ +const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const +{ + Q_D(const QAbstractItemModel); + return d->roleNames; +} + +/*! Called to let the model know that it should submit whatever it has cached to the permanent storage. Typically used for row editing. @@ -2278,7 +2330,8 @@ void QAbstractItemModel::endRemoveColumns() \note The view to which the model is attached to will be reset as well. When a model is reset it means that any previous data reported from the - model is now invalid and has to be queried for again. + model is now invalid and has to be queried for again. This also means + that the current item and any selected items will become invalid. When a model radically changes its data it can sometimes be easier to just call this function rather than emit dataChanged() to inform other diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h index 90d04cd..a6bbff4 100644 --- a/src/corelib/kernel/qabstractitemmodel.h +++ b/src/corelib/kernel/qabstractitemmodel.h @@ -220,6 +220,8 @@ public: Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; virtual QSize span(const QModelIndex &index) const; + const QHash<int,QByteArray> &roleNames() const; + #ifdef Q_NO_USING_KEYWORD inline QObject *parent() const { return QObject::parent(); } #else @@ -282,8 +284,10 @@ protected: void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; + void setRoleNames(const QHash<int,QByteArray> &roleNames); + private: - Q_DECLARE_SCOPED_PRIVATE(QAbstractItemModel) + Q_DECLARE_PRIVATE(QAbstractItemModel) Q_DISABLE_COPY(QAbstractItemModel) }; diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index c047f95..6a29723 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QAbstractItemModel) public: - QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {} + QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {} void removePersistentIndexData(QPersistentModelIndexData *data); void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex &parent, int first, int last); @@ -144,6 +144,9 @@ public: } persistent; Qt::DropActions supportedDragActions; + + QHash<int,QByteArray> roleNames; + static const QHash<int,QByteArray> &defaultRoleNames(); }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index c681b1f..c7264cf 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 453c3d3..391774f 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp new file mode 100644 index 0000000..9134622 --- /dev/null +++ b/src/corelib/kernel/qcore_unix.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcore_unix_p.h" + +#ifndef Q_OS_VXWORKS +# include <sys/select.h> +# include <sys/time.h> +#else +# include <selectLib.h> +#endif + +#include <stdlib.h> + +#ifdef Q_OS_MAC +#include <mach/mach_time.h> +#endif + +#if !defined(QT_NO_CLOCK_MONOTONIC) +# if defined(QT_BOOTSTRAPPED) +# define QT_NO_CLOCK_MONOTONIC +# endif +#endif + +QT_BEGIN_NAMESPACE + +bool qt_gettime_is_monotonic() +{ +#if (_POSIX_MONOTONIC_CLOCK-0 > 0) || defined(Q_OS_MAC) + return true; +#else + static int returnValue = 0; + + if (returnValue == 0) { +# if (_POSIX_MONOTONIC_CLOCK-0 < 0) + returnValue = -1; +# elif (_POSIX_MONOTONIC_CLOCK == 0) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + returnValue = (x >= 200112L) ? 1 : -1; +# endif + } + + return returnValue != -1; +#endif +} + +timeval qt_gettime() +{ + timeval tv; +#if defined(Q_OS_MAC) + static mach_timebase_info_data_t info = {0,0}; + if (info.denom == 0) + mach_timebase_info(&info); + + uint64_t cpu_time = mach_absolute_time(); + uint64_t nsecs = cpu_time * (info.numer / info.denom); + tv.tv_sec = nsecs / 1000000000ull; + tv.tv_usec = (nsecs / 1000) - (tv.tv_sec * 1000000); + return tv; +#elif (_POSIX_MONOTONIC_CLOCK-0 > 0) + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +#else +# if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) + if (qt_gettime_is_monotonic()) { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; + } +# endif + // use gettimeofday + ::gettimeofday(&tv, 0); + return tv; +#endif +} + +static inline bool time_update(struct timeval *tv, const struct timeval &start, + const struct timeval &timeout) +{ + if (!qt_gettime_is_monotonic()) { + // we cannot recalculate the timeout without a monotonic clock as the time may have changed + return false; + } + + // clock source is monotonic, so we can recalculate how much timeout is left + struct timeval now = qt_gettime(); + *tv = timeout + start - now; + return true; +} + +int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *orig_timeout) +{ + if (!orig_timeout) { + // no timeout -> block forever + register int ret; + EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0)); + return ret; + } + + timeval start = qt_gettime(); + timeval timeout = *orig_timeout; + + // loop and recalculate the timeout as needed + int ret; + forever { + ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout); + if (ret != -1 || errno != EINTR) + return ret; + + // recalculate the timeout + if (!time_update(&timeout, start, *orig_timeout)) { + // clock reset, fake timeout error + return 0; + } + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h new file mode 100644 index 0000000..9a6069d --- /dev/null +++ b/src/corelib/kernel/qcore_unix_p.h @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCORE_UNIX_P_H +#define QCORE_UNIX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt code on Unix. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplatformdefs.h" + +#ifndef Q_OS_UNIX +# error "qcore_unix_p.h included on a non-Unix system" +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <sys/wait.h> +#include <errno.h> +#include <fcntl.h> + +#if defined(Q_OS_VXWORKS) +# include <ioLib.h> +#endif + +struct sockaddr; + +#if defined(Q_OS_LINUX) && defined(O_CLOEXEC) +# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1 +QT_BEGIN_NAMESPACE +namespace QtLibcSupplement { + inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int) + { errno = ENOSYS; return -1; } + inline int dup3(int, int, int) + { errno = ENOSYS; return -1; } + inline int pipe2(int [], int ) + { errno = ENOSYS; return -1; } +} +QT_END_NAMESPACE +using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement); + +#else +# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0 +#endif + +#define EINTR_LOOP(var, cmd) \ + do { \ + var = cmd; \ + } while (var == -1 && errno == EINTR) + +QT_BEGIN_NAMESPACE + +// Internal operator functions for timevals +inline timeval &normalizedTimeval(timeval &t) +{ + while (t.tv_usec > 1000000l) { + ++t.tv_sec; + t.tv_usec -= 1000000l; + } + while (t.tv_usec < 0l) { + --t.tv_sec; + t.tv_usec += 1000000l; + } + return t; +} +inline bool operator<(const timeval &t1, const timeval &t2) +{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } +inline bool operator==(const timeval &t1, const timeval &t2) +{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } +inline timeval &operator+=(timeval &t1, const timeval &t2) +{ + t1.tv_sec += t2.tv_sec; + t1.tv_usec += t2.tv_usec; + return normalizedTimeval(t1); +} +inline timeval operator+(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec + t2.tv_sec; + tmp.tv_usec = t1.tv_usec + t2.tv_usec; + return normalizedTimeval(tmp); +} +inline timeval operator-(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); + tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000); + return normalizedTimeval(tmp); +} +inline timeval operator*(const timeval &t1, int mul) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec * mul; + tmp.tv_usec = t1.tv_usec * mul; + return normalizedTimeval(tmp); +} + +// don't call QT_OPEN or ::open +// call qt_safe_open +static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) +{ +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + register int fd; + EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode)); + + // unknown flags are ignored, so we have no way of verifying if + // O_CLOEXEC was accepted + if (fd != -1) + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + return fd; +} +#undef QT_OPEN +#define QT_OPEN qt_safe_open + +#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks +// don't call ::pipe +// call qt_safe_pipe +static inline int qt_safe_pipe(int pipefd[2], int flags = 0) +{ +#ifdef O_CLOEXEC + Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0); +#else + Q_ASSERT((flags & ~O_NONBLOCK) == 0); +#endif + + register int ret; +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC) + // use pipe2 + flags |= O_CLOEXEC; + ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR + if (ret == 0 || errno != ENOSYS) + return ret; +#endif + + ret = ::pipe(pipefd); + if (ret == -1) + return -1; + + ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC); + ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); + + // set non-block too? + if (flags & O_NONBLOCK) { + ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK); + ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK); + } + + return 0; +} + +#endif // Q_OS_VXWORKS + +// don't call dup or fcntl(F_DUPFD) +static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC) +{ + Q_ASSERT(flags == FD_CLOEXEC || flags == 0); + + register int ret; +#ifdef F_DUPFD_CLOEXEC + // use this fcntl + if (flags & FD_CLOEXEC) { + ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast); + if (ret != -1 || errno != EINVAL) + return ret; + } +#endif + + // use F_DUPFD + ret = ::fcntl(oldfd, F_DUPFD, atleast); + + if (flags && ret != -1) + ::fcntl(ret, F_SETFD, flags); + return ret; +} + +// don't call dup2 +// call qt_safe_dup2 +static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC) +{ + Q_ASSERT(flags == FD_CLOEXEC || flags == 0); + + register int ret; +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC) + // use dup3 + if (flags & FD_CLOEXEC) { + EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC)); + if (ret == 0 || errno != ENOSYS) + return ret; + } +#endif + EINTR_LOOP(ret, ::dup2(oldfd, newfd)); + if (ret == -1) + return -1; + + if (flags) + ::fcntl(newfd, F_SETFD, flags); + return 0; +} + +static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen) +{ + qint64 ret = 0; + EINTR_LOOP(ret, QT_READ(fd, data, maxlen)); + return ret; +} +#undef QT_READ +#define QT_READ qt_safe_read + +static inline qint64 qt_safe_write(int fd, const void *data, qint64 len) +{ + qint64 ret = 0; + EINTR_LOOP(ret, QT_WRITE(fd, data, len)); + return ret; +} +#undef QT_WRITE +#define QT_WRITE qt_safe_write + +static inline int qt_safe_close(int fd) +{ + register int ret; + EINTR_LOOP(ret, QT_CLOSE(fd)); + return ret; +} +#undef QT_CLOSE +#define QT_CLOSE qt_safe_close + +// Open C does not (yet?) implement these on Symbian OS and VxWorks doesn't have processes +#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_VXWORKS) +static inline int qt_safe_execve(const char *filename, char *const argv[], + char *const envp[]) +{ + register int ret; + EINTR_LOOP(ret, ::execve(filename, argv, envp)); + return ret; +} + +static inline int qt_safe_execv(const char *path, char *const argv[]) +{ + register int ret; + EINTR_LOOP(ret, ::execv(path, argv)); + return ret; +} + +static inline int qt_safe_execvp(const char *file, char *const argv[]) +{ + register int ret; + EINTR_LOOP(ret, ::execvp(file, argv)); + return ret; +} +#endif + +#ifndef Q_OS_VXWORKS // no processes on VxWorks +static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) +{ + register int ret; + EINTR_LOOP(ret, ::waitpid(pid, status, options)); + return ret; +} + +#endif // Q_OS_VXWORKS + +#if !defined(_POSIX_MONOTONIC_CLOCK) +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + +bool qt_gettime_is_monotonic(); +timeval qt_gettime(); +Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *tv); + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 90d8f2f..4a1da35 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -61,6 +61,7 @@ #include <private/qthread_p.h> #include <qlibraryinfo.h> #include <private/qfactoryloader_p.h> +#include <private/qfunctions_p.h> #ifdef Q_OS_SYMBIAN # include <exception> @@ -88,6 +89,10 @@ # include <locale.h> #endif +#ifdef Q_OS_VXWORKS +# include <taskLib.h> +#endif + QT_BEGIN_NAMESPACE class QLockedMutexUnlocker @@ -1733,6 +1738,12 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, return result; } +// Declared in qglobal.h +QString qtTrId(const char *id, int n) +{ + return QCoreApplication::translate(0, id, 0, QCoreApplication::UnicodeUTF8, n); +} + bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator) { return QCoreApplication::self @@ -1828,21 +1839,8 @@ QString QCoreApplication::applicationFilePath() if (!d->cachedApplicationFilePath.isNull()) return d->cachedApplicationFilePath; -#if defined( Q_WS_WIN ) - QFileInfo filePath; - QT_WA({ - wchar_t module_name[MAX_PATH+1]; - GetModuleFileNameW(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - filePath = QString::fromUtf16((ushort *)module_name); - }, { - char module_name[MAX_PATH+1]; - GetModuleFileNameA(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - filePath = QString::fromLocal8Bit(module_name); - }); - - d->cachedApplicationFilePath = filePath.filePath(); +#if defined(Q_WS_WIN) + d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath(); return d->cachedApplicationFilePath; #elif defined(Q_WS_MAC) QString qAppFileName_str = qAppFileName(); @@ -1928,8 +1926,9 @@ qint64 QCoreApplication::applicationPid() { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) return GetCurrentProcessId(); +#elif defined(Q_OS_VXWORKS) + return (pid_t) taskIdCurrent; #else - // UNIX return getpid(); #endif } @@ -2002,13 +2001,13 @@ QStringList QCoreApplication::arguments() return list; } #ifdef Q_OS_WIN - QString cmdline = QT_WA_INLINE(QString::fromUtf16((unsigned short *)GetCommandLineW()), QString::fromLocal8Bit(GetCommandLineA())); + QString cmdline = QString::fromWCharArray(GetCommandLine()); #if defined(Q_OS_WINCE) wchar_t tempFilename[MAX_PATH+1]; - if (GetModuleFileNameW(0, tempFilename, MAX_PATH)) { + if (GetModuleFileName(0, tempFilename, MAX_PATH)) { tempFilename[MAX_PATH] = 0; - cmdline.prepend(QLatin1Char('\"') + QString::fromUtf16((unsigned short *)tempFilename) + QLatin1String("\" ")); + cmdline.prepend(QLatin1Char('\"') + QString::fromWCharArray(tempFilename) + QLatin1String("\" ")); } #endif // Q_OS_WINCE @@ -2315,21 +2314,37 @@ void QCoreApplication::removeLibraryPath(const QString &path) /*! \fn EventFilter QCoreApplication::setEventFilter(EventFilter filter) - Sets the event filter \a filter. Returns a pointer to the filter - function previously defined. - - The event filter is a function that is called for every message - received in all threads. This does \e not include messages to + Replaces the event filter function for the QCoreApplication with + \a filter and returns the pointer to the replaced event filter + function. Only the current event filter function is called. If you + want to use both filter functions, save the replaced EventFilter + in a place where yours can call it. + + The event filter function set here is called for all messages + received by all threads meant for all Qt objects. It is \e not + called for messages that are not meant for Qt objects. + + The event filter function should return true if the message should + be filtered, (i.e. stopped). It should return false to allow + processing the message to continue. + + By default, no event filter function is set (i.e., this function + returns a null EventFilter the first time it is called). + + \note The filter function set here receives native messages, + i.e. MSG or XEvent structs, that are going to Qt objects. It is + called by QCoreApplication::filterEvent(). If the filter function + returns false to indicate the message should be processed further, + the native message can then be translated into a QEvent and + handled by the standard Qt \l{QEvent} {event} filering, e.g. + QObject::installEventFilter(). + + \note The filter function set here is different form the filter + function set via QAbstractEventDispatcher::setEventFilter(), which + gets all messages received by its thread, even messages meant for objects that are not handled by Qt. - The function can return true to stop the event to be processed by - Qt, or false to continue with the standard event processing. - - Only one filter can be defined, but the filter can use the return - value to call the previously set event filter. By default, no - filter is set (i.e., the function returns 0). - - \sa installEventFilter() + \sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter() */ QCoreApplication::EventFilter QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter) diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 60b0882..48e65a7 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -76,7 +76,7 @@ class Q_CORE_EXPORT QCoreApplication : public QObject Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName) Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain) - Q_DECLARE_SCOPED_PRIVATE(QCoreApplication) + Q_DECLARE_PRIVATE(QCoreApplication) public: QCoreApplication(int &argc, char **argv); ~QCoreApplication(); diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 7a35340..bf5716a 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -45,14 +45,15 @@ #include "qt_windows.h" #include "qvector.h" #include "qmutex.h" +#include "qfileinfo.h" #include "qcorecmdlineargs_p.h" #include <private/qthread_p.h> #include <ctype.h> QT_BEGIN_NAMESPACE -char appFileName[MAX_PATH+1]; // application file name -char theAppName[MAX_PATH+1]; // application name +char appFileName[MAX_PATH]; // application file name +char theAppName[MAX_PATH]; // application name HINSTANCE appInst = 0; // handle to app instance HINSTANCE appPrevInst = 0; // handle to prev app instance int appCmdShow = 0; @@ -73,48 +74,69 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho return appCmdShow; } +Q_CORE_EXPORT QString qAppFileName() // get application file name +{ + // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths + // up to, and including MAX_PATH size perfectly fine with string termination, as well + // as easily detect if the file path is indeed larger than MAX_PATH, in which case we + // need to use the heap instead. This is a work-around, since contrary to what the + // MSDN documentation states, GetModuleFileName sometimes doesn't set the + // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if + // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH. + // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal + // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use + // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok). + wchar_t buffer[MAX_PATH + 2]; + DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1); + buffer[MAX_PATH + 1] = 0; + + if (v == 0) + return QString(); + else if (v <= MAX_PATH) + return QString::fromWCharArray(buffer); + + // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap + wchar_t *b = 0; + int i = 1; + size_t size; + do { + ++i; + size = MAX_PATH * i; + b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t))); + if (b) + v = GetModuleFileName(NULL, b, size); + } while (b && v == size); + + if (b) + *(b + size) = 0; + QString res = QString::fromWCharArray(b); + free(b); + + return res; +} void set_winapp_name() { static bool already_set = false; if (!already_set) { already_set = true; -#ifndef Q_OS_WINCE - GetModuleFileNameA(0, appFileName, sizeof(appFileName)); - appFileName[sizeof(appFileName)-1] = 0; -#else - QString afm; - afm.resize(sizeof(appFileName)); - afm.resize(GetModuleFileName(0, (wchar_t *) (afm.unicode()), sizeof(appFileName))); - memcpy(appFileName, afm.toLatin1(), sizeof(appFileName)); -#endif - const char *p = strrchr(appFileName, '\\'); // skip path - if (p) - memcpy(theAppName, p+1, qstrlen(p)); - int l = qstrlen(theAppName); - if ((l > 4) && !qstricmp(theAppName + l - 4, ".exe")) - theAppName[l-4] = '\0'; // drop .exe extension - - if (appInst == 0) { - QT_WA({ - appInst = GetModuleHandle(0); - }, { - appInst = GetModuleHandleA(0); - }); - } - } -} -Q_CORE_EXPORT QString qAppFileName() // get application file name -{ - return QString::fromLatin1(appFileName); + QString moduleName = qAppFileName(); + + QByteArray filePath = moduleName.toLocal8Bit(); + QByteArray fileName = QFileInfo(moduleName).baseName().toLocal8Bit(); + + memcpy(appFileName, filePath.constData(), filePath.length()); + memcpy(theAppName, fileName.constData(), fileName.length()); + + if (appInst == 0) + appInst = GetModuleHandle(0); + } } QString QCoreApplicationPrivate::appName() const { - if (!theAppName[0]) - set_winapp_name(); - return QString::fromLatin1(theAppName); + return QFileInfo(qAppFileName()).baseName(); } class QWinMsgHandlerCriticalSection @@ -145,15 +167,11 @@ Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str) str = "(null)"; staticCriticalSection.lock(); - QT_WA({ - QString s(QString::fromLocal8Bit(str)); - s += QLatin1Char('\n'); - OutputDebugStringW((TCHAR*)s.utf16()); - }, { - QByteArray s(str); - s += '\n'; - OutputDebugStringA(s.data()); - }) + + QString s(QString::fromLocal8Bit(str)); + s += QLatin1Char('\n'); + OutputDebugString((wchar_t*)s.utf16()); + staticCriticalSection.unlock(); } @@ -262,7 +280,7 @@ QT_END_INCLUDE_NAMESPACE // The values below should never change. Note that none of the usual // WM_...FIRST & WM_...LAST values are in the list, as they normally have other // WM_... representations -struct { +struct KnownWM { uint WM; const char* str; } knownWM[] = @@ -564,7 +582,7 @@ struct { { 0,0 }}; // End of known messages // Looks up the WM_ message in the table above -const char* findWMstr(uint msg) +static const char* findWMstr(uint msg) { uint i = 0; const char* result = 0; diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h index c0dd813..a012b4e 100644 --- a/src/corelib/kernel/qcorecmdlineargs_p.h +++ b/src/corelib/kernel/qcorecmdlineargs_p.h @@ -135,9 +135,9 @@ static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this mi QStringList args; int argc = 0; - QVector<ushort*> argv = qWinCmdLine<ushort>((ushort*)cmdLine.utf16(), cmdLine.length(), argc); + QVector<wchar_t*> argv = qWinCmdLine<wchar_t>((wchar_t *)cmdLine.utf16(), cmdLine.length(), argc); for (int a = 0; a < argc; ++a) { - args << QString::fromUtf16(argv[a]); + args << QString::fromWCharArray(argv[a]); } return args; @@ -147,10 +147,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[]) { Q_UNUSED(argc) Q_UNUSED(argv) - QString cmdLine = QT_WA_INLINE( - QString::fromUtf16((unsigned short*)GetCommandLineW()), - QString::fromLocal8Bit(GetCommandLineA()) - ); + QString cmdLine = QString::fromWCharArray(GetCommandLine()); return qWinCmdArgs(cmdLine); } diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 0ffd6f7..72bad5f 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -221,14 +221,13 @@ QT_BEGIN_NAMESPACE \value WindowStateChange The \l{QWidget::windowState()}{window's state} (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent). \value WindowTitleChange The window title has changed. \value WindowUnblocked The window is unblocked after a modal dialog exited. + \value Wrapped The event is a wrapper for, i.e., contains, another event (QWrappedEvent). \value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows. \value KeyboardLayoutChange The keyboard layout has changed. \value DynamicPropertyChange A dynamic property was added, changed or removed from the object. \value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent) \value TouchUpdate Touch-screen event (QTouchEvent) \value TouchEnd End of touch-event sequence (QTouchEvent) - \value Gesture A gesture has occured. - \value GraphicsSceneGesture A gesture has occured on a graphics scene. User events should have values between \c User and \c{MaxUser}: @@ -271,9 +270,9 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal - \omitvalue Wrapped \omitvalue Signal \omitvalue SymbianDeferredFocusChanged + \omitvalue NativeGesture */ /*! diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index efa9fd3..42e3d24 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -276,8 +276,7 @@ public: TouchUpdate = 195, TouchEnd = 196, - Gesture = 197, - GraphicsSceneGesture = 198, + NativeGesture = 197, // Internal for platform gesture support RequestSoftwareInputPanel = 199, CloseSoftwareInputPanel = 200, diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 7610631..2bbe560 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -263,6 +263,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; g_source_set_can_recurse(&timerSource->source, true); + g_source_set_priority(&timerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&timerSource->source, mainContext); } diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index bcb655b..80ec9fa 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -67,7 +67,7 @@ class QEventDispatcherGlibPrivate; class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QEventDispatcherGlib) + Q_DECLARE_PRIVATE(QEventDispatcherGlib) public: explicit QEventDispatcherGlib(QObject *parent = 0); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index e876843..02edfb0 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 310d74d..28fee9e 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -184,7 +184,7 @@ private: class QSelectThread : public QThread { - Q_DECLARE_SCOPED_PRIVATE(QThread) + Q_DECLARE_PRIVATE(QThread) public: QSelectThread(); @@ -218,7 +218,7 @@ public: // from CActiveScheduler class Q_CORE_EXPORT QEventDispatcherSymbian : public QAbstractEventDispatcher { - Q_DECLARE_SCOPED_PRIVATE(QAbstractEventDispatcher) + Q_DECLARE_PRIVATE(QAbstractEventDispatcher) public: QEventDispatcherSymbian(QObject *parent = 0); diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 67f2cd0..78a2b0b 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -49,11 +49,22 @@ #include "qeventdispatcher_unix_p.h" #include <private/qthread_p.h> #include <private/qcoreapplication_p.h> +#include <private/qcore_unix_p.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> +// VxWorks doesn't correctly set the _POSIX_... options +#if defined(Q_OS_VXWORKS) +# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) +# undef _POSIX_MONOTONIC_CLOCK +# define _POSIX_MONOTONIC_CLOCK 1 +# endif +# include <pipeDrv.h> +# include <selectLib.h> +#endif + #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) # include <sys/times.h> #endif @@ -76,6 +87,7 @@ static void signalHandler(int sig) } +#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS) static void initThreadPipeFD(int fd) { int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -90,25 +102,52 @@ static void initThreadPipeFD(int fd) if (ret == -1) perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe"); } - +#endif QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { extern Qt::HANDLE qt_application_thread_id; mainThread = (QThread::currentThreadId() == qt_application_thread_id); + bool pipefail = false; // initialize the common parts of the event loop -#ifdef Q_OS_INTEGRITY +#if defined(Q_OS_INTEGRITY) // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead - if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) + if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + initThreadPipeFD(thread_pipe[1]); + } +#elif defined(Q_OS_VXWORKS) + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + // make sure there is no pipe with this name + pipeDevDelete(name, true); + // create the pipe + if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device"); + pipefail = true; + } else { + if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + thread_pipe[1] = thread_pipe[0]; + } + } #else - if (pipe(thread_pipe) == -1) + if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } #endif - initThreadPipeFD(thread_pipe[0]); - initThreadPipeFD(thread_pipe[1]); + if (pipefail) + qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); sn_highest = -1; @@ -117,9 +156,18 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { +#if defined(Q_OS_VXWORKS) + close(thread_pipe[0]); + + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + pipeDevDelete(name, true); +#else // cleanup the common parts of the event loop close(thread_pipe[0]); close(thread_pipe[1]); +#endif // cleanup timers qDeleteAll(timerList); @@ -224,9 +272,15 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, // select doesn't immediately return next time int nevents = 0; if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) { +#if defined(Q_OS_VXWORKS) + char c[16]; + ::read(thread_pipe[0], c, sizeof(c)); + ::ioctl(thread_pipe[0], FIOFLUSH, 0); +#else char c[16]; while (::read(thread_pipe[0], c, sizeof(c)) > 0) ; +#endif if (!wakeUps.testAndSetRelease(1, 0)) { // hopefully, this is dead code qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!"); @@ -257,18 +311,10 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, QTimerInfoList::QTimerInfoList() { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) - useMonotonicTimers = false; - -# if (_POSIX_MONOTONIC_CLOCK == 0) - // detect if the system support monotonic timers - long x = sysconf(_SC_MONOTONIC_CLOCK); - useMonotonicTimers = x != -1; -# endif + currentTime = qt_gettime(); - getTime(currentTime); - - if (!useMonotonicTimers) { +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) + if (!qt_gettime_is_monotonic()) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = currentTime; @@ -284,9 +330,6 @@ QTimerInfoList::QTimerInfoList() ticksPerSecond = 0; msPerTick = 0; } -#else - // using monotonic timers unconditionally - getTime(currentTime); #endif firstTimerInfo = currentTimerInfo = 0; @@ -294,11 +337,24 @@ QTimerInfoList::QTimerInfoList() timeval QTimerInfoList::updateCurrentTime() { - getTime(currentTime); - return currentTime; + return (currentTime = qt_gettime()); } -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) +#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) + +template <> +timeval qAbs(const timeval &t) +{ + timeval tmp = t; + if (tmp.tv_sec < 0) { + tmp.tv_sec = -tmp.tv_sec - 1; + tmp.tv_usec -= 1000000; + } + if (tmp.tv_sec == 0 && tmp.tv_usec < 0) { + tmp.tv_usec = -tmp.tv_usec; + } + return normalizedTimeval(tmp); +} /* Returns true if the real time clock has changed by more than 10% @@ -309,60 +365,35 @@ timeval QTimerInfoList::updateCurrentTime() */ bool QTimerInfoList::timeChanged(timeval *delta) { - tms unused; + struct tms unused; clock_t currentTicks = times(&unused); - int elapsedTicks = currentTicks - previousTicks; + clock_t elapsedTicks = currentTicks - previousTicks; timeval elapsedTime = currentTime - previousTime; - int elapsedMsecTicks = (elapsedTicks * 1000) / ticksPerSecond; - int deltaMsecs = (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000) - - elapsedMsecTicks; - if (delta) { - delta->tv_sec = deltaMsecs / 1000; - delta->tv_usec = (deltaMsecs % 1000) * 1000; - } + timeval elapsedTimeTicks; + elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond; + elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000; + + timeval dummy; + if (!delta) + delta = &dummy; + *delta = elapsedTime - elapsedTimeTicks; + previousTicks = currentTicks; previousTime = currentTime; // If tick drift is more than 10% off compared to realtime, we assume that the clock has // been set. Of course, we have to allow for the tick granularity as well. - - return (qAbs(deltaMsecs) - msPerTick) * 10 > elapsedMsecTicks; -} - -void QTimerInfoList::getTime(timeval &t) -{ -#if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED) - if (useMonotonicTimers) { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; - return; - } -#endif - - gettimeofday(&t, 0); - // NTP-related fix - while (t.tv_usec >= 1000000l) { - t.tv_usec -= 1000000l; - ++t.tv_sec; - } - while (t.tv_usec < 0l) { - if (t.tv_sec > 0l) { - t.tv_usec += 1000000l; - --t.tv_sec; - } else { - t.tv_usec = 0l; - break; - } - } + timeval tickGranularity; + tickGranularity.tv_sec = 0; + tickGranularity.tv_usec = msPerTick * 1000; + return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10); } void QTimerInfoList::repairTimersIfNeeded() { - if (useMonotonicTimers) + if (qt_gettime_is_monotonic()) return; timeval delta; if (timeChanged(&delta)) @@ -371,14 +402,6 @@ void QTimerInfoList::repairTimersIfNeeded() #else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED) -void QTimerInfoList::getTime(timeval &t) -{ - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t.tv_sec = ts.tv_sec; - t.tv_usec = ts.tv_nsec / 1000; -} - void QTimerInfoList::repairTimersIfNeeded() { } @@ -407,7 +430,7 @@ void QTimerInfoList::timerRepair(const timeval &diff) // repair all timers for (int i = 0; i < size(); ++i) { register QTimerInfo *t = at(i); - t->timeout = t->timeout - diff; + t->timeout = t->timeout + diff; } } @@ -607,25 +630,7 @@ QEventDispatcherUNIX::~QEventDispatcherUNIX() int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout) { - Q_D(QEventDispatcherUNIX); - if (timeout) { - // handle the case where select returns with a timeout, too - // soon. - timeval tvStart = d->timerList.currentTime; - timeval tvCurrent = tvStart; - timeval originalTimeout = *timeout; - - int nsel; - do { - timeval tvRest = originalTimeout + tvStart - tvCurrent; - nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest); - d->timerList.getTime(tvCurrent); - } while (nsel == 0 && (tvCurrent - tvStart) < originalTimeout); - - return nsel; - } - - return ::select(nfds, readfds, writefds, exceptfds, timeout); + return ::qt_safe_select(nfds, readfds, writefds, exceptfds, timeout); } /*! diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index c52965a..a52af00 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -56,55 +56,20 @@ #include "QtCore/qabstracteventdispatcher.h" #include "QtCore/qlist.h" #include "private/qabstracteventdispatcher_p.h" +#include "private/qcore_unix_p.h" #include "private/qpodlist_p.h" #include "QtCore/qvarlengtharray.h" -#include <sys/types.h> -#include <sys/time.h> -#if !defined(Q_OS_HPUX) || defined(__ia64) -#include <sys/select.h> +#if defined(Q_OS_VXWORKS) +# include <sys/times.h> +#else +# include <sys/time.h> +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include <sys/select.h> +# endif #endif -#include <unistd.h> QT_BEGIN_NAMESPACE -#if !defined(_POSIX_MONOTONIC_CLOCK) -# define _POSIX_MONOTONIC_CLOCK -1 -#endif - -// Internal operator functions for timevals -inline bool operator<(const timeval &t1, const timeval &t2) -{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } -inline bool operator==(const timeval &t1, const timeval &t2) -{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } -inline timeval &operator+=(timeval &t1, const timeval &t2) -{ - t1.tv_sec += t2.tv_sec; - if ((t1.tv_usec += t2.tv_usec) >= 1000000l) { - ++t1.tv_sec; - t1.tv_usec -= 1000000l; - } - return t1; -} -inline timeval operator+(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec + t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) { - ++tmp.tv_sec; - tmp.tv_usec -= 1000000l; - } - return tmp; -} -inline timeval operator-(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec - t2.tv_sec; - if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) { - --tmp.tv_sec; - tmp.tv_usec += 1000000l; - } - return tmp; -} // internal timer info struct QTimerInfo { @@ -117,9 +82,7 @@ struct QTimerInfo { class QTimerInfoList : public QList<QTimerInfo*> { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) - bool useMonotonicTimers; - +#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED) timeval previousTime; clock_t previousTicks; int ticksPerSecond; @@ -134,8 +97,6 @@ class QTimerInfoList : public QList<QTimerInfo*> public: QTimerInfoList(); - void getTime(timeval &t); - timeval currentTime; timeval updateCurrentTime(); @@ -181,7 +142,7 @@ class QEventDispatcherUNIXPrivate; class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QEventDispatcherUNIX) + Q_DECLARE_PRIVATE(QEventDispatcherUNIX) public: explicit QEventDispatcherUNIX(QObject *parent = 0); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index cb1549c..33b66f5 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -355,8 +355,7 @@ QEventDispatcherWin32Private::QEventDispatcherWin32Private() { resolveTimerAPI(); - wakeUpNotifier.setHandle(QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0), - CreateEventA(0, FALSE, FALSE, 0))); + wakeUpNotifier.setHandle(CreateEvent(0, FALSE, FALSE, 0)); if (!wakeUpNotifier.handle()) qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed"); } @@ -367,13 +366,8 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private() CloseHandle(wakeUpNotifier.handle()); if (internalHwnd) DestroyWindow(internalHwnd); - QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc)); -#if !defined(Q_OS_WINCE) - UnregisterClassA(className.constData(), qWinAppInst()); -#else - UnregisterClassW(reinterpret_cast<const wchar_t *> (QString::fromLatin1(className.constData()).utf16()) - , qWinAppInst()); -#endif + QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + UnregisterClass((wchar_t*)className.utf16(), qWinAppInst()); } void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) @@ -382,18 +376,24 @@ void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen QCoreApplication::sendEvent(wen, &event); } - +// ### Qt 5: remove Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { - QT_WA({ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } , - { return PeekMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); }); + return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } +// ### Qt 5: remove Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - QT_WA({ return PostMessage(hWnd, msg, wParam, lParam); } , - { return PostMessageA(hWnd, msg, wParam, lParam); }); + return PostMessage(hWnd, msg, wParam, lParam); +} + +// ### Qt 5: remove +Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, + UINT wMsgFilterMax) +{ + return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax); } // This function is called by a workerthread @@ -443,10 +443,10 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) #ifdef GWLP_USERDATA QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLongPtrA(hwnd, GWLP_USERDATA); + (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #else QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLongA(hwnd, GWL_USERDATA); + (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA); #endif if (eventDispatcher) { QEventDispatcherWin32Private *d = eventDispatcher->d_func(); @@ -494,54 +494,35 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) { - HINSTANCE hi = qWinAppInst(); -#if defined(Q_OS_WINCE) + // make sure that multiple Qt's can coexist in the same process + QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + WNDCLASS wc; -#else - WNDCLASSA wc; -#endif wc.style = 0; wc.lpfnWndProc = qt_internal_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = hi; + wc.hInstance = qWinAppInst(); wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; + wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16()); - // make sure that multiple Qt's can coexist in the same process - QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc)); -#if defined(Q_OS_WINCE) - QString tmp = QString::fromLatin1(className.data()); - wc.lpszClassName = reinterpret_cast<const wchar_t *> (tmp.utf16()); RegisterClass(&wc); HWND wnd = CreateWindow(wc.lpszClassName, // classname - wc.lpszClassName, // window name - 0, // style - 0, 0, 0, 0, // geometry - 0, // parent - 0, // menu handle - hi, // application - 0); // windows creation data. -#else - wc.lpszClassName = className.constData(); - RegisterClassA(&wc); - HWND wnd = CreateWindowA(wc.lpszClassName, // classname - wc.lpszClassName, // window name - 0, // style - 0, 0, 0, 0, // geometry - 0, // parent - 0, // menu handle - hi, // application - 0); // windows creation data. -#endif - + wc.lpszClassName, // window name + 0, // style + 0, 0, 0, 0, // geometry + 0, // parent + 0, // menu handle + qWinAppInst(), // application + 0); // windows creation data. #ifdef GWLP_USERDATA - SetWindowLongPtrA(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher); + SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher); #else - SetWindowLongA(wnd, GWL_USERDATA, (LONG)eventDispatcher); + SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher); #endif if (!wnd) { @@ -690,7 +671,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) haveMessage = true; msg = d->queuedSocketEvents.takeFirst(); } else { - haveMessage = winPeekMessage(&msg, 0, 0, 0, PM_REMOVE); + haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) && ((msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) @@ -738,11 +719,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) if (!filterEvent(&msg)) { TranslateMessage(&msg); - QT_WA({ - DispatchMessage(&msg); - } , { - DispatchMessageA(&msg); - }); + DispatchMessage(&msg); } } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); @@ -781,7 +758,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) bool QEventDispatcherWin32::hasPendingEvents() { MSG msg; - return qGlobalPostedEventsCount() || winPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); + return qGlobalPostedEventsCount() || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); } void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 37578a0..ca5dbf8 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -67,7 +67,7 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QEventDispatcherWin32) + Q_DECLARE_PRIVATE(QEventDispatcherWin32) void createInternalHwnd(); friend class QGuiEventDispatcherWin32; diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h index e14e352..60d00df 100644 --- a/src/corelib/kernel/qeventloop.h +++ b/src/corelib/kernel/qeventloop.h @@ -55,7 +55,7 @@ class QEventLoopPrivate; class Q_CORE_EXPORT QEventLoop : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QEventLoop) + Q_DECLARE_PRIVATE(QEventLoop) public: explicit QEventLoop(QObject *parent = 0); diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h index a7f2f9d..ad44a15 100644 --- a/src/corelib/kernel/qfunctions_p.h +++ b/src/corelib/kernel/qfunctions_p.h @@ -57,6 +57,8 @@ #if defined(Q_OS_WINCE) # include "QtCore/qfunctions_wince.h" +#elif defined(Q_OS_VXWORKS) +# include "QtCore/qfunctions_vxworks.h" #endif #ifdef Q_CC_RVCT diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp new file mode 100644 index 0000000..def8f4c --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" + +#ifdef Q_OS_VXWORKS + +#include "qplatformdefs.h" +#include "qfunctions_vxworks.h" + +#include <vmLib.h> +#include <selectLib.h> +#include <ioLib.h> + +QT_USE_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)) +{ + const char* current = (char*) base; + const char* const end = (char*) (current + (*elements) * size); + while (current != end) { + if (compare(current, key) == 0) + return (void*)current; + current += size; + } + return 0; +} + + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/) +{ + return rand(); +} + +// no usleep() support +int usleep(unsigned int usec) +{ + div_t dt = div(usec, 1000000); + struct timespec ts = { dt.quot, dt.rem * 1000 }; + + return nanosleep(&ts, 0); +} + + +// gettimeofday() is declared, but is missing from the library +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +#if defined(Q_CC_DIAB) +# pragma weak gettimeofday +#endif +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) +{ + // the compiler will optimize this and will only use one code path + if (sizeof(struct timeval) == sizeof(struct timespec)) { + int res = clock_gettime(CLOCK_REALTIME, (struct timespec *) tv); + if (!res) + tv->tv_usec /= 1000; + return res; + } else { + struct timespec ts; + + int res = clock_gettime(CLOCK_REALTIME, &ts); + if (!res) { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + } + return res; + } +} + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize() +{ + return vmPageSizeGet(); +} + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *) +{ + errno = EIO; + return -1; +} + +ssize_t readlink(const char *, char *, size_t) +{ + errno = EIO; + return -1; +} + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length) +{ + int fd = open(path, O_WRONLY, 00777); + if (fd >= 0) { + int res = ftruncate(fd, length); + int en = errno; + close(fd); + errno = en; + return res; + } + // errno is already set by open + return -1; +} + + + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid() +{ + return 0; +} + +gid_t getgid() +{ + return 0; +} + +uid_t geteuid() +{ + return 0; +} + +struct passwd *getpwuid(uid_t uid) +{ + static struct passwd pwbuf = { "root", 0, 0, 0, 0, 0, 0 }; + + if (uid == 0) { + return &pwbuf; + } else { + errno = ENOENT; + return 0; + } +} + +struct group *getgrgid(gid_t gid) +{ + static struct group grbuf = { "root", 0, 0, 0 }; + + if (gid == 0) { + return &grbuf; + } else { + errno = ENOENT; + return 0; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h new file mode 100644 index 0000000..e31d495 --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUNCTIONS_VXWORKS_H +#define QFUNCTIONS_VXWORKS_H +#ifdef Q_OS_VXWORKS + +#include <unistd.h> +#include <pthread.h> +#include <dirent.h> +#include <signal.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/times.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <netinet/in.h> +#ifndef QT_NO_IPV6IFNAME +#include <net/if.h> +#endif + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifdef QT_BUILD_CORE_LIB +QT_MODULE(Core) +#endif + +QT_END_NAMESPACE +QT_END_HEADER + + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +#ifndef NSIG +#define NSIG _NSIGS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// isascii is missing (sometimes!!) +#ifndef isascii +inline int isascii(int c) { return (c & 0x7f); } +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)); + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/); + +// no usleep() support +int usleep(unsigned int); + +// gettimeofday() is declared, but is missing from the library. +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) __attribute__((weak)); + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize(); + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *); +ssize_t readlink(const char *, char *, size_t); + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length); + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid(); +gid_t getgid(); +uid_t geteuid(); + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* user password */ + uid_t pw_uid; /* user ID */ + gid_t pw_gid; /* group ID */ + char *pw_gecos; /* real name */ + char *pw_dir; /* home directory */ + char *pw_shell; /* shell program */ +}; + +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group ID */ + char **gr_mem; /* group members */ +}; + +struct passwd *getpwuid(uid_t uid); +struct group *getgrgid(gid_t gid); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS +#endif // QFUNCTIONS_VXWORKS_H diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp index 2c47adb..5680ad5 100644 --- a/src/corelib/kernel/qfunctions_wince.cpp +++ b/src/corelib/kernel/qfunctions_wince.cpp @@ -108,7 +108,7 @@ int qt_wince__getdrive( void ) return 1; } -int qt_wince__waccess( const WCHAR *path, int pmode ) +int qt_wince__waccess( const wchar_t *path, int pmode ) { DWORD res = GetFileAttributes( path ); if ( 0xFFFFFFFF == res ) @@ -118,7 +118,7 @@ int qt_wince__waccess( const WCHAR *path, int pmode ) return -1; if ( (pmode & X_OK) && !(res & FILE_ATTRIBUTE_DIRECTORY) ) { - QString file = QString::fromUtf16(reinterpret_cast<const ushort *> (path)); + QString file = QString::fromWCharArray(path); if ( !(file.endsWith(QString::fromLatin1(".exe")) || file.endsWith(QString::fromLatin1(".com"))) ) return -1; @@ -130,12 +130,12 @@ int qt_wince__waccess( const WCHAR *path, int pmode ) int qt_wince_open( const char *filename, int oflag, int pmode ) { QString fn( QString::fromLatin1(filename) ); - return _wopen( (WCHAR*)fn.utf16(), oflag, pmode ); + return _wopen( (wchar_t*)fn.utf16(), oflag, pmode ); } -int qt_wince__wopen( const WCHAR *filename, int oflag, int /*pmode*/ ) +int qt_wince__wopen( const wchar_t *filename, int oflag, int /*pmode*/ ) { - WCHAR *flag; + wchar_t *flag; if ( oflag & _O_APPEND ) { if ( oflag & _O_WRONLY ) { @@ -290,7 +290,7 @@ bool qt_wince__chmod(const char *file, int mode) return _wchmod( reinterpret_cast<const wchar_t *> (QString::fromLatin1(file).utf16()), mode); } -bool qt_wince__wchmod(const WCHAR *file, int mode) +bool qt_wince__wchmod(const wchar_t *file, int mode) { // ### Does not work properly, what about just adding one property? if(mode&_S_IWRITE) { diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h index 307e17b..41cb641 100644 --- a/src/corelib/kernel/qfunctions_wince.h +++ b/src/corelib/kernel/qfunctions_wince.h @@ -175,8 +175,8 @@ typedef int mode_t; extern int errno; int qt_wince__getdrive( void ); -int qt_wince__waccess( const WCHAR *path, int pmode ); -int qt_wince__wopen( const WCHAR *filename, int oflag, int pmode ); +int qt_wince__waccess( const wchar_t *path, int pmode ); +int qt_wince__wopen( const wchar_t *filename, int oflag, int pmode ); long qt_wince__lseek( int handle, long offset, int origin ); int qt_wince__read( int handle, void *buffer, unsigned int count ); int qt_wince__write( int handle, const void *buffer, unsigned int count ); @@ -204,7 +204,7 @@ int qt_wince_SetErrorMode(int); #endif bool qt_wince__chmod(const char *file, int mode); -bool qt_wince__wchmod(const WCHAR *file, int mode); +bool qt_wince__wchmod(const wchar_t *file, int mode); #pragma warning(disable: 4273) HANDLE qt_wince_CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h new file mode 100644 index 0000000..6af01ac --- /dev/null +++ b/src/corelib/kernel/qguard_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUARD_P_H +#define QGUARD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +QT_BEGIN_NAMESPACE + +class QObject; +template<class T> +class QGuard +{ + QObject *o; + QGuard<QObject> *next; + QGuard<QObject> **prev; + friend void q_guard_addGuard(QGuard<QObject> *); + friend void q_guard_removeGuard(QGuard<QObject> *); + friend class QObjectPrivate; +public: + inline QGuard(); + inline QGuard(T *); + inline QGuard(const QGuard<T> &); + inline virtual ~QGuard(); + + inline QGuard<T> &operator=(const QGuard<T> &o); + inline QGuard<T> &operator=(T *); + + inline bool isNull() const + { return !o; } + + inline T* operator->() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + inline T& operator*() const + { return *static_cast<T*>(const_cast<QObject*>(o)); } + inline operator T*() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + inline T* data() const + { return static_cast<T*>(const_cast<QObject*>(o)); } + +protected: + virtual void objectDestroyed(T *) {} +}; + +QT_END_NAMESPACE + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +inline void q_guard_addGuard(QGuard<QObject> *); +inline void q_guard_removeGuard(QGuard<QObject> *); + +template<class T> +QGuard<T>::QGuard() +: o(0), next(0), prev(0) +{ +} + +template<class T> +QGuard<T>::QGuard(T *g) +: o(g), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::QGuard(const QGuard<T> &g) +: o(g.o), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::~QGuard() +{ + if (prev) q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = 0; +} + +template<class T> +QGuard<T> &QGuard<T>::operator=(const QGuard<T> &g) +{ + if (g.o != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g.o; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +template<class T> +inline QGuard<T> &QGuard<T>::operator=(T *g) +{ + if (g != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +QT_END_NAMESPACE + +#endif // QGUARD_P_H diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h index 348957f..7a77d56 100644 --- a/src/corelib/kernel/qmath.h +++ b/src/corelib/kernel/qmath.h @@ -132,6 +132,10 @@ inline qreal qPow(qreal x, qreal y) return pow(x, y); } +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 0b9f841..1d0b2c8 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -148,7 +148,9 @@ enum PropertyFlags { Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, -// Override = 0x00000200, +// Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -179,6 +181,10 @@ enum MethodFlags { MethodScriptable = 0x40 }; +enum MetaObjectFlags { + DynamicMetaObject = 0x01 +}; + struct QMetaObjectPrivate { int revision; @@ -188,6 +194,7 @@ struct QMetaObjectPrivate int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; + int flags; }; static inline const QMetaObjectPrivate *priv(const uint* data) @@ -277,6 +284,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const } /*! + \internal +*/ +int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) +{ + if (QMetaObject *mo = object->d_ptr->metaObject) + return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv); + else + return object->qt_metacall(cl, idx, argv); +} + +/*! \fn const char *QMetaObject::className() const Returns the class name. @@ -696,6 +714,14 @@ int QMetaObject::indexOfProperty(const char *name) const } m = m->d.superdata; } + + if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + QAbstractDynamicMetaObject *me = + const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this)); + + i = me->createProperty(name, 0); + } + return i; } @@ -1326,6 +1352,18 @@ int QMetaMethod::attributes() const } /*! + \since 4.6 + + Returns this method's index. +*/ +int QMetaMethod::methodIndex() const +{ + if (!mobj) + return -1; + return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -1525,7 +1563,7 @@ bool QMetaMethod::invoke(QObject *object, // recompute the methodIndex by reversing the arithmetic in QMetaObject::property() int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; } else { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " @@ -2042,6 +2080,18 @@ int QMetaProperty::userType() const } /*! + \since 4.6 + + Returns this property's index. +*/ +int QMetaProperty::propertyIndex() const +{ + if (!mobj) + return -1; + return idx + mobj->propertyOffset(); +} + +/*! Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns false. @@ -2138,19 +2188,25 @@ QVariant QMetaProperty::read(const QObject *object) const return QVariant(); } } + + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value + int status = -1; QVariant value; - void *argv[2] = { 0, &value }; + void *argv[] = { 0, &value, &status }; if (t == QVariant::LastType) { argv[0] = &value; } else { value = QVariant(t, (void*)0); argv[0] = value.data(); } - const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty, - idx + mobj->propertyOffset(), - argv); - if (argv[1] == 0) - // "value" was changed + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, + idx + mobj->propertyOffset(), argv); + + if (status != -1) return value; if (t != QVariant::LastType && argv[0] != value.data()) // pointer or reference @@ -2208,13 +2264,19 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const return false; } - void *argv[2] = { 0, &v }; + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value, return the value of status + int status = -1; + void *argv[] = { 0, &v, &status }; if (t == QVariant::LastType) argv[0] = &v; else argv[0] = v.data(); - object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); - return true; + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); + return status; } /*! @@ -2230,7 +2292,7 @@ bool QMetaProperty::reset(QObject *object) const if (!object || !mobj || !isResettable()) return false; void *argv[] = { 0 }; - object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); return true; } @@ -2293,6 +2355,8 @@ QMetaMethod QMetaProperty::notifySignal() const } /*! + \since 4.6 + Returns the index of the property change notifying signal if one was specified, otherwise returns -1. @@ -2342,8 +2406,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const bool b = flags & Designable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyDesignable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable, + idx + mobj->propertyOffset(), argv); } return b; @@ -2368,8 +2432,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const bool b = flags & Scriptable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyScriptable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2392,8 +2456,8 @@ bool QMetaProperty::isStored(const QObject *object) const bool b = flags & Stored; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyStored, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2419,13 +2483,41 @@ bool QMetaProperty::isUser(const QObject *object) const bool b = flags & User; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser, + idx + mobj->propertyOffset(), argv); } return b; } /*! + Returns true if the property is constant; otherwise returns false. + + A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute + is set. +*/ +bool QMetaProperty::isConstant() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Constant; +} + +/*! + Returns true if the property is final; otherwise returns false. + + A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute + is set. +*/ +bool QMetaProperty::isFinal() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Final; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; @@ -2445,8 +2537,8 @@ bool QMetaProperty::isEditable(const QObject *object) const bool b = flags & Editable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyEditable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable, + idx + mobj->propertyOffset(), argv); } return b; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 000ba6e..419fe06 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -69,6 +69,7 @@ public: MethodType methodType() const; enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; + int methodIndex() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -178,6 +179,7 @@ public: const char *typeName() const; QVariant::Type type() const; int userType() const; + int propertyIndex() const; bool isReadable() const; bool isWritable() const; @@ -187,6 +189,8 @@ public: bool isStored(const QObject *obj = 0) const; bool isEditable(const QObject *obj = 0) const; bool isUser(const QObject *obj = 0) const; + bool isConstant() const; + bool isFinal() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 02338fe..bd27ec2 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -171,6 +171,11 @@ QT_BEGIN_NAMESPACE \value QBitmap QBitmap \value QMatrix QMatrix \value QTransform QTransform + \value QMatrix4x4 QMatrix4x4 + \value QVector2D QVector2D + \value QVector3D QVector3D + \value QVector4D QVector4D + \value QQuaternion QQuaternion \value User Base value for user types @@ -272,6 +277,11 @@ static const struct { const char * typeName; int type; } types[] = { {"QTextFormat", QMetaType::QTextFormat}, {"QMatrix", QMetaType::QMatrix}, {"QTransform", QMetaType::QTransform}, + {"QMatrix4x4", QMetaType::QMatrix4x4}, + {"QVector2D", QMetaType::QVector2D}, + {"QVector3D", QMetaType::QVector3D}, + {"QVector4D", QMetaType::QVector4D}, + {"QQuaternion", QMetaType::QQuaternion}, /* All Metatype builtins */ {"void*", QMetaType::VoidStar}, @@ -430,16 +440,15 @@ int QMetaType::registerType(const char *typeName, Destructor destructor, #endif QWriteLocker locker(customTypesLock()); - static int currentIdx = User; int idx = qMetaTypeType_unlocked(normalizedTypeName); if (!idx) { - ct->resize(ct->count() + 1); - idx = currentIdx++; - QCustomTypeInfo &inf = (*ct)[idx - User]; + QCustomTypeInfo inf; inf.typeName = normalizedTypeName; inf.constr = constructor; inf.destr = destructor; + idx = ct->size() + User; + ct->append(inf); } return idx; } @@ -671,6 +680,11 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) case QMetaType::QTextFormat: case QMetaType::QMatrix: case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector3D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: if (!qMetaTypeGuiHelper) return false; qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data); @@ -863,6 +877,11 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) case QMetaType::QTextFormat: case QMetaType::QMatrix: case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector3D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: if (!qMetaTypeGuiHelper) return false; qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data); diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 497c014..052312c 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -79,7 +79,9 @@ public: QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73, QCursor = 74, QSizePolicy = 75, QKeySequence = 76, QPen = 77, QTextLength = 78, QTextFormat = 79, QMatrix = 80, QTransform = 81, - LastGuiType = 81 /* QTransform */, + QMatrix4x4 = 82, QVector2D = 83, QVector3D = 84, QVector4D = 85, + QQuaternion = 86, + LastGuiType = 86 /* QQuaternion */, FirstCoreExtType = 128 /* VoidStar */, VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132, @@ -292,6 +294,11 @@ class QTextLength; class QTextFormat; class QMatrix; class QTransform; +class QMatrix4x4; +class QVector2D; +class QVector3D; +class QVector4D; +class QQuaternion; QT_END_NAMESPACE @@ -354,6 +361,11 @@ Q_DECLARE_BUILTIN_METATYPE(QTextLength, QTextLength) Q_DECLARE_BUILTIN_METATYPE(QTextFormat, QTextFormat) Q_DECLARE_BUILTIN_METATYPE(QMatrix, QMatrix) Q_DECLARE_BUILTIN_METATYPE(QTransform, QTransform) +Q_DECLARE_BUILTIN_METATYPE(QMatrix4x4, QMatrix4x4) +Q_DECLARE_BUILTIN_METATYPE(QVector2D, QVector2D) +Q_DECLARE_BUILTIN_METATYPE(QVector3D, QVector3D) +Q_DECLARE_BUILTIN_METATYPE(QVector4D, QVector4D) +Q_DECLARE_BUILTIN_METATYPE(QQuaternion, QQuaternion) QT_END_HEADER diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index 3d2a7cb..4a1ba9f 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -105,7 +105,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty Q_Q(const QMimeData); QVariant data = q->retrieveData(format, type); - if (data.type() == type || data.type() == QVariant::Invalid) + if (data.type() == type || !data.isValid()) return data; // provide more conversion possiblities than just what QVariant provides diff --git a/src/corelib/kernel/qmimedata.h b/src/corelib/kernel/qmimedata.h index 9366c5d..609528a 100644 --- a/src/corelib/kernel/qmimedata.h +++ b/src/corelib/kernel/qmimedata.h @@ -94,7 +94,7 @@ protected: QVariant::Type preferredType) const; private: Q_DISABLE_COPY(QMimeData) - Q_DECLARE_SCOPED_PRIVATE(QMimeData) + Q_DECLARE_PRIVATE(QMimeData) }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index cc2df0c..e6947a0 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -123,8 +123,11 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } } +QObjectData::~QObjectData() {} +QDeclarativeData::~QDeclarativeData() {} + QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0) + : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0), declarativeData(0), objectGuards(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -140,15 +143,18 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals = 0; + for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) + connectedSignals[i] = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + metaObject = 0; hasGuards = false; } QObjectPrivate::~QObjectPrivate() { + delete static_cast<QAbstractDynamicMetaObject*>(metaObject); if (deleteWatch) *deleteWatch = 1; #ifndef QT_NO_USERDATA @@ -428,8 +434,24 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - if (!QObjectPrivate::get(object)->hasGuards) + QObjectPrivate *priv = QObjectPrivate::get(object); + QGuard<QObject> *guard = priv->objectGuards; + while (guard) { + guard->o = 0; + guard = guard->next; + } + while (priv->objectGuards) { + guard = priv->objectGuards; + guard->prev = 0; + if (guard->next) guard->next->prev = &priv->objectGuards; + priv->objectGuards = guard->next; + guard->next = 0; + guard->objectDestroyed(object); + } + + if (!priv->hasGuards) return; + GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -480,7 +502,7 @@ QMetaCallEvent::~QMetaCallEvent() */ int QMetaCallEvent::placeMetaCall(QObject *object) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_); + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_); } /*! @@ -578,7 +600,7 @@ int QMetaCallEvent::placeMetaCall(QObject *object) \l uic generates code that invokes this function to enable auto-connection to be performed between widgets on forms created with \QD. More information about using auto-connection with \QD is - given in the \l{Using a Designer .ui File in Your Application} section of + given in the \l{Using a Designer UI File in Your Application} section of the \QD manual. \section2 Dynamic Properties @@ -774,6 +796,8 @@ QObject::~QObject() QT_TRY { emit destroyed(this); + if (d->declarativeData) + d->declarativeData->destroyed(this); // ### TODO: Can this throw? } QT_CATCH(...) { // all the signal/slots connections are still in place - if we don't // quit now, we will crash pretty soon. @@ -898,7 +922,7 @@ QObject::~QObject() QObjectPrivate::Connection::~Connection() { if (argumentTypes != &DIRECT_CONNECTION_ONLY) - delete [] argumentTypes; + delete [] static_cast<int *>(argumentTypes); } @@ -2132,6 +2156,34 @@ void QObject::deleteLater() \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17 + \section1 Meta Data + + Additional data can be attached to each translatable message. + The syntax: + + \tt{//= <id>} + + can be used to give the message a unique identifier to support tools + which need it. + The syntax: + + \tt{//~ <field name> <field contents>} + + can be used to attach meta data to the message. The field name should consist + of a domain prefix (possibly the conventional file extension of the file format + the field is inspired by), a hyphen and the actual field name in + underscore-delimited notation. For storage in TS files, the field name together + with the prefix "extra-" will form an XML element name. The field contents will + be XML-escaped, but otherwise appear verbatim as the element's contents. + Any number of unique fields can be added to each message. + + Example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp meta data + + Meta data appearing right in front of a magic TRANSLATOR comment applies to the + whole TS file. + \section1 Character Encodings You can set the encoding for \a sourceText by calling QTextCodec::setCodecForTr(). @@ -2886,10 +2938,16 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, if (c->next) c->next->prev = &c->next; - if (signal_index < 0) - sender->d_func()->connectedSignals = ~0u; - else if (signal_index < 32) - sender->d_func()->connectedSignals |= (1 << signal_index); + if (signal_index < 0) { + for (uint i = 0; i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0] ); ++i) + sender->d_func()->connectedSignals[i] = ~0u; + } else if (signal_index < (int)sizeof sender->d_func()->connectedSignals * 8) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + sender->d_func()->connectedSignals[n] |= (1 << (signal_index - n * 8 + * sizeof sender->d_func()->connectedSignals[0])); + } + return true; } @@ -3179,10 +3237,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal } #if defined(QT_NO_EXCEPTIONS) - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); #else QT_TRY { - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } QT_CATCH(...) { locker.relock(); @@ -3231,11 +3289,12 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) { - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3248,11 +3307,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void **argv) { int signal_index = m->methodOffset() + local_signal_index; - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3264,21 +3324,59 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void QMetaObject::activate(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) { + Q_ASSERT(from_local_signal_index <= to_local_signal_index); int offset = m->methodOffset(); int from_signal_index = offset + from_local_signal_index; int to_signal_index = offset + to_local_signal_index; - if (to_signal_index < 32 + + if (to_signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = (1 << (to_signal_index + 1)) - 1; - signal_mask ^= (1 << from_signal_index) - 1; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + + uint n = (from_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (from_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + uint nt = (to_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint mt = 1 << (to_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + bool connected = false; + quint32 *connectedSignals = sender->d_func()->connectedSignals; + for (uint i = 0; !connected && i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0]); ++i) { + uint mask = 0; + if (i > n) + mask = ~0u; + else if (i == n) + mask = ~(m -1); + if (i > nt) + mask = 0; + else if (i == nt) + mask &= (mt << 1) - 1; + connected = connectedSignals[i] & mask; + } + if (!connected) // nothing connected to these signals, and no spy return; } activate(sender, from_signal_index, to_signal_index, argv); } +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. +*/ +bool QMetaObject::isConnected(QObject *sender, int signal_index) { + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) + // nothing connected to these signals, and no spy + return false; + } + return true; +} /***************************************************************************** Properties @@ -3868,23 +3966,17 @@ QDebug operator<<(QDebug dbg, const QObject *o) { Synonym for QList<QObject *>. */ -#ifdef QT_JAMBI_BUILD -class QDPtrAccessor : public QObject { -public: - QObjectData *d() const { return d_ptr; } -}; -#endif - void qDeleteInEventHandler(QObject *o) { #ifdef QT_JAMBI_BUILD if (!o) return; - ((QDPtrAccessor *) o)->d()->inEventHandler = false; + QObjectPrivate::get(o)->inEventHandler = false; #endif delete o; } + QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index e725c82..a9f005b 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -110,6 +110,7 @@ public: uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; int postedEvents; + QMetaObject *metaObject; // assert dynamic }; @@ -117,7 +118,7 @@ class Q_CORE_EXPORT QObject { Q_OBJECT Q_PROPERTY(QString objectName READ objectName WRITE setObjectName) - Q_DECLARE_SCOPED_PRIVATE(QObject) + Q_DECLARE_PRIVATE(QObject) public: Q_INVOKABLE explicit QObject(QObject *parent=0); @@ -380,6 +381,9 @@ inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) #endif // Q_MOC_RUN +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + template <class T> inline T qobject_cast_helper(QObject *object, T) { return static_cast<T>(((T)0)->staticMetaObject.cast(object)); } @@ -396,6 +400,8 @@ inline T qobject_cast(const QObject *object) #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \ { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \ template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \ @@ -459,8 +465,13 @@ inline T qobject_cast(const QObject *object) } +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast<IFace *>(QObject *object) \ { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \ template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \ diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 07c397f..e58ee6c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,6 +60,7 @@ #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" #include "QtCore/qvariant.h" +#include "private/qguard_p.h" QT_BEGIN_NAMESPACE @@ -81,56 +82,20 @@ void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; -inline QObjectData::~QObjectData() {} - enum { QObjectPrivateVersion = QT_VERSION }; +class Q_CORE_EXPORT QDeclarativeData +{ +public: + virtual ~QDeclarativeData(); + virtual void destroyed(QObject *) = 0; +}; + class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) public: - QObjectPrivate(int version = QObjectPrivateVersion); - virtual ~QObjectPrivate(); - -#ifdef QT3_SUPPORT - QList<QObject *> pendingChildInsertedEvents; - void sendPendingChildInsertedEvents(); - void removePendingChildInsertedEvents(QObject *child); -#else - // preserve binary compatibility with code compiled without Qt 3 support - QList<QObject *> unused; -#endif - - // id of the thread that owns the object - QThreadData *threadData; - void moveToThread_helper(); - void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); - void _q_reregisterTimers(void *pointer); - - struct Sender - { - QObject *sender; - int signal; - int ref; - }; - // object currently activating the object - Sender *currentSender; - - QObject *currentChildBeingDeleted; - - bool isSender(const QObject *receiver, const char *signal) const; - QObjectList receiverList(const char *signal) const; - QObjectList senderList() const; - - QList<QPointer<QObject> > eventFilters; - - void setParent_helper(QObject *); - - void deleteChildren(); - - static void clearGuards(QObject *); - struct ExtraData { #ifndef QT_NO_USERDATA @@ -139,12 +104,7 @@ public: QList<QByteArray> propertyNames; QList<QVariant> propertyValues; }; - ExtraData *extraData; - mutable quint32 connectedSignals; - QString objectName; - - // Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions struct Connection { QObject *sender; @@ -159,11 +119,34 @@ public: }; typedef QList<Connection *> ConnectionList; - QObjectConnectionListVector *connectionLists; + struct Sender + { + QObject *sender; + int signal; + int ref; + }; + + + QObjectPrivate(int version = QObjectPrivateVersion); + virtual ~QObjectPrivate(); + void deleteChildren(); + + void setParent_helper(QObject *); + void moveToThread_helper(); + void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); + void _q_reregisterTimers(void *pointer); + + bool isSender(const QObject *receiver, const char *signal) const; + QObjectList receiverList(const char *signal) const; + QObjectList senderList() const; + void addConnection(int signal, Connection *c); void cleanConnectionLists(); - Connection *senders; //linked list; +#ifdef QT3_SUPPORT + void sendPendingChildInsertedEvents(); + void removePendingChildInsertedEvents(QObject *child); +#endif static Sender *setCurrentSender(QObject *receiver, Sender *sender); @@ -172,14 +155,65 @@ public: Sender *previousSender); static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); - - int *deleteWatch; + static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { return o->d_func(); } + +public: + QString objectName; + ExtraData *extraData; // extra data set by the user + QThreadData *threadData; // id of the thread that owns the object + + QObjectConnectionListVector *connectionLists; + + Connection *senders; // linked list of connections connected to this object + Sender *currentSender; // object currently activating the object + mutable quint32 connectedSignals[2]; // 64-bit, so doesn't cause padding on 64-bit platforms + +#ifdef QT3_SUPPORT + QList<QObject *> pendingChildInsertedEvents; +#else + // preserve binary compatibility with code compiled without Qt 3 support + // ### why? + QList<QObject *> unused; +#endif + + QList<QPointer<QObject> > eventFilters; + QObject *currentChildBeingDeleted; + + // these objects are all used to indicate that a QObject was deleted + // plus QPointer, which keeps a separate list + QDeclarativeData *declarativeData; + QGuard<QObject> *objectGuards; + int *deleteWatch; }; +inline void q_guard_addGuard(QGuard<QObject> *g) +{ + QObjectPrivate *p = QObjectPrivate::get(g->o); + if (p->wasDeleted) { + qWarning("QGuard: cannot add guard to deleted object"); + g->o = 0; + return; + } + + g->next = p->objectGuards; + p->objectGuards = g; + g->prev = &p->objectGuards; + if (g->next) + g->next->prev = &g->next; +} + +inline void q_guard_removeGuard(QGuard<QObject> *g) +{ + if (g->next) g->next->prev = g->prev; + *g->prev = g->next; + g->next = 0; + g->prev = 0; +} + Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); @@ -220,6 +254,14 @@ private: void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); + +struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject +{ + virtual ~QAbstractDynamicMetaObject() {} + virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } + virtual int createProperty(const char *, const char *) { return -1; } +}; + QT_END_NAMESPACE #endif // QOBJECT_P_H diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 9187765..1ae46d5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -334,6 +334,9 @@ struct Q_CORE_EXPORT QMetaObject static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); + + static bool isConnected(QObject *sender, int signal_index); + // internal guarded pointers static void addGuard(QObject **ptr); static void removeGuard(QObject **ptr); @@ -428,6 +431,7 @@ struct Q_CORE_EXPORT QMetaObject }; int static_metacall(Call, int, void **) const; + static int metacall(QObject *, Call, int, void **); #ifdef QT3_SUPPORT QT3_SUPPORT const char *superClassName() const; @@ -439,6 +443,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; const void *extradata; } d; + }; struct QMetaObjectExtraData diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h index 0e15ebe..4957c3e 100644 --- a/src/corelib/kernel/qsharedmemory.h +++ b/src/corelib/kernel/qsharedmemory.h @@ -57,7 +57,7 @@ class QSharedMemoryPrivate; class Q_CORE_EXPORT QSharedMemory : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QSharedMemory) + Q_DECLARE_PRIVATE(QSharedMemory) public: enum AccessMode diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp index ffa363f..d35c21f 100644 --- a/src/corelib/kernel/qsharedmemory_symbian.cpp +++ b/src/corelib/kernel/qsharedmemory_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index 7e8dc23..05369c4 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -48,6 +48,9 @@ #include <qdebug.h> #include <errno.h> + +#ifndef QT_NO_SHAREDMEMORY + #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> @@ -56,7 +59,7 @@ #include <fcntl.h> #include <unistd.h> -#ifndef QT_NO_SHAREDMEMORY +#include "private/qcore_unix_p.h" QT_BEGIN_NAMESPACE @@ -82,7 +85,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) error = QSharedMemory::AlreadyExists; break; case ENOENT: - errorString = QSharedMemory::tr("%1: doesn't exists").arg(function); + errorString = QSharedMemory::tr("%1: doesn't exist").arg(function); error = QSharedMemory::NotFound; break; case EMFILE: @@ -121,7 +124,7 @@ key_t QSharedMemoryPrivate::handle() // ftok requires that an actual file exists somewhere QString fileName = makePlatformSafeKey(key); if (!QFile::exists(fileName)) { - errorString = QSharedMemory::tr("%1: unix key file doesn't exists").arg(QLatin1String("QSharedMemory::handle:")); + errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::NotFound; return 0; } @@ -152,7 +155,7 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) if (QFile::exists(fileName)) return 0; - int fd = open(QFile::encodeName(fileName).constData(), + int fd = qt_safe_open(QFile::encodeName(fileName).constData(), O_EXCL | O_CREAT | O_RDWR, 0640); if (-1 == fd) { if (errno == EEXIST) diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index d963a6d..ae64806 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -71,7 +71,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) case ERROR_INVALID_PARAMETER: #endif error = QSharedMemory::NotFound; - errorString = QSharedMemory::tr("%1: doesn't exists").arg(function); + errorString = QSharedMemory::tr("%1: doesn't exist").arg(function); break; case ERROR_COMMITMENT_LIMIT: error = QSharedMemory::InvalidSize; @@ -106,16 +106,11 @@ HANDLE QSharedMemoryPrivate::handle() return false; } #ifndef Q_OS_WINCE - QT_WA({ - hand = OpenFileMappingW(FILE_MAP_ALL_ACCESS, false, (TCHAR*)safeKey.utf16()); - }, { - hand = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, safeKey.toLocal8Bit().constData()); - }); + hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)safeKey.utf16()); #else // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. - hand = CreateFileMappingW(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, 0, (TCHAR*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)safeKey.utf16()); #endif if (!hand) { setErrorString(function); @@ -148,13 +143,7 @@ bool QSharedMemoryPrivate::create(int size) } // Create the file mapping. - QT_WA( { - hand = CreateFileMappingW(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, size, (TCHAR*)safeKey.utf16()); - }, { - hand = CreateFileMappingA(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, size, safeKey.toLocal8Bit().constData()); - } ); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)safeKey.utf16()); setErrorString(function); // hand is valid when it already exists unlike unix so explicitly check diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h index 8c1f663..7bc5035 100644 --- a/src/corelib/kernel/qsignalmapper.h +++ b/src/corelib/kernel/qsignalmapper.h @@ -56,7 +56,7 @@ class QSignalMapperPrivate; class Q_CORE_EXPORT QSignalMapper : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QSignalMapper) + Q_DECLARE_PRIVATE(QSignalMapper) public: explicit QSignalMapper(QObject *parent = 0); ~QSignalMapper(); diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h index bc5d97d..96dda35 100644 --- a/src/corelib/kernel/qsocketnotifier.h +++ b/src/corelib/kernel/qsocketnotifier.h @@ -53,7 +53,7 @@ QT_MODULE(Core) class Q_CORE_EXPORT QSocketNotifier : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QObject) + Q_DECLARE_PRIVATE(QObject) public: enum Type { Read, Write, Exception }; diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp index 1516841..a14db7e 100644 --- a/src/corelib/kernel/qsystemsemaphore_symbian.cpp +++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp index 4e03ddf..1102258 100644 --- a/src/corelib/kernel/qsystemsemaphore_win.cpp +++ b/src/corelib/kernel/qsystemsemaphore_win.cpp @@ -87,11 +87,7 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) // Create it if it doesn't already exists. if (semaphore == 0) { QString safeName = makeKeyFileName(); - QT_WA({ - semaphore = CreateSemaphoreW(0, initialValue, MAXLONG, (TCHAR*)safeName.utf16()); - }, { - semaphore = CreateSemaphoreA(0, initialValue, MAXLONG, safeName.toLocal8Bit().constData()); - }); + semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)safeName.utf16()); if (semaphore == NULL) setErrorString(QLatin1String("QSystemSemaphore::handle")); } diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index d2a0b3a..2ee9d26 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -103,9 +103,8 @@ QT_BEGIN_NAMESPACE Note that QTimer's accuracy depends on the underlying operating system and hardware. Most platforms support an accuracy of - 1 millisecond, but Windows 98 supports only 55. If Qt is - unable to deliver the requested number of timer clicks, it will - silently discard some. + 1 millisecond. If Qt is unable to deliver the requested number of + timer clicks, it will silently discard some. An alternative to using QTimer is to call QObject::startTimer() for your object and reimplement the QObject::timerEvent() event diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 64cf16e..dc1b530 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -58,6 +58,7 @@ #if defined(Q_OS_UNIX) #define QT_USE_MMAP +#include "private/qcore_unix_p.h" #endif // most of the headers below are already included in qplatformdefs.h @@ -502,7 +503,7 @@ bool QTranslator::load(const QString & filename, const QString & directory, \overload load() \fn bool QTranslator::load(const uchar *data, int len) - Loads the .qm file data \a data of length \a len into the + Loads the QM file data \a data of length \a len into the translator. The data is not copied. The caller must be able to guarantee that \a data diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h index 1f94210..b4cea18 100644 --- a/src/corelib/kernel/qtranslator.h +++ b/src/corelib/kernel/qtranslator.h @@ -86,7 +86,7 @@ public: private: Q_DISABLE_COPY(QTranslator) - Q_DECLARE_SCOPED_PRIVATE(QTranslator) + Q_DECLARE_PRIVATE(QTranslator) }; #endif // QT_NO_TRANSLATION diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index dd3468d..5016d3b 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1291,6 +1291,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value Map a QVariantMap \value Matrix a QMatrix \value Transform a QTransform + \value Matrix4x4 a QMatrix4x4 \value Palette a QPalette \value Pen a QPen \value Pixmap a QPixmap @@ -1298,6 +1299,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value PointArray a QPointArray \value PointF a QPointF \value Polygon a QPolygon + \value Quaternion a QQuaternion \value Rect a QRect \value RectF a QRectF \value RegExp a QRegExp @@ -1313,6 +1315,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value UInt a \l uint \value ULongLong a \l qulonglong \value Url a QUrl + \value Vector2D a QVector2D + \value Vector3D a QVector3D + \value Vector4D a QVector4D \value UserType Base value for user-defined types. @@ -1704,7 +1709,7 @@ QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); } Note that return values in the ranges QVariant::Char through QVariant::RegExp and QVariant::Font through QVariant::Transform correspond to the values in the ranges QMetaType::QChar through - QMetaType::QRegExp and QMetaType::QFont through QMetaType::QTransform. + QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion. Pay particular attention when working with char and QChar variants. Note that there is no QVariant constructor specifically @@ -1932,7 +1937,7 @@ void QVariant::load(QDataStream &s) create(static_cast<int>(u), 0); d.is_null = is_null; - if (d.type == QVariant::Invalid) { + if (!isValid()) { // Since we wrote something, we should read something QString x; s >> x; @@ -1976,7 +1981,7 @@ void QVariant::save(QDataStream &s) const s << QMetaType::typeName(userType()); } - if (d.type == QVariant::Invalid) { + if (!isValid()) { s << QString(); return; } diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index e923844..a68939d 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -154,7 +154,12 @@ class Q_CORE_EXPORT QVariant TextFormat = 79, Matrix = 80, Transform = 81, - LastGuiType = Transform, + Matrix4x4 = 82, + Vector2D = 83, + Vector3D = 84, + Vector4D = 85, + Quaternion = 86, + LastGuiType = Quaternion, UserType = 127, #ifdef QT3_SUPPORT diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h index 2c8934f..07aa0ae 100644 --- a/src/corelib/kernel/qwineventnotifier_p.h +++ b/src/corelib/kernel/qwineventnotifier_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QWinEventNotifier : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QObject) + Q_DECLARE_PRIVATE(QObject) public: explicit QWinEventNotifier(QObject *parent = 0); diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h index b646b4d..1717ac0 100644 --- a/src/corelib/plugin/qfactoryloader_p.h +++ b/src/corelib/plugin/qfactoryloader_p.h @@ -66,7 +66,7 @@ class QFactoryLoaderPrivate; class Q_CORE_EXPORT QFactoryLoader : public QObject { Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QFactoryLoader) + Q_DECLARE_PRIVATE(QFactoryLoader) public: QFactoryLoader(const char *iid, diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 3f42311..265a5a2 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -637,11 +637,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) #endif if (!pHnd) { #ifdef Q_OS_WIN - QT_WA({ - hTempModule = ::LoadLibraryExW((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - } , { - temporary_load = load_sys(); - }); + hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); #else # if defined(Q_OS_SYMBIAN) //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists @@ -659,7 +655,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction) #ifdef Q_OS_WINCE - ::GetProcAddressW(hTempModule, L"qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") #else ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") #endif @@ -698,12 +694,15 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) #endif } + // Qt 4.5 compatibility: stl doesn't affect binary compatibility + key.replace(" no-stl", ""); + +#ifndef QT_NO_SETTINGS QStringList queried; queried << QString::number(qt_version,16) << QString::number((int)debug) << QLatin1String(key) << lastModified; -#ifndef QT_NO_SETTINGS settings->setValue(regkey, queried); #endif } diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index bdf6b78..462cfbf 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -#if !defined(QT_HPUX_LD) +#if !defined(QT_HPUX_LD) && !defined(Q_OS_VXWORKS) QT_BEGIN_INCLUDE_NAMESPACE #include <dlfcn.h> QT_END_INCLUDE_NAMESPACE @@ -66,7 +66,9 @@ QT_END_INCLUDE_NAMESPACE static QString qdlerror() { -#if !defined(QT_HPUX_LD) +#if defined(Q_OS_VXWORKS) + const char *err = "VxWorks does not support dynamic libraries."; +#elif !defined(QT_HPUX_LD) const char *err = dlerror(); #else const char *err = strerror(errno); @@ -76,6 +78,8 @@ static QString qdlerror() bool QLibraryPrivate::load_sys() { + QString attempt; +#if !defined(Q_OS_VXWORKS) QFileInfo fi(fileName); #if defined(Q_OS_SYMBIAN) @@ -179,7 +183,6 @@ bool QLibraryPrivate::load_sys() } #endif #endif // QT_HPUX_LD - QString attempt; bool retry = true; for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { @@ -227,7 +230,8 @@ bool QLibraryPrivate::load_sys() attempt = str; } } -# endif +#endif +#endif // Q_OS_VXWORKS if (!pHnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); } @@ -240,14 +244,16 @@ bool QLibraryPrivate::load_sys() bool QLibraryPrivate::unload_sys() { -#if defined(QT_HPUX_LD) +#if !defined(Q_OS_VXWORKS) +# if defined(QT_HPUX_LD) if (shl_unload((shl_t)pHnd)) { -#else +# else if (dlclose(pHnd)) { -#endif +# endif errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror()); return false; } +#endif errorString.clear(); return true; } @@ -272,6 +278,8 @@ void* QLibraryPrivate::resolve_sys(const char* symbol) void* address = 0; if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0) address = 0; +#elif defined(Q_OS_VXWORKS) + void *address = 0; #else void* address = dlsym(pHnd, symbol); #endif diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 43eeafa..847c0d2 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -67,30 +67,18 @@ bool QLibraryPrivate::load_sys() //avoid 'Bad Image' message box UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); - + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); + if (pluginState != IsAPlugin) { #if defined(Q_OS_WINCE) if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { QString secondAttempt = fileName; - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(secondAttempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(secondAttempt)).data()); - }); + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16()); } #endif if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { attempt += QLatin1String(".dll"); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); } } @@ -100,15 +88,11 @@ bool QLibraryPrivate::load_sys() } if (pHnd) { errorString.clear(); - QT_WA({ - TCHAR buffer[MAX_PATH + 1]; - ::GetModuleFileNameW(pHnd, buffer, MAX_PATH); - attempt = QString::fromUtf16(reinterpret_cast<const ushort *>(&buffer)); - }, { - char buffer[MAX_PATH + 1]; - ::GetModuleFileNameA(pHnd, buffer, MAX_PATH); - attempt = QString::fromLocal8Bit(buffer); - }); + + wchar_t buffer[MAX_PATH]; + ::GetModuleFileName(pHnd, buffer, MAX_PATH); + attempt = QString::fromWCharArray(buffer); + const QDir dir = QFileInfo(fileName).dir(); const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1); if (dir.path() == QLatin1String(".")) diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index ff2b412..233b4f9 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -63,21 +63,6 @@ typedef QObject *(*QtPluginInstanceFunction)(); void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function); -struct qt_plugin_instance_deleter -{ - qt_plugin_instance_deleter(QPointer<QObject> &instance) - : instance_(instance) - { - } - - ~qt_plugin_instance_deleter() - { - delete instance_; - } - - QPointer<QObject> &instance_; -}; - #define Q_IMPORT_PLUGIN(PLUGIN) \ extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \ class Static##PLUGIN##PluginInstance{ \ @@ -91,10 +76,8 @@ struct qt_plugin_instance_deleter #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \ { \ static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \ - if (!_instance) { \ - static QT_PREPEND_NAMESPACE(qt_plugin_instance_deleter) deleter(_instance); \ + if (!_instance) \ _instance = new IMPLEMENTATION; \ - } \ return _instance; \ } diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index 3229ab7..5355ac2 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -85,7 +85,7 @@ protected: private: Q_DISABLE_COPY(QAbstractState) - Q_DECLARE_SCOPED_PRIVATE(QAbstractState) + Q_DECLARE_PRIVATE(QAbstractState) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 670aa7d..3248dcf 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -115,13 +115,10 @@ QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(QAbstractTransition QStateMachine *QAbstractTransitionPrivate::machine() const { - QObject *par = parent; - while (par != 0) { - if (QStateMachine *mach = qobject_cast<QStateMachine*>(par)) - return mach; - par = par->parent(); - } - return 0; + QState *source = sourceState(); + if (!source) + return 0; + return source->machine(); } bool QAbstractTransitionPrivate::callEventTest(QEvent *e) @@ -156,17 +153,6 @@ QAbstractTransition::QAbstractTransition(QState *sourceState) } /*! - Constructs a new QAbstractTransition object with the given \a targets and \a - sourceState. -*/ -QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets, - QState *sourceState) - : QObject(*new QAbstractTransitionPrivate, sourceState) -{ - setTargetStates(targets); -} - -/*! \internal */ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, @@ -176,17 +162,6 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, } /*! - \internal -*/ -QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, - const QList<QAbstractState*> &targets, - QState *parent) - : QObject(dd, parent) -{ - setTargetStates(targets); -} - -/*! Destroys this transition. */ QAbstractTransition::~QAbstractTransition() @@ -256,10 +231,6 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets) 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(); diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index a87af39..8ff3a6e 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -72,7 +72,6 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates) public: QAbstractTransition(QState *sourceState = 0); - QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0); virtual ~QAbstractTransition(); QState *sourceState() const; @@ -104,12 +103,10 @@ protected: protected: QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent); - QAbstractTransition(QAbstractTransitionPrivate &dd, - const QList<QAbstractState*> &targets, QState *parent); private: Q_DISABLE_COPY(QAbstractTransition) - Q_DECLARE_SCOPED_PRIVATE(QAbstractTransition) + Q_DECLARE_PRIVATE(QAbstractTransition) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 3933981..813c960 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -153,22 +153,6 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, } /*! - Constructs a new QEventTransition object associated with events of the given - \a type for the given \a object. The transition has the given \a targets and - \a sourceState. -*/ -QEventTransition::QEventTransition(QObject *object, QEvent::Type type, - const QList<QAbstractState*> &targets, - QState *sourceState) - : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; -} - -/*! \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) @@ -190,20 +174,6 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, } /*! - \internal -*/ -QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, const QList<QAbstractState*> &targets, - QState *parent) - : QAbstractTransition(dd, targets, parent) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; -} - -/*! Destroys this QObject event transition. */ QEventTransition::~QEventTransition() diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index c227ab1..0ebca19 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -62,8 +62,6 @@ class Q_CORE_EXPORT QEventTransition : public QAbstractTransition public: QEventTransition(QState *sourceState = 0); QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0); - QEventTransition(QObject *object, QEvent::Type type, - const QList<QAbstractState*> &targets, QState *sourceState = 0); ~QEventTransition(); QObject *eventObject() const; @@ -82,13 +80,10 @@ protected: QEventTransition(QEventTransitionPrivate &dd, QState *parent); QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent); - QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, const QList<QAbstractState*> &targets, - QState *parent); private: Q_DISABLE_COPY(QEventTransition) - Q_DECLARE_SCOPED_PRIVATE(QEventTransition) + Q_DECLARE_PRIVATE(QEventTransition) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h index 7b77b2b..e37ef36 100644 --- a/src/corelib/statemachine/qfinalstate.h +++ b/src/corelib/statemachine/qfinalstate.h @@ -68,7 +68,7 @@ protected: private: Q_DISABLE_COPY(QFinalState) - Q_DECLARE_SCOPED_PRIVATE(QFinalState) + Q_DECLARE_PRIVATE(QFinalState) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index 889308d..395bb98 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -83,7 +83,7 @@ protected: private: Q_DISABLE_COPY(QHistoryState) - Q_DECLARE_SCOPED_PRIVATE(QHistoryState) + Q_DECLARE_PRIVATE(QHistoryState) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index c09c5a3..b7ca61f 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -58,16 +58,16 @@ QT_MODULE(Core) class Q_CORE_EXPORT QSignalEvent : public QEvent { public: - QSignalEvent(const QObject *sender, int signalIndex, + QSignalEvent(QObject *sender, int signalIndex, const QList<QVariant> &arguments); ~QSignalEvent(); - inline const QObject *sender() const { return m_sender; } + inline QObject *sender() const { return m_sender; } inline int signalIndex() const { return m_signalIndex; } inline QList<QVariant> arguments() const { return m_arguments; } private: - const QObject *m_sender; + QObject *m_sender; int m_signalIndex; QList<QVariant> m_arguments; }; diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 389e513..7814699 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -159,21 +159,6 @@ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, } /*! - Constructs a new signal transition associated with the given \a signal of - the given \a sender. The transition has the given \a targets and \a - sourceState. -*/ -QSignalTransition::QSignalTransition(QObject *sender, const char *signal, - const QList<QAbstractState*> &targets, - QState *sourceState) - : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState) -{ - Q_D(QSignalTransition); - d->sender = sender; - d->signal = signal; -} - -/*! Destroys this signal transition. */ QSignalTransition::~QSignalTransition() diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index d6c2324..415751e 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -62,9 +62,6 @@ public: QSignalTransition(QState *sourceState = 0); QSignalTransition(QObject *sender, const char *signal, QState *sourceState = 0); - QSignalTransition(QObject *sender, const char *signal, - const QList<QAbstractState*> &targets, - QState *sourceState = 0); ~QSignalTransition(); QObject *senderObject() const; @@ -81,7 +78,7 @@ protected: private: Q_DISABLE_COPY(QSignalTransition) - Q_DECLARE_SCOPED_PRIVATE(QSignalTransition) + Q_DECLARE_PRIVATE(QSignalTransition) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 83dd869..09d0be0 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE The assignProperty() function is used for defining property assignments that should be performed when a state is entered. - Top-level states must be passed QStateMachine::rootState() as their parent + Top-level states must be passed a QStateMachine object as their parent state, or added to a state machine using QStateMachine::addState(). \section1 States with Child States @@ -215,6 +215,8 @@ QList<QAbstractTransition*> QStatePrivate::transitions() const return result; } +#ifndef QT_NO_PROPERTIES + /*! Instructs this state to set the property with the given \a name of the given \a object to the given \a value when the state is entered. @@ -239,10 +241,12 @@ void QState::assignProperty(QObject *object, const char *name, d->propertyAssignments.append(QPropertyAssignment(object, name, value)); } +#endif // QT_NO_PROPERTIES + /*! Returns this state's error state. - \sa QStateMachine::errorState(), QStateMachine::setErrorState() + \sa QStateMachine::error() */ QAbstractState *QState::errorState() const { @@ -256,19 +260,17 @@ QAbstractState *QState::errorState() const state recursively. If no error state is set for the state itself or any of its ancestors, an error will cause the machine to stop executing and an error will be printed to the console. - - \sa QStateMachine::setErrorState(), QStateMachine::errorState() */ void QState::setErrorState(QAbstractState *state) { Q_D(QState); - if (state != 0 && state->machine() != machine()) { - qWarning("QState::setErrorState: error state cannot belong " - "to a different state machine"); + if (state != 0 && qobject_cast<QStateMachine*>(state)) { + qWarning("QStateMachine::setErrorState: root state cannot be error state"); return; } - if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) { - qWarning("QStateMachine::setErrorState: root state cannot be error state"); + if (state != 0 && (!state->machine() || ((state->machine() != machine()) && !qobject_cast<QStateMachine*>(this)))) { + qWarning("QState::setErrorState: error state cannot belong " + "to a different state machine"); return; } @@ -288,12 +290,7 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) return 0; } - // 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; - } - + transition->setParent(this); const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates; for (int i = 0; i < targets.size(); ++i) { QAbstractState *t = targets.at(i); @@ -308,7 +305,6 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) return 0; } } - transition->setParent(this); if (machine() != 0 && machine()->configuration().contains(this)) QStateMachinePrivate::get(machine())->registerTransitions(this); return transition; @@ -343,7 +339,8 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, return 0; } } - QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target); + QSignalTransition *trans = new QSignalTransition(sender, signal); + trans->setTargetState(target); addTransition(trans); return trans; } @@ -355,7 +352,8 @@ class UnconditionalTransition : public QAbstractTransition { public: UnconditionalTransition(QAbstractState *target) - : QAbstractTransition(QList<QAbstractState*>() << target) {} + : QAbstractTransition() + { setTargetState(target); } protected: void onTransition(QEvent *) {} bool eventTest(QEvent *) { return true; } diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index be37591..ce88b25 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -87,8 +87,10 @@ public: ChildMode childMode() const; void setChildMode(ChildMode mode); +#ifndef QT_NO_PROPERTIES void assignProperty(QObject *object, const char *name, const QVariant &value); +#endif Q_SIGNALS: void finished(); @@ -105,7 +107,7 @@ protected: private: Q_DISABLE_COPY(QState) - Q_DECLARE_SCOPED_PRIVATE(QState) + Q_DECLARE_PRIVATE(QState) }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index b519107..932a239 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -102,14 +102,9 @@ QT_BEGIN_NAMESPACE 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. + Use the addState() function to add a top-level state to the state machine. + 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 @@ -179,26 +174,6 @@ This is */ /*! - \property QStateMachine::rootState - - \brief the root state of this state machine -*/ - -/*! - \property QStateMachine::initialState - - \brief the initial state of this state machine - - The initial state must be one of the rootState()'s child states. -*/ - -/*! - \property QStateMachine::errorState - - \brief the error state of this state machine -*/ - -/*! \property QStateMachine::errorString \brief the error string of this state machine @@ -230,12 +205,12 @@ This is QStateMachinePrivate::QStateMachinePrivate() { state = NotRunning; + _startState = 0; processing = false; processingScheduled = false; stop = false; error = QStateMachine::NoError; globalRestorePolicy = QStateMachine::DoNotRestoreProperties; - rootState = 0; signalEventGenerator = 0; #ifndef QT_NO_ANIMATION animationsEnabled = true; @@ -255,6 +230,11 @@ QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q) return 0; } +QState *QStateMachinePrivate::rootState() const +{ + return const_cast<QStateMachine*>(q_func()); +} + static QEvent *cloneEvent(QEvent *e) { switch (e->type()) { @@ -302,7 +282,9 @@ bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return true; } else { - QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(s1->machine() != 0); + QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); + QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2); Q_ASSERT(lca != 0); return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } @@ -318,17 +300,19 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return false; } else { - QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(s1->machine() != 0); + QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); + QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2); Q_ASSERT(lca != 0); return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } -QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) +QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const { if (states.isEmpty()) return 0; - QList<QState*> ancestors = properAncestors(states.at(0), 0); + QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState()); for (int i = 0; i < ancestors.size(); ++i) { QState *anc = ancestors.at(i); bool ok = true; @@ -376,7 +360,7 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event continue; if (isPreempted(state, enabledTransitions)) continue; - QList<QState*> lst = properAncestors(state, 0); + QList<QState*> lst = properAncestors(state, rootState()->parentState()); if (QState *grp = qobject_cast<QState*>(state)) lst.prepend(grp); bool found = false; @@ -412,7 +396,9 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransit #endif executeTransitionContent(event, enabledTransitions); QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions); +#ifndef QT_NO_PROPERTIES applyProperties(enabledTransitions, exitedStates, enteredStates); +#endif #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after entering states:" << configuration; qDebug() << q_func() << ": end microstep"; @@ -557,11 +543,13 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL if (isFinal(s)) { QState *parent = s->parentState(); if (parent) { - QState *grandparent = parent->parentState(); + if (parent != rootState()) { #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": emitting finished signal for" << parent; + qDebug() << q << ": emitting finished signal for" << parent; #endif - QStatePrivate::get(parent)->emitFinished(); + QStatePrivate::get(parent)->emitFinished(); + } + QState *grandparent = parent->parentState(); if (grandparent && isParallel(grandparent)) { bool allChildStatesFinal = true; QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates(); @@ -572,7 +560,7 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL break; } } - if (allChildStatesFinal) { + if (allChildStatesFinal && (grandparent != rootState())) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": emitting finished signal for" << grandparent; #endif @@ -585,7 +573,7 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL { QSet<QAbstractState*>::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - if (isFinal(*it) && (*it)->parentState() == rootState) { + if (isFinal(*it) && (*it)->parentState() == rootState()) { processing = false; stopProcessingReason = Finished; break; @@ -630,6 +618,11 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } } else { + if (s == rootState()) { + // Error has already been set by exitStates(). + Q_ASSERT(error != QStateMachine::NoError); + return; + } statesToEnter.insert(s); if (isParallel(s)) { QState *grp = qobject_cast<QState*>(s); @@ -643,6 +636,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QState *grp = qobject_cast<QState*>(s); QAbstractState *initial = grp->initialState(); if (initial != 0) { + Q_ASSERT(initial->machine() == q_func()); addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); } else { setError(QStateMachine::NoInitialStateError, grp); @@ -675,6 +669,8 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } +#ifndef QT_NO_PROPERTIES + void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList, const QList<QAbstractState*> &exitedStates, const QList<QAbstractState*> &enteredStates) @@ -862,6 +858,8 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } } +#endif // QT_NO_PROPERTIES + bool QStateMachinePrivate::isFinal(const QAbstractState *s) { return qobject_cast<const QFinalState*>(s) != 0; @@ -873,20 +871,26 @@ bool QStateMachinePrivate::isParallel(const QAbstractState *s) return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); } -bool QStateMachinePrivate::isCompound(const QAbstractState *s) +bool QStateMachinePrivate::isCompound(const QAbstractState *s) const { const QState *group = qobject_cast<const QState*>(s); if (!group) return false; + bool isMachine = (qobject_cast<const QStateMachine*>(group) != 0); + // Don't treat the machine as compound if it's a sub-state of this machine + if (isMachine && (group != rootState())) + return false; return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty()) - || (qobject_cast<QStateMachine*>(group->parent()) != 0); + || isMachine; } -bool QStateMachinePrivate::isAtomic(const QAbstractState *s) +bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const { const QState *ss = qobject_cast<const QState*>(s); return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) - || isFinal(s); + || isFinal(s) + // Treat the machine as atomic if it's a sub-state of this machine + || (ss && (qobject_cast<const QStateMachine*>(ss) != 0) && (ss != rootState())); } @@ -935,6 +939,8 @@ bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const return false; } +#ifndef QT_NO_PROPERTIES + void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName) { RestorableId id(object, propertyName); @@ -979,6 +985,8 @@ void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArra registeredRestorables.remove(id); } +#endif // QT_NO_PROPERTIES + QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) { // Find error state recursively in parent hierarchy if not set explicitly for context state @@ -1034,7 +1042,7 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta if (currentContext == currentErrorState) currentErrorState = 0; - Q_ASSERT(currentErrorState != rootState); + Q_ASSERT(currentErrorState != rootState()); if (currentErrorState != 0) { QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); @@ -1091,12 +1099,14 @@ void QStateMachinePrivate::_q_animationFinished() resetAnimationEndValues.remove(anim); } +#ifndef QT_NO_PROPERTIES // Set the final property value. QPropertyAssignment assn = propertyForAnimation.take(anim); Q_ASSERT(assn.object != 0); assn.object->setProperty(assn.propertyName, assn.value); if (!assn.explicitlySet) unregisterRestorable(assn.object, assn.propertyName); +#endif QAbstractState *state = stateForAnimation.take(anim); Q_ASSERT(state != 0); @@ -1129,7 +1139,8 @@ class InitialTransition : public QAbstractTransition { public: InitialTransition(QAbstractState *target) - : QAbstractTransition(QList<QAbstractState*>() << target) {} + : QAbstractTransition() + { setTargetState(target); } protected: virtual bool eventTest(QEvent *) { return true; } virtual void onTransition(QEvent *) {} @@ -1137,15 +1148,26 @@ protected: } // namespace +QState *QStateMachinePrivate::startState() +{ + Q_Q(QStateMachine); + if (_startState == 0) + _startState = new StartState(q); + return _startState; +} + +void QStateMachinePrivate::removeStartState() +{ + delete _startState; + _startState = 0; +} + void QStateMachinePrivate::_q_start() { Q_Q(QStateMachine); Q_ASSERT(state == Starting); - if (!rootState) { - state = NotRunning; - return; - } - QAbstractState *initial = rootState->initialState(); + Q_ASSERT(rootState() != 0); + QAbstractState *initial = rootState()->initialState(); configuration.clear(); qDeleteAll(internalEventQueue); internalEventQueue.clear(); @@ -1159,17 +1181,27 @@ void QStateMachinePrivate::_q_start() processingScheduled = true; // we call _q_process() below emit q->started(); - StartState *start = new StartState(rootState); - QAbstractTransition *initialTransition = new InitialTransition(initial); - start->addTransition(initialTransition); - QList<QAbstractTransition*> transitions; - transitions.append(initialTransition); + QState *start = startState(); + Q_ASSERT(start != 0); + + QList<QAbstractTransition*> transitions = QStatePrivate::get(start)->transitions(); + + // If a transition has already been added, then we skip this step, as the + // initial transition in that case has been overridden. + if (transitions.isEmpty()) { + QAbstractTransition *initialTransition = new InitialTransition(initial); + start->addTransition(initialTransition); + transitions.append(initialTransition); + } + QEvent nullEvent(QEvent::None); executeTransitionContent(&nullEvent, transitions); QList<QAbstractState*> enteredStates = enterStates(&nullEvent, transitions); +#ifndef QT_NO_PROPERTIES applyProperties(transitions, QList<QAbstractState*>() << start, enteredStates); - delete start; +#endif + removeStartState(); #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": initial configuration:" << configuration; @@ -1269,6 +1301,68 @@ void QStateMachinePrivate::scheduleProcess() QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection); } +namespace { + +class GoToStateTransition : public QAbstractTransition +{ +public: + GoToStateTransition(QAbstractState *target) + : QAbstractTransition() + { setTargetState(target); } +protected: + void onTransition(QEvent *) { deleteLater(); } + bool eventTest(QEvent *) { return true; } +}; + +} // namespace + +/*! + \internal + + Causes this state machine to unconditionally transition to the given + \a targetState. + + Provides a backdoor for using the state machine "imperatively"; i.e. rather + than defining explicit transitions, you drive the machine's execution by + calling this function. It breaks the whole integrity of the + transition-driven model, but is provided for pragmatic reasons. +*/ +void QStateMachinePrivate::goToState(QAbstractState *targetState) +{ + if (!targetState) { + qWarning("QStateMachine::goToState(): cannot go to null state"); + return; + } + + if (configuration.contains(targetState)) + return; + + QState *sourceState = 0; + if (state == Running) { + QSet<QAbstractState*>::const_iterator it; + for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { + sourceState = qobject_cast<QState*>(*it); + if (sourceState != 0) + break; + } + } else { + sourceState = startState(); + } + + Q_ASSERT(sourceState != 0); + // Reuse previous GoToStateTransition in case of several calls to + // goToState() in a row. + GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState); + if (!trans) { + trans = new GoToStateTransition(targetState); + sourceState->addTransition(trans); + } else { + trans->setTargetState(targetState); + } + + scheduleProcess(); +} + void QStateMachinePrivate::registerTransitions(QAbstractState *state) { QState *group = qobject_cast<QState*>(state); @@ -1371,15 +1465,22 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit void QStateMachinePrivate::unregisterAllTransitions() { + Q_Q(QStateMachine); { - QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState); - for (int i = 0; i < transitions.size(); ++i) - unregisterSignalTransition(transitions.at(i)); + QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState()); + for (int i = 0; i < transitions.size(); ++i) { + QSignalTransition *t = transitions.at(i); + if (t->machine() == q) + unregisterSignalTransition(t); + } } { - QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState); - for (int i = 0; i < transitions.size(); ++i) - unregisterEventTransition(transitions.at(i)); + QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState()); + for (int i = 0; i < transitions.size(); ++i) { + QEventTransition *t = transitions.at(i); + if (t->machine() == q) + unregisterEventTransition(t); + } } } @@ -1431,7 +1532,7 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio } #endif -void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex, +void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex, void **argv) { Q_ASSERT(connections[sender].at(signalIndex) != 0); @@ -1457,16 +1558,20 @@ void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int sig Constructs a new state machine with the given \a parent. */ QStateMachine::QStateMachine(QObject *parent) - : QObject(*new QStateMachinePrivate, parent) + : QState(*new QStateMachinePrivate, /*parentState=*/0) { + // Can't pass the parent to the QState constructor, as it expects a QState + // But this works as expected regardless of whether parent is a QState or not + setParent(parent); } /*! \internal */ QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent) - : QObject(dd, parent) + : QState(dd, /*parentState=*/0) { + setParent(parent); } /*! @@ -1476,69 +1581,6 @@ QStateMachine::~QStateMachine() { } -namespace { - -class RootState : public QState -{ -public: - RootState(QState *parent) - : QState(parent) - { - } - - void onEntry(QEvent *) {} - void onExit(QEvent *) {} -}; - -} // namespace - -/*! - Returns this state machine's root state. -*/ -QState *QStateMachine::rootState() const -{ - Q_D(const QStateMachine); - if (!d->rootState) { - const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0); - d->rootState->setParent(const_cast<QStateMachine*>(this)); - } - return d->rootState; -} - -/*! - Returns the error state of the state machine's root state. - - \sa QState::errorState() -*/ -QAbstractState *QStateMachine::errorState() const -{ - return rootState()->errorState(); -} - -/*! - Sets the error state of this state machine's root state to be \a state. When a running state - machine encounters an error which puts it in an undefined state, it will enter an error state - based on the context of the error that occurred. It will enter this state regardless of what - is currently in the event queue. - - If the erroneous state has an error state set, this will be entered by the machine. If no error - state has been set, the state machine will search the parent hierarchy recursively for an - error state. The error state of the root state can thus be seen as a global error state that - applies for all states for which a more specific error state has not been set. - - Before entering the error state, the state machine will set the error code returned by error() and - error message returned by errorString(). - - If there is no error state available for the erroneous state, the state machine will print a - warning message on the console and stop executing. - - \sa QState::setErrorState(), rootState() -*/ -void QStateMachine::setErrorState(QAbstractState *state) -{ - rootState()->setErrorState(state); -} - /*! \enum QStateMachine::Error This enum type defines errors that can occur in the state machine at run time. When the state @@ -1640,39 +1682,13 @@ void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restoreP } /*! - Returns this state machine's initial state, or 0 if no initial state has - been set. -*/ -QAbstractState *QStateMachine::initialState() const -{ - Q_D(const QStateMachine); - if (!d->rootState) - return 0; - return d->rootState->initialState(); -} - -/*! - Sets this state machine's initial \a state. -*/ -void QStateMachine::setInitialState(QAbstractState *state) -{ - Q_D(QStateMachine); - if (!d->rootState) { - if (!state) - return; - rootState()->setInitialState(state); - } - d->rootState->setInitialState(state); -} - -/*! Adds the given \a state to this state machine. The state becomes a top-level - state (i.e. a child of the rootState()). + state. If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine. - \sa removeState(), rootState(), setInitialState() + \sa removeState(), setInitialState() */ void QStateMachine::addState(QAbstractState *state) { @@ -1684,7 +1700,7 @@ void QStateMachine::addState(QAbstractState *state) qWarning("QStateMachine::addState: state has already been added to this machine"); return; } - state->setParent(rootState()); + state->setParent(this); } /*! @@ -1730,7 +1746,7 @@ void QStateMachine::start() { Q_D(QStateMachine); - if (rootState()->initialState() == 0) { + if (initialState() == 0) { qWarning("QStateMachine::start: No initial state set for machine. Refusing to start."); return; } @@ -1821,7 +1837,7 @@ void QStateMachine::postInternalEvent(QEvent *event) Returns the maximal consistent set of states (including parallel and final states) that this state machine is currently in. If a state \c s is in the configuration, it is always the case that the parent of \c s is also in - c. Note, however, that the rootState() is not an explicit member of the + c. Note, however, that the machine itself is not an explicit member of the configuration. */ QSet<QAbstractState*> QStateMachine::configuration() const @@ -1840,15 +1856,6 @@ QSet<QAbstractState*> QStateMachine::configuration() const */ /*! - \fn QStateMachine::finished() - - This signal is emitted when the state machine has reached a top-level final - state (QFinalState). - - \sa QStateMachine::started() -*/ - -/*! \fn QStateMachine::stopped() This signal is emitted when the state machine has stopped. @@ -1872,14 +1879,6 @@ bool QStateMachine::event(QEvent *e) d->scheduleProcess(); return true; } - } else if (e->type() == QEvent::ChildAdded) { - QChildEvent *ce = static_cast<QChildEvent*>(e); - if (QAbstractState *state = qobject_cast<QAbstractState*>(ce->child())) { - if (state != rootState()) { - state->setParent(rootState()); - return true; - } - } } return QObject::event(e); } @@ -1949,6 +1948,24 @@ void QStateMachine::endMicrostep(QEvent *event) Q_UNUSED(event); } +/*! + \reimp +*/ +void QStateMachine::onEntry(QEvent *event) +{ + start(); + QState::onEntry(event); +} + +/*! + \reimp +*/ +void QStateMachine::onExit(QEvent *event) +{ + stop(); + QState::onExit(event); +} + #ifndef QT_NO_ANIMATION /*! @@ -2095,7 +2112,7 @@ QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) Constructs a new QSignalEvent object with the given \a sender, \a signalIndex and \a arguments. */ -QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex, +QSignalEvent::QSignalEvent(QObject *sender, int signalIndex, const QList<QVariant> &arguments) : QEvent(QEvent::Signal), m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments) @@ -2155,6 +2172,8 @@ QSignalEvent::~QSignalEvent() Constructs a new QWrappedEvent object with the given \a object and \a event. + + The QWrappedEvent object takes ownership of \a event. */ QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) : QEvent(QEvent::Wrapped), m_object(object), m_event(event) @@ -2166,6 +2185,7 @@ QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) */ QWrappedEvent::~QWrappedEvent() { + delete m_event; } /*! diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 1f0d5b0..230d852 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -42,7 +42,7 @@ #ifndef QSTATEMACHINE_H #define QSTATEMACHINE_H -#include <QtCore/qabstractstate.h> +#include <QtCore/qstate.h> #include <QtCore/qlist.h> #include <QtCore/qobject.h> @@ -57,18 +57,12 @@ QT_MODULE(Core) #ifndef QT_NO_STATEMACHINE class QEvent; -class QAbstractState; -class QState; class QStateMachinePrivate; class QAbstractAnimation; -class QAbstractState; -class Q_CORE_EXPORT QStateMachine : public QObject +class Q_CORE_EXPORT QStateMachine : public QState { Q_OBJECT - Q_PROPERTY(QState* rootState READ rootState) - Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) - Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) Q_ENUMS(RestorePolicy) @@ -94,14 +88,6 @@ public: void addState(QAbstractState *state); void removeState(QAbstractState *state); - QState *rootState() const; - - QAbstractState *initialState() const; - void setInitialState(QAbstractState *state); - - QAbstractState *errorState() const; - void setErrorState(QAbstractState *state); - Error error() const; QString errorString() const; void clearError(); @@ -135,9 +121,11 @@ public Q_SLOTS: Q_SIGNALS: void started(); void stopped(); - void finished(); protected: + void onEntry(QEvent *event); + void onExit(QEvent *event); + void postInternalEvent(QEvent *event); virtual void beginSelectTransitions(QEvent *event); @@ -153,7 +141,7 @@ protected: private: Q_DISABLE_COPY(QStateMachine) - Q_DECLARE_SCOPED_PRIVATE(QStateMachine) + Q_DECLARE_PRIVATE(QStateMachine) Q_PRIVATE_SLOT(d_func(), void _q_start()) Q_PRIVATE_SLOT(d_func(), void _q_process()) #ifndef QT_NO_ANIMATION diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 1335b93..f0f74d6 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -53,7 +53,8 @@ // We mean it. // -#include <private/qobject_p.h> +#include "private/qstate_p.h" + #include <QtCore/qcoreevent.h> #include <QtCore/qhash.h> #include <QtCore/qlist.h> @@ -61,9 +62,6 @@ #include <QtCore/qset.h> #include <QtCore/qvector.h> -#include "qstate.h" -#include "private/qstate_p.h" - QT_BEGIN_NAMESPACE class QEvent; @@ -81,7 +79,7 @@ class QAbstractAnimation; #endif class QStateMachine; -class QStateMachinePrivate : public QObjectPrivate +class Q_CORE_EXPORT QStateMachinePrivate : public QStatePrivate { Q_DECLARE_PUBLIC(QStateMachine) public: @@ -101,7 +99,7 @@ public: static QStateMachinePrivate *get(QStateMachine *q); - static QState *findLCA(const QList<QAbstractState*> &states); + QState *findLCA(const QList<QAbstractState*> &states) const; static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); @@ -116,6 +114,11 @@ public: void _q_animationFinished(); #endif + QState *rootState() const; + + QState *startState(); + void removeStartState(); + void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; @@ -133,11 +136,13 @@ public: bool isInFinalState(QAbstractState *s) const; static bool isFinal(const QAbstractState *s); static bool isParallel(const QAbstractState *s); - static bool isCompound(const QAbstractState *s); - static bool isAtomic(const QAbstractState *s); + bool isCompound(const QAbstractState *s) const; + bool isAtomic(const QAbstractState *s) const; static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other); static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound); + void goToState(QAbstractState *targetState); + void registerTransitions(QAbstractState *state); void registerSignalTransition(QSignalTransition *transition); void unregisterSignalTransition(QSignalTransition *transition); @@ -147,10 +152,11 @@ public: #endif void unregisterTransition(QAbstractTransition *transition); void unregisterAllTransitions(); - void handleTransitionSignal(const QObject *sender, int signalIndex, + void handleTransitionSignal(QObject *sender, int signalIndex, void **args); void scheduleProcess(); +#ifndef QT_NO_PROPERTIES typedef QPair<QObject *, QByteArray> RestorableId; QHash<RestorableId, QVariant> registeredRestorables; void registerRestorable(QObject *object, const QByteArray &propertyName); @@ -158,13 +164,14 @@ public: bool hasRestorable(QObject *object, const QByteArray &propertyName) const; QVariant restorableValue(QObject *object, const QByteArray &propertyName) const; QList<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const; +#endif State state; + QState *_startState; bool processing; bool processingScheduled; bool stop; StopProcessingReason stopProcessingReason; - QState *rootState; QSet<QAbstractState*> configuration; QList<QEvent*> internalEventQueue; QList<QEvent*> externalEventQueue; @@ -207,7 +214,7 @@ public: f_cloneEvent cloneEvent; }; - static Q_CORE_EXPORT const Handler *handler; + static const Handler *handler; }; QT_END_NAMESPACE diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 43ba668..02c7c6f 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -49,6 +49,10 @@ #include <errno.h> +#if defined(Q_OS_VXWORKS) && defined(wakeup) +#undef wakeup +#endif + QT_BEGIN_NAMESPACE static void report_error(int code, const char *where, const char *what) diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index f2022a5..ae79735 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include <windows.h> +#include <qt_windows.h> #include "qmutex.h" #include <qatomic.h> @@ -50,19 +50,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) { - if (QSysInfo::WindowsVersion == 0) { - // mutex was created before initializing WindowsVersion. this - // can happen when creating the resource file engine handler, - // for example. try again with just the A version -#ifdef Q_OS_WINCE - event = CreateEventW(0, FALSE, FALSE, 0); -#else - event = CreateEventA(0, FALSE, FALSE, 0); -#endif - } else { - event = QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0), - CreateEventA(0, FALSE, FALSE, 0)); - } + event = CreateEvent(0, FALSE, FALSE, 0); if (!event) qWarning("QMutexPrivate::QMutexPrivate: Cannot create event"); } diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index 51d42b5..4742bea 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -190,7 +190,8 @@ inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock) class Q_CORE_EXPORT QReadWriteLock { public: - inline explicit QReadWriteLock() { } + enum RecursionMode { NonRecursive, Recursive }; + inline explicit QReadWriteLock(RecursionMode = NonRecursive) { } inline ~QReadWriteLock() { } static inline void lockForRead() { } diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a4a57ce..6eaa55a 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -264,9 +264,14 @@ QThreadPrivate::~QThreadPrivate() Returns the thread handle of the currently executing thread. \warning The handle returned by this function is used for internal - purposes and should not be used in any application code. On - Windows, the returned value is a pseudo-handle for the current - thread that cannot be used for numerical comparison. + purposes and should not be used in any application code. + + \warning On Windows, the returned value is a pseudo-handle for the + current thread. It can't be used for numerical comparison. i.e., + this function returns the DWORD (Windows-Thread ID) returned by + the Win32 function getCurrentThreadId(), not the HANDLE + (Windows-Thread HANDLE) returned by the Win32 function + getCurrentThread(). */ /*! diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 0d8aa8b..c784352 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -127,7 +127,7 @@ protected: private: Q_OBJECT - Q_DECLARE_SCOPED_PRIVATE(QThread) + Q_DECLARE_PRIVATE(QThread) static void initialize(); static void cleanup(); @@ -154,7 +154,7 @@ private: friend class QCoreApplication; friend class QThreadData; friend class QAdoptedThread; - Q_DECLARE_SCOPED_PRIVATE(QThread) + Q_DECLARE_PRIVATE(QThread) }; #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 752796b..a67ae33 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -214,7 +214,7 @@ public: // thread wrapper for the main() thread class QAdoptedThread : public QThread { - Q_DECLARE_SCOPED_PRIVATE(QThread) + Q_DECLARE_PRIVATE(QThread) public: QAdoptedThread(QThreadData *data = 0); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index cabf823..de0575c 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -66,6 +66,13 @@ #ifdef Q_OS_BSD4 #include <sys/sysctl.h> #endif +#ifdef Q_OS_VXWORKS +# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6)) +# include <vxCpuLib.h> +# include <cpuset.h> +# define QT_VXWORKS_HAS_CPUSET +# endif +#endif #if defined(Q_OS_MAC) # ifdef qDebug @@ -90,6 +97,13 @@ static pthread_key_t current_thread_data_key; static void destroy_current_thread_data(void *p) { +#if defined(Q_OS_VXWORKS) + // Calling setspecific(..., 0) sets the value to 0 for ALL threads. + // The 'set to 1' workaround adds a bit of an overhead though, + // since this function is called twice now. + if (p == (void *)1) + return; +#endif // POSIX says the value in our key is set to zero before calling // this destructor function, so we need to set it back to the // right value... @@ -98,7 +112,12 @@ static void destroy_current_thread_data(void *p) // ... but we must reset it to zero before returning so we aren't // called again (POSIX allows implementations to call destructor // functions repeatedly until all values are zero) - pthread_setspecific(current_thread_data_key, 0); + pthread_setspecific(current_thread_data_key, +#if defined(Q_OS_VXWORKS) + (void *)1); +#else + 0); +#endif } static void create_current_thread_data_key() @@ -323,10 +342,28 @@ int QThread::idealThreadCount() // IRIX cores = (int)sysconf(_SC_NPROC_ONLN); #elif defined(Q_OS_INTEGRITY) - // ### TODO - how to get the amound of CPUs on INTEGRITY? + // as of aug 2008 Integrity only supports one single core CPU + cores = 1; #elif defined(Q_OS_SYMBIAN) - // ### TODO - Get the number of cores from HAL? when multicore architectures (SMP) are supported + // ### TODO - Get the number of cores from HAL? when multicore architectures (SMP) are supported + cores = 1; +#elif defined(Q_OS_VXWORKS) + // VxWorks +# if defined(QT_VXWORKS_HAS_CPUSET) + cpuset_t cpus = vxCpuEnabledGet(); + cores = 0; + + // 128 cores should be enough for everyone ;) + for (int i = 0; i < 128 && !CPUSET_ISZERO(cpus); ++i) { + if (CPUSET_ISSET(cpus, i)) { + CPUSET_CLR(cpus, i); + cores++; + } + } +# else + // as of aug 2008 VxWorks < 6.6 only supports one single core CPU cores = 1; +# endif #else // the rest: Linux, Solaris, AIX, Tru64 cores = (int)sysconf(_SC_NPROCESSORS_ONLN); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 8bf6269..d8a1876 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -54,7 +54,7 @@ #include <private/qcoreapplication_p.h> #include <private/qeventdispatcher_win_p.h> -#include <windows.h> +#include <qt_windows.h> #ifndef Q_OS_WINCE @@ -170,8 +170,7 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) // Start watcher thread if it is not already running. if (qt_adopted_thread_watcher_handle == 0) { if (qt_adopted_thread_wakeup == 0) { - qt_adopted_thread_wakeup = QT_WA_INLINE(CreateEventW(0, false, false, 0), - CreateEventA(0, false, false, 0)); + qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0); qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup); } @@ -371,11 +370,10 @@ int QThread::idealThreadCount() void QThread::yieldCurrentThread() { #ifndef Q_OS_WINCE - if (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - SwitchToThread(); - else + SwitchToThread(); +#else + ::Sleep(0); #endif - ::Sleep(0); } void QThread::sleep(unsigned long secs) @@ -426,17 +424,11 @@ void QThread::start(Priority priority) return; } - // Since Win 9x will have problems if the priority is idle or time critical - // we have to use the closest one instead int prio; d->priority = priority; switch (d->priority) { case IdlePriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_LOWEST; - } else { - prio = THREAD_PRIORITY_IDLE; - } + prio = THREAD_PRIORITY_IDLE; break; case LowestPriority: @@ -460,11 +452,7 @@ void QThread::start(Priority priority) break; case TimeCriticalPriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_HIGHEST; - } else { - prio = THREAD_PRIORITY_TIME_CRITICAL; - } + prio = THREAD_PRIORITY_TIME_CRITICAL; break; case InheritPriority: @@ -570,17 +558,11 @@ void QThread::setPriority(Priority priority) // copied from start() with a few modifications: - // Since Win 9x will have problems if the priority is idle or time critical - // we have to use the closest one instead int prio; d->priority = priority; switch (d->priority) { case IdlePriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_LOWEST; - } else { - prio = THREAD_PRIORITY_IDLE; - } + prio = THREAD_PRIORITY_IDLE; break; case LowestPriority: @@ -604,11 +586,7 @@ void QThread::setPriority(Priority priority) break; case TimeCriticalPriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_HIGHEST; - } else { - prio = THREAD_PRIORITY_TIME_CRITICAL; - } + prio = THREAD_PRIORITY_TIME_CRITICAL; break; case InheritPriority: diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 9129fb6..b0146d2 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -64,11 +64,7 @@ class QWaitConditionEvent public: inline QWaitConditionEvent() : priority(0), wokenUp(false) { - QT_WA ({ - event = CreateEvent(NULL, TRUE, FALSE, NULL); - }, { - event = CreateEventA(NULL, TRUE, FALSE, NULL); - }); + event = CreateEvent(NULL, TRUE, FALSE, NULL); } inline ~QWaitConditionEvent() { CloseHandle(event); } int priority; diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h index 697b6ff..4bad24c 100644 --- a/src/corelib/tools/qbytearraymatcher.h +++ b/src/corelib/tools/qbytearraymatcher.h @@ -81,13 +81,14 @@ private: // explicitely allow anonymous unions for RVCT to prevent compiler warnings #pragma anon_unions #endif + struct Data { + uchar q_skiptable[256]; + const uchar *p; + int l; + }; union { uint dummy[256]; - struct { - uchar q_skiptable[256]; - const uchar *p; - int l; - } p; + Data p; }; }; diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h new file mode 100644 index 0000000..f3724f6 --- /dev/null +++ b/src/corelib/tools/qbytedata_p.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBYTEDATA_H +#define QBYTEDATA_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qbytearray.h> + +QT_BEGIN_NAMESPACE + +// this class handles a list of QByteArrays. It is a variant of QRingBuffer +// that avoid malloc/realloc/memcpy. +class QByteDataBuffer +{ +private: + QList<QByteArray> buffers; + qint64 bufferCompleteSize; +public: + QByteDataBuffer() : bufferCompleteSize(0) + { + } + + ~QByteDataBuffer() + { + clear(); + } + + inline void append(QByteDataBuffer& other) + { + if (other.isEmpty()) + return; + + buffers.append(other.buffers); + bufferCompleteSize += other.byteAmount(); + } + + + inline void append(QByteArray& bd) + { + if (bd.isEmpty()) + return; + + buffers.append(bd); + bufferCompleteSize += bd.size(); + } + + inline void prepend(QByteArray& bd) + { + if (bd.isEmpty()) + return; + + buffers.prepend(bd); + bufferCompleteSize += bd.size(); + } + + // return the first QByteData. User of this function has to qFree() its .data! + // preferably use this function to read data. + inline QByteArray read() + { + bufferCompleteSize -= buffers.first().size(); + return buffers.takeFirst(); + } + + // return everything. User of this function has to qFree() its .data! + // avoid to use this, it might malloc and memcpy. + inline QByteArray readAll() + { + return read(byteAmount()); + } + + // return amount. User of this function has to qFree() its .data! + // avoid to use this, it might malloc and memcpy. + inline QByteArray read(qint64 amount) + { + amount = qMin(byteAmount(), amount); + QByteArray byteData; + byteData.resize(amount); + read(byteData.data(), byteData.size()); + return byteData; + } + + // return amount bytes. User of this function has to qFree() its .data! + // avoid to use this, it will memcpy. + qint64 read(char* dst, qint64 amount) + { + amount = qMin(amount, byteAmount()); + qint64 originalAmount = amount; + char *writeDst = dst; + + while (amount > 0) { + QByteArray first = buffers.takeFirst(); + if (amount >= first.size()) { + // take it completely + bufferCompleteSize -= first.size(); + amount -= first.size(); + memcpy(writeDst, first.constData(), first.size()); + writeDst += first.size(); + first.clear(); + } else { + // take a part of it & it is the last one to take + bufferCompleteSize -= amount; + memcpy(writeDst, first.constData(), amount); + + qint64 newFirstSize = first.size() - amount; + QByteArray newFirstData; + newFirstData.resize(newFirstSize); + memcpy(newFirstData.data(), first.constData() + amount, newFirstSize); + buffers.prepend(newFirstData); + + amount = 0; + first.clear(); + } + } + + return originalAmount; + } + + inline char getChar() + { + char c; + read(&c, 1); + return c; + } + + inline void clear() + { + buffers.clear(); + bufferCompleteSize = 0; + } + + // The byte count of all QByteArrays + inline qint64 byteAmount() const + { + return bufferCompleteSize; + } + + // the number of QByteArrays + inline qint64 bufferCount() const + { + return buffers.length(); + } + + inline bool isEmpty() const + { + return byteAmount() == 0; + } + + inline qint64 sizeNextBlock() const + { + if(buffers.isEmpty()) + return 0; + else + return buffers.first().size(); + } + + inline QByteArray& operator[](int i) + { + return buffers[i]; + } +}; + +QT_END_NAMESPACE + +#endif // QBYTEDATA_H diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 88053d6..458a383 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1421,16 +1421,15 @@ QDataStream &operator>>(QDataStream &in, QChar &chr) // --------------------------------------------------------------------------- -static QString decomposeHelper - (const QString &str, bool canonical, QChar::UnicodeVersion version) +static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from) { unsigned short buffer[3]; - QString s = str; + QString &s = *str; - const unsigned short *utf16 = s.utf16(); + const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data()); const unsigned short *uc = utf16 + s.length(); - while (uc != utf16) { + while (uc != utf16 + from) { uint ucs4 = *(--uc); if (QChar(ucs4).isLowSurrogate() && uc != utf16) { ushort high = *(uc - 1); @@ -1450,11 +1449,9 @@ static QString decomposeHelper s.replace(uc - utf16, ucs4 > 0x10000 ? 2 : 1, (const QChar *)d, length); // since the insert invalidates the pointers and we do decomposition recursive int pos = uc - utf16; - utf16 = s.utf16(); + utf16 = reinterpret_cast<unsigned short *>(s.data()); uc = utf16 + pos + length; } - - return s; } @@ -1489,21 +1486,21 @@ static ushort ligatureHelper(ushort u1, ushort u2) return 0; } -static QString composeHelper(const QString &str) +static void composeHelper(QString *str, int from) { - QString s = str; + QString &s = *str; - if (s.length() < 2) - return s; + if (s.length() - from < 2) + return; // the loop can partly ignore high Unicode as all ligatures are in the BMP int starter = 0; int lastCombining = 0; - int pos = 0; + int pos = from; while (pos < s.length()) { - uint uc = s.utf16()[pos]; + uint uc = s.at(pos).unicode(); if (QChar(uc).isHighSurrogate() && pos < s.length()-1) { - ushort low = s.utf16()[pos+1]; + ushort low = s.at(pos+1).unicode(); if (QChar(low).isLowSurrogate()) { uc = QChar::surrogateToUcs4(uc, low); ++pos; @@ -1512,7 +1509,7 @@ static QString composeHelper(const QString &str) int combining = QChar::combiningClass(uc); if (starter == pos - 1 || combining > lastCombining) { // allowed to form ligature with S - QChar ligature = ligatureHelper(s.utf16()[starter], uc); + QChar ligature = ligatureHelper(s.at(starter).unicode(), uc); if (ligature.unicode()) { s[starter] = ligature; s.remove(pos, 1); @@ -1524,16 +1521,14 @@ static QString composeHelper(const QString &str) lastCombining = combining; ++pos; } - return s; } -static QString canonicalOrderHelper - (const QString &str, QChar::UnicodeVersion version) +static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from) { - QString s = str; + QString &s = *str; const int l = s.length()-1; - int pos = 0; + int pos = from; while (pos < l) { int p2 = pos+1; uint u1 = s.at(pos).unicode(); @@ -1593,7 +1588,6 @@ static QString canonicalOrderHelper ++pos; } } - return s; } int QT_FASTCALL QUnicodeTables::script(unsigned int uc) diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index e738ec8..f42b7a0 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -61,6 +61,7 @@ void QContiguousCacheData::dump() const \ingroup tools \ingroup shared \reentrant + \since 4.6 The QContiguousCache class provides an efficient way of caching items for display in a user interface view. Unlike QCache, it adds a restriction @@ -95,7 +96,7 @@ MyRecord record(int row) const 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 + 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 @@ -104,9 +105,9 @@ MyRecord record(int row) const 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() + lastIndex(), at() or \l{QContiguousCache::operator[]()}{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. @@ -190,8 +191,6 @@ MyRecord record(int row) const /*! \fn int QContiguousCache::count() const - \overload - Same as size(). */ @@ -258,14 +257,15 @@ MyRecord record(int row) const /*! \fn T &QContiguousCache::operator[](int i) - Returns the item at index position \a i as a modifiable reference. If + 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. + \note This non-const overload of operator[] requires QContiguousCache + to make a deep copy. Use at() for read-only access to a non-const + QContiguousCache. \sa insert(), at() */ diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 7d52f1e..7221925 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -44,6 +44,7 @@ #include <QtCore/qatomic.h> #include <limits.h> +#include <new> QT_BEGIN_HEADER @@ -76,6 +77,12 @@ struct QContiguousCacheTypedData int start; int offset; uint sharable : 1; + // uint unused : 31; + + // total is 24 bytes (HP-UX aCC: 40 bytes) + // the next entry is already aligned to 8 bytes + // there will be an 8 byte gap here if T requires 16-byte alignment + // (such as long double on 64-bit platforms, __int128, __float128) T array[1]; }; @@ -166,8 +173,8 @@ void QContiguousCache<T>::detach_helper() T *dest = x.d->array + x.d->start; T *src = d->array + d->start; - int count = x.d->count; - while (count--) { + int oldcount = x.d->count; + while (oldcount--) { if (QTypeInfo<T>::isComplex) { new (dest) T(*src); } else { @@ -200,8 +207,8 @@ void QContiguousCache<T>::setCapacity(int asize) 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--) { + int oldcount = x.d->count; + while (oldcount--) { if (QTypeInfo<T>::isComplex) { new (dest) T(*src); } else { @@ -224,10 +231,10 @@ void QContiguousCache<T>::clear() { if (d->ref == 1) { if (QTypeInfo<T>::isComplex) { - int count = d->count; + int oldcount = d->count; T * i = d->array + d->start; T * e = d->array + d->alloc; - while (count--) { + while (oldcount--) { i->~T(); i++; if (i == e) @@ -254,11 +261,11 @@ inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc) } template <typename T> -QContiguousCache<T>::QContiguousCache(int capacity) +QContiguousCache<T>::QContiguousCache(int cap) { - p = malloc(capacity); + p = malloc(cap); d->ref = 1; - d->alloc = capacity; + d->alloc = cap; d->count = d->start = d->offset = 0; d->sharable = true; } @@ -295,10 +302,10 @@ template <typename T> void QContiguousCache<T>::free(Data *x) { if (QTypeInfo<T>::isComplex) { - int count = d->count; + int oldcount = d->count; T * i = d->array + d->start; T * e = d->array + d->alloc; - while (count--) { + while (oldcount--) { i->~T(); i++; if (i == e) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 6e4aaeb..d43b376 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -49,7 +49,7 @@ #include "qregexp.h" #include "qdebug.h" #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) -#include <windows.h> +#include <qt_windows.h> #endif #ifndef Q_WS_WIN #include <locale.h> @@ -2502,16 +2502,9 @@ QString QDateTime::toString(Qt::DateFormat f) const buf += QLatin1Char(' '); buf += QString::number(d->date.day()); #else - QString winstr; - QT_WA({ - TCHAR out[255]; - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); - winstr = QString::fromUtf16((ushort*)out); - } , { - char out[255]; - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255); - winstr = QString::fromLocal8Bit(out); - }); + wchar_t out[255]; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); + QString winstr = QString::fromWCharArray(out); switch (winstr.toInt()) { case 1: buf = d->date.shortDayName(d->date.dayOfWeek()); diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 18a252a..0828c61 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -60,8 +60,10 @@ Easing curves describe a function that controls how the speed of the interpolation between 0 and 1 should be. Easing curves allow transitions from one value to another to appear more natural than a simple constant speed would allow. - The QEasingCurve class is usually used in conjunction with the QAnimation class, - but can be used on its own. + The QEasingCurve class is usually used in conjunction with the QVariantAnimation and + QPropertyAnimation classes but can be used on its own. It is usually used to accelerate + the interpolation from zero velocity (ease in) or decelerate to zero velocity (ease out). + Ease in and ease out can also be combined in the same easing curve. To calculate the speed of the interpolation, the easing curve provides the function valueForProgress(), where the \a progress argument specifies the progress of the @@ -80,10 +82,10 @@ \endcode will print the effective progress of the interpolation between 0 and 1. - When using a QAnimation, the easing curve will be used to control the + When using a QPropertyAnimation, the associated easing curve will be used to control the progress of the interpolation between startValue and endValue: \code - QAnimation animation; + QPropertyAnimation animation; animation.setStartValue(0); animation.setEndValue(1000); animation.setDuration(1000); @@ -98,189 +100,191 @@ \value Linear \inlineimage qeasingcurve-linear.png \br - Easing equation function for a simple linear tweening, - with no easing. + Easing curve for a linear (t) function: + velocity is constant. \value InQuad \inlineimage qeasingcurve-inquad.png \br - Easing equation function for a quadratic (t^2) easing - in: accelerating from zero velocity. + Easing curve for a quadratic (t^2) function: + accelerating from zero velocity. \value OutQuad \inlineimage qeasingcurve-outquad.png \br - Easing equation function for a quadratic (t^2) easing - out: decelerating to zero velocity. + Easing curve for a quadratic (t^2) function: + decelerating to zero velocity. \value InOutQuad \inlineimage qeasingcurve-inoutquad.png \br - Easing equation function for a quadratic (t^2) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a quadratic (t^2) function: + acceleration until halfway, then deceleration. \value OutInQuad \inlineimage qeasingcurve-outinquad.png \br - Easing equation function for a quadratic (t^2) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a quadratic (t^2) function: + deceleration until halfway, then acceleration. \value InCubic \inlineimage qeasingcurve-incubic.png \br - Easing equation function for a cubic (t^3) easing - in: accelerating from zero velocity. + Easing curve for a cubic (t^3) function: + accelerating from zero velocity. \value OutCubic \inlineimage qeasingcurve-outcubic.png \br - Easing equation function for a cubic (t^3) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^3) function: + decelerating from zero velocity. \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png \br - Easing equation function for a cubic (t^3) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^3) function: + acceleration until halfway, then deceleration. \value OutInCubic \inlineimage qeasingcurve-outincubic.png \br - Easing equation function for a cubic (t^3) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^3) function: + deceleration until halfway, then acceleration. \value InQuart \inlineimage qeasingcurve-inquart.png \br - Easing equation function for a quartic (t^4) easing - in: accelerating from zero velocity. + Easing curve for a quartic (t^4) function: + accelerating from zero velocity. \value OutQuart \inlineimage qeasingcurve-outquart.png \br - Easing equation function for a quartic (t^4) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^4) function: + decelerating from zero velocity. \value InOutQuart \inlineimage qeasingcurve-inoutquart.png \br - Easing equation function for a quartic (t^4) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^4) function: + acceleration until halfway, then deceleration. \value OutInQuart \inlineimage qeasingcurve-outinquart.png \br - Easing equation function for a quartic (t^4) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^4) function: + deceleration until halfway, then acceleration. \value InQuint \inlineimage qeasingcurve-inquint.png \br - Easing equation function for a quintic (t^5) easing + Easing curve for a quintic (t^5) easing in: accelerating from zero velocity. \value OutQuint \inlineimage qeasingcurve-outquint.png \br - Easing equation function for a quintic (t^5) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^5) function: + decelerating from zero velocity. \value InOutQuint \inlineimage qeasingcurve-inoutquint.png \br - Easing equation function for a quintic (t^5) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^5) function: + acceleration until halfway, then deceleration. \value OutInQuint \inlineimage qeasingcurve-outinquint.png \br - Easing equation function for a quintic (t^5) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^5) function: + deceleration until halfway, then acceleration. \value InSine \inlineimage qeasingcurve-insine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - in: accelerating from zero velocity. + Easing curve for a sinusoidal (sin(t)) function: + accelerating from zero velocity. \value OutSine \inlineimage qeasingcurve-outsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - out: decelerating from zero velocity. + Easing curve for a sinusoidal (sin(t)) function: + decelerating from zero velocity. \value InOutSine \inlineimage qeasingcurve-inoutsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a sinusoidal (sin(t)) function: + acceleration until halfway, then deceleration. \value OutInSine \inlineimage qeasingcurve-outinsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a sinusoidal (sin(t)) function: + deceleration until halfway, then acceleration. \value InExpo \inlineimage qeasingcurve-inexpo.png \br - Easing equation function for an exponential (2^t) easing - in: accelerating from zero velocity. + Easing curve for an exponential (2^t) function: + accelerating from zero velocity. \value OutExpo \inlineimage qeasingcurve-outexpo.png \br - Easing equation function for an exponential (2^t) easing - out: decelerating from zero velocity. + Easing curve for an exponential (2^t) function: + decelerating from zero velocity. \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png \br - Easing equation function for an exponential (2^t) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for an exponential (2^t) function: + acceleration until halfway, then deceleration. \value OutInExpo \inlineimage qeasingcurve-outinexpo.png \br - Easing equation function for an exponential (2^t) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for an exponential (2^t) function: + deceleration until halfway, then acceleration. \value InCirc \inlineimage qeasingcurve-incirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - in: accelerating from zero velocity. + Easing curve for a circular (sqrt(1-t^2)) function: + accelerating from zero velocity. \value OutCirc \inlineimage qeasingcurve-outcirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - out: decelerating from zero velocity. + Easing curve for a circular (sqrt(1-t^2)) function: + decelerating from zero velocity. \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a circular (sqrt(1-t^2)) function: + acceleration until halfway, then deceleration. \value OutInCirc \inlineimage qeasingcurve-outincirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a circular (sqrt(1-t^2)) function: + deceleration until halfway, then acceleration. \value InElastic \inlineimage qeasingcurve-inelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing in: + Easing curve for an elastic + (exponentially decaying sine wave) function: accelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. \value OutElastic \inlineimage qeasingcurve-outelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing out: + Easing curve for an elastic + (exponentially decaying sine wave) function: decelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing in/out: + Easing curve for an elastic + (exponentially decaying sine wave) function: acceleration until halfway, then deceleration. \value OutInElastic \inlineimage qeasingcurve-outinelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing out/in: + Easing curve for an elastic + (exponentially decaying sine wave) function: deceleration until halfway, then acceleration. \value InBack \inlineimage qeasingcurve-inback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing in: + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity. \value OutBack \inlineimage qeasingcurve-outback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing out: - decelerating from zero velocity. + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing out: + decelerating to zero velocity. \value InOutBack \inlineimage qeasingcurve-inoutback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing in/out: + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration. \value OutInBack \inlineimage qeasingcurve-outinback.png \br - Easing equation function for a back (overshooting + Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration. \value InBounce \inlineimage qeasingcurve-inbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing in: accelerating + Easing curve for a bounce (exponentially + decaying parabolic bounce) function: accelerating from zero velocity. \value OutBounce \inlineimage qeasingcurve-outbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing out: decelerating + Easing curve for a bounce (exponentially + decaying parabolic bounce) function: decelerating from zero velocity. \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing in/out: + Easing curve for a bounce (exponentially + decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration. \value OutInBounce \inlineimage qeasingcurve-outinbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing out/in: + Easing curve for a bounce (exponentially + decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration. \omitvalue InCurve \omitvalue OutCurve \omitvalue SineCurve \omitvalue CosineCurve - \value Custom This is returned if the user have specified a custom curve type with setCustomType(). Note that you cannot call setType() with this value, but type() can return it. + \value Custom This is returned if the user specified a custom curve type with + setCustomType(). Note that you cannot call setType() with this value, + but type() can return it. \omitvalue NCurveTypes */ diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index a8fac2d..18e608d 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -393,15 +393,8 @@ static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT); static QString getWinLocaleInfo(LCTYPE type) { - int cnt = 0; - LCID id = GetUserDefaultLCID(); - - QT_WA({ - cnt = GetLocaleInfoW(id, type, 0, 0)*2; - } , { - cnt = GetLocaleInfoA(id, type, 0, 0); - }); + int cnt = GetLocaleInfo(id, type, 0, 0) * 2; if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", (int)type); @@ -410,27 +403,14 @@ static QString getWinLocaleInfo(LCTYPE type) QByteArray buff(cnt, 0); - QT_WA({ - cnt = GetLocaleInfoW(id, type, - reinterpret_cast<wchar_t*>(buff.data()), - buff.size()/2); - } , { - cnt = GetLocaleInfoA(id, type, - buff.data(), buff.size()); - }); + cnt = GetLocaleInfo(id, type, reinterpret_cast<wchar_t*>(buff.data()), buff.size() / 2); if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", (int)type); return QString(); } - QString result; - QT_WA({ - result = QString::fromUtf16(reinterpret_cast<ushort*>(buff.data())); - } , { - result = QString::fromLocal8Bit(buff.data()); - }); - return result; + return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buff.data())); } QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) @@ -440,8 +420,8 @@ QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) result = envVarLocale(); QChar lang[3]; QChar cntry[2]; - if ( result == "C" || !result.isEmpty() - && splitLocaleName(QString::fromLocal8Bit(result), lang, cntry) ) { + if ( result == "C" || (!result.isEmpty() + && splitLocaleName(QString::fromLocal8Bit(result), lang, cntry)) ) { long id = 0; bool ok = false; id = qstrtoll(result.data(), 0, 0, &ok); @@ -452,20 +432,19 @@ QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) } } - if (QSysInfo::WindowsVersion == QSysInfo::WV_95 - || (QSysInfo::WindowsVersion & QSysInfo::WV_CE_based)) { - result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); - } else { - if (id == LOCALE_USER_DEFAULT) - id = GetUserDefaultLCID(); - QString resultuage = winIso639LangName(id); - QString country = winIso3116CtryName(id); - result = resultuage.toLatin1(); - if (!country.isEmpty()) { - result += '_'; - result += country.toLatin1(); - } +#if defined(Q_OS_WINCE) + result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); +#else + if (id == LOCALE_USER_DEFAULT) + id = GetUserDefaultLCID(); + QString resultuage = winIso639LangName(id); + QString country = winIso3116CtryName(id); + result = resultuage.toLatin1(); + if (!country.isEmpty()) { + result += '_'; + result += country.toLatin1(); } +#endif return result; } @@ -551,15 +530,9 @@ static QString winDateToString(const QDate &date, DWORD flags) LCID id = GetUserDefaultLCID(); - QT_WA({ - TCHAR buf[255]; - if (GetDateFormatW(id, flags, &st, 0, buf, 255)) - return QString::fromUtf16((ushort*)buf); - } , { - char buf[255]; - if (GetDateFormatA(id, flags, &st, 0, (char*)&buf, 255)) - return QString::fromLocal8Bit(buf); - }); + wchar_t buf[255]; + if (GetDateFormat(id, flags, &st, 0, buf, 255)) + return QString::fromWCharArray(buf); return QString(); } @@ -576,15 +549,9 @@ static QString winTimeToString(const QTime &time) DWORD flags = 0; LCID id = GetUserDefaultLCID(); - QT_WA({ - TCHAR buf[255]; - if (GetTimeFormatW(id, flags, &st, 0, buf, 255)) - return QString::fromUtf16((ushort*)buf); - } , { - char buf[255]; - if (GetTimeFormatA(id, flags, &st, 0, (char*)&buf, 255)) - return QString::fromLocal8Bit(buf); - }); + wchar_t buf[255]; + if (GetTimeFormat(id, flags, &st, 0, buf, 255)) + return QString::fromWCharArray(buf); return QString(); } @@ -633,12 +600,10 @@ static QString winMonthName(int month, bool short_format) static QLocale::MeasurementSystem winSystemMeasurementSystem() { LCID id = GetUserDefaultLCID(); - TCHAR output[2]; + wchar_t output[2]; if (GetLocaleInfo(id, LOCALE_IMEASURE, output, 2)) { - QString iMeasure = QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast<ushort*>(output)), - QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + QString iMeasure = QString::fromWCharArray(output); if (iMeasure == QLatin1String("1")) { return QLocale::ImperialSystem; } @@ -650,12 +615,10 @@ static QLocale::MeasurementSystem winSystemMeasurementSystem() static QString winSystemAMText() { LCID id = GetUserDefaultLCID(); - TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + wchar_t output[15]; // maximum length including terminating zero character for Win2003+ if (GetLocaleInfo(id, LOCALE_S1159, output, 15)) { - return QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast<ushort*>(output)), - QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + return QString::fromWCharArray(output); } return QString(); @@ -664,12 +627,10 @@ static QString winSystemAMText() static QString winSystemPMText() { LCID id = GetUserDefaultLCID(); - TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + wchar_t output[15]; // maximum length including terminating zero character for Win2003+ if (GetLocaleInfo(id, LOCALE_S2359, output, 15)) { - return QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast<ushort*>(output)), - QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + return QString::fromWCharArray(output); } return QString(); @@ -773,9 +734,6 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const return QVariant(); } -/* Win95 doesn't have a function to return the ISO lang/country name of the user's locale. - Instead it can return a "Windows code". This maps windows codes to ISO country names. */ - struct WindowsToISOListElt { ushort windows_code; char iso_name[6]; @@ -931,15 +889,9 @@ static QString winIso639LangName(LCID id) // Windows returns the wrong ISO639 for some languages, we need to detect them here using // the language code QString lang_code; - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_ILANGUAGE, out, 255)) - lang_code = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_ILANGUAGE, out, 255)) - lang_code = QString::fromLocal8Bit(out); - }); + wchar_t out[256]; + if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) + lang_code = QString::fromWCharArray(out); if (!lang_code.isEmpty()) { const char *endptr; @@ -961,15 +913,8 @@ static QString winIso639LangName(LCID id) return result; // not one of the problematic languages - do the usual lookup - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_SISO639LANGNAME , out, 255)) - result = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_SISO639LANGNAME, out, 255)) - result = QString::fromLocal8Bit(out); - }); + if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255)) + result = QString::fromWCharArray(out); return result; } @@ -978,15 +923,9 @@ static QString winIso3116CtryName(LCID id) { QString result; - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_SISO3166CTRYNAME, out, 255)) - result = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_SISO3166CTRYNAME, out, 255)) - result = QString::fromLocal8Bit(out); - }); + wchar_t out[256]; + if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255)) + result = QString::fromWCharArray(out); return result; } @@ -2696,7 +2635,7 @@ static QString timeZone() DWORD res = GetTimeZoneInformation(&info); if (res == TIME_ZONE_ID_UNKNOWN) return QString(); - return QString::fromUtf16(reinterpret_cast<const ushort *> (info.StandardName)); + return QString::fromWCharArray(info.StandardName); #elif defined(Q_OS_WIN) _tzset(); # if defined(_MSC_VER) && _MSC_VER >= 1400 @@ -2708,6 +2647,8 @@ static QString timeZone() # else return QString::fromLocal8Bit(_tzname[1]); # endif +#elif defined(Q_OS_VXWORKS) + return QString(); #else tzset(); return QString::fromLocal8Bit(tzname[1]); @@ -5012,6 +4953,9 @@ static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c) #define Bletch 0x10 #define Bndry_mask 0xfffff #define Bndry_mask1 0xfffff +#if defined(LSB) && defined(Q_OS_VXWORKS) +#undef LSB +#endif #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 1 @@ -5374,7 +5318,11 @@ struct p5s_deleter { ~p5s_deleter() { - Bfree(p5s); + while (p5s) { + Bigint *next = p5s->next; + Bfree(p5s); + p5s = next; + } } }; diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp index 95d4edf..dc9692b 100644 --- a/src/corelib/tools/qlocale_symbian.cpp +++ b/src/corelib/tools/qlocale_symbian.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp index 49afdca..af60f52 100644 --- a/src/corelib/tools/qpoint.cpp +++ b/src/corelib/tools/qpoint.cpp @@ -444,6 +444,8 @@ QDebug operator<<(QDebug d, const QPointF &p) /*! + \since 4.6 + Returns the sum of the absolute values of x() and y(), traditionally known as the "Manhattan length" of the vector from the origin to the point. diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index d980a9b..0ac4fa2 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -70,6 +70,8 @@ int qFindString(const QChar *haystack, int haystackLen, int from, #define RXERR_LEFTDELIM QT_TRANSLATE_NOOP("QRegExp", "missing left delim") #define RXERR_END QT_TRANSLATE_NOOP("QRegExp", "unexpected end") #define RXERR_LIMIT QT_TRANSLATE_NOOP("QRegExp", "met internal limit") +#define RXERR_INTERVAL QT_TRANSLATE_NOOP("QRegExp", "invalid interval") +#define RXERR_CATEGORY QT_TRANSLATE_NOOP("QRegExp", "invalid category") /* WARNING! Be sure to read qregexp.tex before modifying this file. @@ -686,6 +688,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, {tools/regexp}{Regular Expression Example} */ +#if defined(Q_OS_VXWORKS) && defined(EOS) +# undef EOS +#endif + const int NumBadChars = 64; #define BadChar(ch) ((ch).unicode() % NumBadChars) @@ -1116,6 +1122,7 @@ private: bool valid; // is the regular expression valid? Qt::CaseSensitivity cs; // case sensitive? bool greedyQuantifiers; // RegExp2? + bool xmlSchemaExtensions; #ifndef QT_NO_REGEXP_BACKREF int nbrefs; // number of back-references #endif @@ -1193,6 +1200,8 @@ private: friend class Box; + void setupCategoriesRangeMap(); + /* This is the lexical analyzer for regular expressions. */ @@ -1232,6 +1241,7 @@ private: int yyTok; // the last token read bool yyMayCapture; // set this to false to disable capturing + QHash<QByteArray, QPair<int, int> > categoriesRangeMap; // fast lookup hash for xml schema extensions friend struct QRegExpMatchState; }; @@ -1253,7 +1263,8 @@ struct QRegExpLookahead #endif QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) - : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2) + : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2), + xmlSchemaExtensions(false) { setup(); @@ -1268,6 +1279,8 @@ QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) case QRegExp::FixedString: rx = QRegExp::escape(key.pattern); break; + case QRegExp::W3CXmlSchema11: + xmlSchemaExtensions = true; default: rx = key.pattern; } @@ -1484,9 +1497,8 @@ int QRegExpEngine::anchorAlternation(int a, int b) return Anchor_Alternation | (n - 1); #endif - aa.resize(n + 1); - aa[n].a = a; - aa[n].b = b; + QRegExpAnchorAlternation element = {a, b}; + aa.append(element); return Anchor_Alternation | n; } @@ -2626,6 +2638,152 @@ void QRegExpEngine::Box::addAnchorsToEngine(const Box &to) const } } +void QRegExpEngine::setupCategoriesRangeMap() +{ + categoriesRangeMap.insert("IsBasicLatin", qMakePair(0x0000, 0x007F)); + categoriesRangeMap.insert("IsLatin-1Supplement", qMakePair(0x0080, 0x00FF)); + categoriesRangeMap.insert("IsLatinExtended-A", qMakePair(0x0100, 0x017F)); + categoriesRangeMap.insert("IsLatinExtended-B", qMakePair(0x0180, 0x024F)); + categoriesRangeMap.insert("IsIPAExtensions", qMakePair(0x0250, 0x02AF)); + categoriesRangeMap.insert("IsSpacingModifierLetters", qMakePair(0x02B0, 0x02FF)); + categoriesRangeMap.insert("IsCombiningDiacriticalMarks", qMakePair(0x0300, 0x036F)); + categoriesRangeMap.insert("IsGreek", qMakePair(0x0370, 0x03FF)); + categoriesRangeMap.insert("IsCyrillic", qMakePair(0x0400, 0x04FF)); + categoriesRangeMap.insert("IsCyrillicSupplement", qMakePair(0x0500, 0x052F)); + categoriesRangeMap.insert("IsArmenian", qMakePair(0x0530, 0x058F)); + categoriesRangeMap.insert("IsHebrew", qMakePair(0x0590, 0x05FF)); + categoriesRangeMap.insert("IsArabic", qMakePair(0x0600, 0x06FF)); + categoriesRangeMap.insert("IsSyriac", qMakePair(0x0700, 0x074F)); + categoriesRangeMap.insert("IsArabicSupplement", qMakePair(0x0750, 0x077F)); + categoriesRangeMap.insert("IsThaana", qMakePair(0x0780, 0x07BF)); + categoriesRangeMap.insert("IsDevanagari", qMakePair(0x0900, 0x097F)); + categoriesRangeMap.insert("IsBengali", qMakePair(0x0980, 0x09FF)); + categoriesRangeMap.insert("IsGurmukhi", qMakePair(0x0A00, 0x0A7F)); + categoriesRangeMap.insert("IsGujarati", qMakePair(0x0A80, 0x0AFF)); + categoriesRangeMap.insert("IsOriya", qMakePair(0x0B00, 0x0B7F)); + categoriesRangeMap.insert("IsTamil", qMakePair(0x0B80, 0x0BFF)); + categoriesRangeMap.insert("IsTelugu", qMakePair(0x0C00, 0x0C7F)); + categoriesRangeMap.insert("IsKannada", qMakePair(0x0C80, 0x0CFF)); + categoriesRangeMap.insert("IsMalayalam", qMakePair(0x0D00, 0x0D7F)); + categoriesRangeMap.insert("IsSinhala", qMakePair(0x0D80, 0x0DFF)); + categoriesRangeMap.insert("IsThai", qMakePair(0x0E00, 0x0E7F)); + categoriesRangeMap.insert("IsLao", qMakePair(0x0E80, 0x0EFF)); + categoriesRangeMap.insert("IsTibetan", qMakePair(0x0F00, 0x0FFF)); + categoriesRangeMap.insert("IsMyanmar", qMakePair(0x1000, 0x109F)); + categoriesRangeMap.insert("IsGeorgian", qMakePair(0x10A0, 0x10FF)); + categoriesRangeMap.insert("IsHangulJamo", qMakePair(0x1100, 0x11FF)); + categoriesRangeMap.insert("IsEthiopic", qMakePair(0x1200, 0x137F)); + categoriesRangeMap.insert("IsEthiopicSupplement", qMakePair(0x1380, 0x139F)); + categoriesRangeMap.insert("IsCherokee", qMakePair(0x13A0, 0x13FF)); + categoriesRangeMap.insert("IsUnifiedCanadianAboriginalSyllabics", qMakePair(0x1400, 0x167F)); + categoriesRangeMap.insert("IsOgham", qMakePair(0x1680, 0x169F)); + categoriesRangeMap.insert("IsRunic", qMakePair(0x16A0, 0x16FF)); + categoriesRangeMap.insert("IsTagalog", qMakePair(0x1700, 0x171F)); + categoriesRangeMap.insert("IsHanunoo", qMakePair(0x1720, 0x173F)); + categoriesRangeMap.insert("IsBuhid", qMakePair(0x1740, 0x175F)); + categoriesRangeMap.insert("IsTagbanwa", qMakePair(0x1760, 0x177F)); + categoriesRangeMap.insert("IsKhmer", qMakePair(0x1780, 0x17FF)); + categoriesRangeMap.insert("IsMongolian", qMakePair(0x1800, 0x18AF)); + categoriesRangeMap.insert("IsLimbu", qMakePair(0x1900, 0x194F)); + categoriesRangeMap.insert("IsTaiLe", qMakePair(0x1950, 0x197F)); + categoriesRangeMap.insert("IsNewTaiLue", qMakePair(0x1980, 0x19DF)); + categoriesRangeMap.insert("IsKhmerSymbols", qMakePair(0x19E0, 0x19FF)); + categoriesRangeMap.insert("IsBuginese", qMakePair(0x1A00, 0x1A1F)); + categoriesRangeMap.insert("IsPhoneticExtensions", qMakePair(0x1D00, 0x1D7F)); + categoriesRangeMap.insert("IsPhoneticExtensionsSupplement", qMakePair(0x1D80, 0x1DBF)); + categoriesRangeMap.insert("IsCombiningDiacriticalMarksSupplement", qMakePair(0x1DC0, 0x1DFF)); + categoriesRangeMap.insert("IsLatinExtendedAdditional", qMakePair(0x1E00, 0x1EFF)); + categoriesRangeMap.insert("IsGreekExtended", qMakePair(0x1F00, 0x1FFF)); + categoriesRangeMap.insert("IsGeneralPunctuation", qMakePair(0x2000, 0x206F)); + categoriesRangeMap.insert("IsSuperscriptsandSubscripts", qMakePair(0x2070, 0x209F)); + categoriesRangeMap.insert("IsCurrencySymbols", qMakePair(0x20A0, 0x20CF)); + categoriesRangeMap.insert("IsCombiningMarksforSymbols", qMakePair(0x20D0, 0x20FF)); + categoriesRangeMap.insert("IsLetterlikeSymbols", qMakePair(0x2100, 0x214F)); + categoriesRangeMap.insert("IsNumberForms", qMakePair(0x2150, 0x218F)); + categoriesRangeMap.insert("IsArrows", qMakePair(0x2190, 0x21FF)); + categoriesRangeMap.insert("IsMathematicalOperators", qMakePair(0x2200, 0x22FF)); + categoriesRangeMap.insert("IsMiscellaneousTechnical", qMakePair(0x2300, 0x23FF)); + categoriesRangeMap.insert("IsControlPictures", qMakePair(0x2400, 0x243F)); + categoriesRangeMap.insert("IsOpticalCharacterRecognition", qMakePair(0x2440, 0x245F)); + categoriesRangeMap.insert("IsEnclosedAlphanumerics", qMakePair(0x2460, 0x24FF)); + categoriesRangeMap.insert("IsBoxDrawing", qMakePair(0x2500, 0x257F)); + categoriesRangeMap.insert("IsBlockElements", qMakePair(0x2580, 0x259F)); + categoriesRangeMap.insert("IsGeometricShapes", qMakePair(0x25A0, 0x25FF)); + categoriesRangeMap.insert("IsMiscellaneousSymbols", qMakePair(0x2600, 0x26FF)); + categoriesRangeMap.insert("IsDingbats", qMakePair(0x2700, 0x27BF)); + categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-A", qMakePair(0x27C0, 0x27EF)); + categoriesRangeMap.insert("IsSupplementalArrows-A", qMakePair(0x27F0, 0x27FF)); + categoriesRangeMap.insert("IsBraillePatterns", qMakePair(0x2800, 0x28FF)); + categoriesRangeMap.insert("IsSupplementalArrows-B", qMakePair(0x2900, 0x297F)); + categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-B", qMakePair(0x2980, 0x29FF)); + categoriesRangeMap.insert("IsSupplementalMathematicalOperators", qMakePair(0x2A00, 0x2AFF)); + categoriesRangeMap.insert("IsMiscellaneousSymbolsandArrows", qMakePair(0x2B00, 0x2BFF)); + categoriesRangeMap.insert("IsGlagolitic", qMakePair(0x2C00, 0x2C5F)); + categoriesRangeMap.insert("IsCoptic", qMakePair(0x2C80, 0x2CFF)); + categoriesRangeMap.insert("IsGeorgianSupplement", qMakePair(0x2D00, 0x2D2F)); + categoriesRangeMap.insert("IsTifinagh", qMakePair(0x2D30, 0x2D7F)); + categoriesRangeMap.insert("IsEthiopicExtended", qMakePair(0x2D80, 0x2DDF)); + categoriesRangeMap.insert("IsSupplementalPunctuation", qMakePair(0x2E00, 0x2E7F)); + categoriesRangeMap.insert("IsCJKRadicalsSupplement", qMakePair(0x2E80, 0x2EFF)); + categoriesRangeMap.insert("IsKangxiRadicals", qMakePair(0x2F00, 0x2FDF)); + categoriesRangeMap.insert("IsIdeographicDescriptionCharacters", qMakePair(0x2FF0, 0x2FFF)); + categoriesRangeMap.insert("IsCJKSymbolsandPunctuation", qMakePair(0x3000, 0x303F)); + categoriesRangeMap.insert("IsHiragana", qMakePair(0x3040, 0x309F)); + categoriesRangeMap.insert("IsKatakana", qMakePair(0x30A0, 0x30FF)); + categoriesRangeMap.insert("IsBopomofo", qMakePair(0x3100, 0x312F)); + categoriesRangeMap.insert("IsHangulCompatibilityJamo", qMakePair(0x3130, 0x318F)); + categoriesRangeMap.insert("IsKanbun", qMakePair(0x3190, 0x319F)); + categoriesRangeMap.insert("IsBopomofoExtended", qMakePair(0x31A0, 0x31BF)); + categoriesRangeMap.insert("IsCJKStrokes", qMakePair(0x31C0, 0x31EF)); + categoriesRangeMap.insert("IsKatakanaPhoneticExtensions", qMakePair(0x31F0, 0x31FF)); + categoriesRangeMap.insert("IsEnclosedCJKLettersandMonths", qMakePair(0x3200, 0x32FF)); + categoriesRangeMap.insert("IsCJKCompatibility", qMakePair(0x3300, 0x33FF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionA", qMakePair(0x3400, 0x4DB5)); + categoriesRangeMap.insert("IsYijingHexagramSymbols", qMakePair(0x4DC0, 0x4DFF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographs", qMakePair(0x4E00, 0x9FFF)); + categoriesRangeMap.insert("IsYiSyllables", qMakePair(0xA000, 0xA48F)); + categoriesRangeMap.insert("IsYiRadicals", qMakePair(0xA490, 0xA4CF)); + categoriesRangeMap.insert("IsModifierToneLetters", qMakePair(0xA700, 0xA71F)); + categoriesRangeMap.insert("IsSylotiNagri", qMakePair(0xA800, 0xA82F)); + categoriesRangeMap.insert("IsHangulSyllables", qMakePair(0xAC00, 0xD7A3)); + categoriesRangeMap.insert("IsPrivateUse", qMakePair(0xE000, 0xF8FF)); + categoriesRangeMap.insert("IsCJKCompatibilityIdeographs", qMakePair(0xF900, 0xFAFF)); + categoriesRangeMap.insert("IsAlphabeticPresentationForms", qMakePair(0xFB00, 0xFB4F)); + categoriesRangeMap.insert("IsArabicPresentationForms-A", qMakePair(0xFB50, 0xFDFF)); + categoriesRangeMap.insert("IsVariationSelectors", qMakePair(0xFE00, 0xFE0F)); + categoriesRangeMap.insert("IsVerticalForms", qMakePair(0xFE10, 0xFE1F)); + categoriesRangeMap.insert("IsCombiningHalfMarks", qMakePair(0xFE20, 0xFE2F)); + categoriesRangeMap.insert("IsCJKCompatibilityForms", qMakePair(0xFE30, 0xFE4F)); + categoriesRangeMap.insert("IsSmallFormVariants", qMakePair(0xFE50, 0xFE6F)); + categoriesRangeMap.insert("IsArabicPresentationForms-B", qMakePair(0xFE70, 0xFEFF)); + categoriesRangeMap.insert("IsHalfwidthandFullwidthForms", qMakePair(0xFF00, 0xFFEF)); + categoriesRangeMap.insert("IsSpecials", qMakePair(0xFFF0, 0xFFFF)); + categoriesRangeMap.insert("IsLinearBSyllabary", qMakePair(0x10000, 0x1007F)); + categoriesRangeMap.insert("IsLinearBIdeograms", qMakePair(0x10080, 0x100FF)); + categoriesRangeMap.insert("IsAegeanNumbers", qMakePair(0x10100, 0x1013F)); + categoriesRangeMap.insert("IsAncientGreekNumbers", qMakePair(0x10140, 0x1018F)); + categoriesRangeMap.insert("IsOldItalic", qMakePair(0x10300, 0x1032F)); + categoriesRangeMap.insert("IsGothic", qMakePair(0x10330, 0x1034F)); + categoriesRangeMap.insert("IsUgaritic", qMakePair(0x10380, 0x1039F)); + categoriesRangeMap.insert("IsOldPersian", qMakePair(0x103A0, 0x103DF)); + categoriesRangeMap.insert("IsDeseret", qMakePair(0x10400, 0x1044F)); + categoriesRangeMap.insert("IsShavian", qMakePair(0x10450, 0x1047F)); + categoriesRangeMap.insert("IsOsmanya", qMakePair(0x10480, 0x104AF)); + categoriesRangeMap.insert("IsCypriotSyllabary", qMakePair(0x10800, 0x1083F)); + categoriesRangeMap.insert("IsKharoshthi", qMakePair(0x10A00, 0x10A5F)); + categoriesRangeMap.insert("IsByzantineMusicalSymbols", qMakePair(0x1D000, 0x1D0FF)); + categoriesRangeMap.insert("IsMusicalSymbols", qMakePair(0x1D100, 0x1D1FF)); + categoriesRangeMap.insert("IsAncientGreekMusicalNotation", qMakePair(0x1D200, 0x1D24F)); + categoriesRangeMap.insert("IsTaiXuanJingSymbols", qMakePair(0x1D300, 0x1D35F)); + categoriesRangeMap.insert("IsMathematicalAlphanumericSymbols", qMakePair(0x1D400, 0x1D7FF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionB", qMakePair(0x20000, 0x2A6DF)); + categoriesRangeMap.insert("IsCJKCompatibilityIdeographsSupplement", qMakePair(0x2F800, 0x2FA1F)); + categoriesRangeMap.insert("IsTags", qMakePair(0xE0000, 0xE007F)); + categoriesRangeMap.insert("IsVariationSelectorsSupplement", qMakePair(0xE0100, 0xE01EF)); + categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-A", qMakePair(0xF0000, 0xFFFFF)); + categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-B", qMakePair(0x100000, 0x10FFFF)); +} + int QRegExpEngine::getChar() { return (yyPos == yyLen) ? EOS : yyIn[yyPos++].unicode(); @@ -2718,6 +2876,177 @@ int QRegExpEngine::getEscape() yyCharClass->addCategories(0x000f807e); yyCharClass->addSingleton(0x005f); // '_' return Tok_CharClass; + case 'I': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'i': + if (xmlSchemaExtensions) { + yyCharClass->addCategories(0x000f807e); + yyCharClass->addSingleton(0x003a); // ':' + yyCharClass->addSingleton(0x005f); // '_' + yyCharClass->addRange(0x0041, 0x005a); // [A-Z] + yyCharClass->addRange(0x0061, 0x007a); // [a-z] + yyCharClass->addRange(0xc0, 0xd6); + yyCharClass->addRange(0xd8, 0xf6); + yyCharClass->addRange(0xf8, 0x2ff); + yyCharClass->addRange(0x370, 0x37d); + yyCharClass->addRange(0x37f, 0x1fff); + yyCharClass->addRange(0x200c, 0x200d); + yyCharClass->addRange(0x2070, 0x218f); + yyCharClass->addRange(0x2c00, 0x2fef); + yyCharClass->addRange(0x3001, 0xd7ff); + yyCharClass->addRange(0xf900, 0xfdcf); + yyCharClass->addRange(0xfdf0, 0xfffd); + yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); + } + return Tok_CharClass; + case 'C': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'c': + if (xmlSchemaExtensions) { + yyCharClass->addCategories(0x000f807e); + yyCharClass->addSingleton(0x002d); // '-' + yyCharClass->addSingleton(0x002e); // '.' + yyCharClass->addSingleton(0x003a); // ':' + yyCharClass->addSingleton(0x005f); // '_' + yyCharClass->addSingleton(0xb7); + yyCharClass->addRange(0x0030, 0x0039); // [0-9] + yyCharClass->addRange(0x0041, 0x005a); // [A-Z] + yyCharClass->addRange(0x0061, 0x007a); // [a-z] + yyCharClass->addRange(0xc0, 0xd6); + yyCharClass->addRange(0xd8, 0xf6); + yyCharClass->addRange(0xf8, 0x2ff); + yyCharClass->addRange(0x370, 0x37d); + yyCharClass->addRange(0x37f, 0x1fff); + yyCharClass->addRange(0x200c, 0x200d); + yyCharClass->addRange(0x2070, 0x218f); + yyCharClass->addRange(0x2c00, 0x2fef); + yyCharClass->addRange(0x3001, 0xd7ff); + yyCharClass->addRange(0xf900, 0xfdcf); + yyCharClass->addRange(0xfdf0, 0xfffd); + yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); + yyCharClass->addRange(0x0300, 0x036f); + yyCharClass->addRange(0x203f, 0x2040); + } + return Tok_CharClass; + case 'P': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'p': + if (xmlSchemaExtensions) { + if (yyCh != '{') { + error(RXERR_CHARCLASS); + return Tok_CharClass; + } + + QByteArray category; + yyCh = getChar(); + while (yyCh != '}') { + if (yyCh == EOS) { + error(RXERR_END); + return Tok_CharClass; + } + category.append(yyCh); + yyCh = getChar(); + } + yyCh = getChar(); // skip closing '}' + + if (category == "M") { + yyCharClass->addCategories(0x0000000e); + } else if (category == "Mn") { + yyCharClass->addCategories(0x00000002); + } else if (category == "Mc") { + yyCharClass->addCategories(0x00000004); + } else if (category == "Me") { + yyCharClass->addCategories(0x00000008); + } else if (category == "N") { + yyCharClass->addCategories(0x00000070); + } else if (category == "Nd") { + yyCharClass->addCategories(0x00000010); + } else if (category == "Nl") { + yyCharClass->addCategories(0x00000020); + } else if (category == "No") { + yyCharClass->addCategories(0x00000040); + } else if (category == "Z") { + yyCharClass->addCategories(0x00000380); + } else if (category == "Zs") { + yyCharClass->addCategories(0x00000080); + } else if (category == "Zl") { + yyCharClass->addCategories(0x00000100); + } else if (category == "Zp") { + yyCharClass->addCategories(0x00000200); + } else if (category == "C") { + yyCharClass->addCategories(0x00006c00); + } else if (category == "Cc") { + yyCharClass->addCategories(0x00000400); + } else if (category == "Cf") { + yyCharClass->addCategories(0x00000800); + } else if (category == "Cs") { + yyCharClass->addCategories(0x00001000); + } else if (category == "Co") { + yyCharClass->addCategories(0x00002000); + } else if (category == "Cn") { + yyCharClass->addCategories(0x00004000); + } else if (category == "L") { + yyCharClass->addCategories(0x000f8000); + } else if (category == "Lu") { + yyCharClass->addCategories(0x00008000); + } else if (category == "Ll") { + yyCharClass->addCategories(0x00010000); + } else if (category == "Lt") { + yyCharClass->addCategories(0x00020000); + } else if (category == "Lm") { + yyCharClass->addCategories(0x00040000); + } else if (category == "Lo") { + yyCharClass->addCategories(0x00080000); + } else if (category == "P") { + yyCharClass->addCategories(0x4f580780); + } else if (category == "Pc") { + yyCharClass->addCategories(0x00100000); + } else if (category == "Pd") { + yyCharClass->addCategories(0x00200000); + } else if (category == "Ps") { + yyCharClass->addCategories(0x00400000); + } else if (category == "Pe") { + yyCharClass->addCategories(0x00800000); + } else if (category == "Pi") { + yyCharClass->addCategories(0x01000000); + } else if (category == "Pf") { + yyCharClass->addCategories(0x02000000); + } else if (category == "Po") { + yyCharClass->addCategories(0x04000000); + } else if (category == "S") { + yyCharClass->addCategories(0x78000000); + } else if (category == "Sm") { + yyCharClass->addCategories(0x08000000); + } else if (category == "Sc") { + yyCharClass->addCategories(0x10000000); + } else if (category == "Sk") { + yyCharClass->addCategories(0x20000000); + } else if (category == "So") { + yyCharClass->addCategories(0x40000000); + } else if (category.startsWith("Is")) { + if (categoriesRangeMap.isEmpty()) + setupCategoriesRangeMap(); + + if (categoriesRangeMap.contains(category)) { + const QPair<int, int> range = categoriesRangeMap.value(category); + yyCharClass->addRange(range.first, range.second); + } else { + error(RXERR_CATEGORY); + } + } else { + error(RXERR_CATEGORY); + } + } + return Tok_CharClass; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'x': @@ -2939,7 +3268,7 @@ int QRegExpEngine::getToken() yyMaxRep = getRep(InftyRep); } if (yyMaxRep < yyMinRep) - qSwap(yyMinRep, yyMaxRep); + error(RXERR_INTERVAL); if (yyCh != '}') error(RXERR_REPETITION); yyCh = getChar(); @@ -3305,7 +3634,7 @@ static void prepareEngine_helper(QRegExpPrivate *priv) { bool initMatchState = !priv->eng; #if !defined(QT_NO_REGEXP_OPTIM) - if (!priv->eng) { + if (!priv->eng && globalEngineCache()) { QMutexLocker locker(mutex()); priv->eng = globalEngineCache()->take(priv->engineKey); if (priv->eng != 0) @@ -3383,6 +3712,9 @@ static void invalidateEngine(QRegExpPrivate *priv) equivalent to using the RegExp pattern on a string in which all metacharacters are escaped using escape(). + \value W3CXmlSchema11 The pattern is a regular expression as + defined by the W3C XML Schema 1.1 specification. + \sa setPatternSyntax() */ diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index 057eec2..16682a3 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -61,7 +61,7 @@ class QStringList; class Q_CORE_EXPORT QRegExp { public: - enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2 }; + enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2, W3CXmlSchema11 }; enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; QRegExp(); diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 16368e9..a0d6943 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -299,6 +299,54 @@ public: return read(size()); } + // read an unspecified amount (will read the first buffer) + inline QByteArray read() { + if (bufferSize == 0) + return QByteArray(); + + // multiple buffers, just take the first one + if (head == 0 && tailBuffer != 0) { + QByteArray qba = buffers.takeFirst(); + --tailBuffer; + bufferSize -= qba.length(); + return qba; + } + + // one buffer with good value for head. Just take it. + if (head == 0 && tailBuffer == 0) { + QByteArray qba = buffers.takeFirst(); + qba.resize(tail); + buffers << QByteArray(); + bufferSize = 0; + tail = 0; + return qba; + } + + // Bad case: We have to memcpy. + // We can avoid by initializing the QRingBuffer with basicBlockSize of 0 + // and only using this read() function. + QByteArray qba(readPointer(), nextDataBlockSize()); + buffers.removeFirst(); + head = 0; + if (tailBuffer == 0) { + buffers << QByteArray(); + tail = 0; + } else { + --tailBuffer; + } + bufferSize -= qba.length(); + return qba; + } + + // append a new buffer to the end + inline void append(const QByteArray &qba) { + buffers[tailBuffer].resize(tail); + buffers << qba; + ++tailBuffer; + tail = qba.length(); + bufferSize += qba.length(); + } + inline QByteArray peek(int maxLength) const { int bytesToRead = qMin(size(), maxLength); if(maxLength <= 0) @@ -353,7 +401,7 @@ public: private: QList<QByteArray> buffers; int head, tail; - int tailBuffer; + int tailBuffer; // always buffers.size() - 1 int basicBlockSize; int bufferSize; }; diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp index cf24381..06f9e6f 100644 --- a/src/corelib/tools/qscopedpointer.cpp +++ b/src/corelib/tools/qscopedpointer.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index 62daacb..923ae1b 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -161,6 +161,8 @@ public: return oldD; } + typedef T *pointer; + protected: T *d; diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp index 1599a13..d000c33 100644 --- a/src/corelib/tools/qshareddata.cpp +++ b/src/corelib/tools/qshareddata.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QSharedData is designed to be used with QSharedDataPointer or QExplicitlySharedDataPointer to implement custom \l{implicitly - shared} or \l {explicitly shared} classes. QSharedData provides + shared} or explicitly shared classes. QSharedData provides \l{thread-safe} reference counting. See QSharedDataPointer and QExplicitlySharedDataPointer for details. diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 083fea6..f7b014e 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -133,7 +133,7 @@ To access the pointer that QWeakPointer is tracking, you must first create a QSharedPointer object and verify if the pointer - is null or not. + is null or not. See QWeakPointer::toStrongRef() for more information. \sa QSharedPointer, QScopedPointer */ @@ -215,6 +215,8 @@ If \tt T is a derived type of the template parameter of this class, QSharedPointer will perform an automatic cast. Otherwise, you will get a compiler error. + + \sa QWeakPointer::toStrongRef() */ /*! @@ -345,10 +347,30 @@ */ /*! + \fn QSharedPointer<X> QSharedPointer::objectCast() const + \since 4.6 + + Performs a \l qobject_cast() from this pointer's type to \tt X and + returns a QSharedPointer that shares the reference. If this + function is used to up-cast, then QSharedPointer will perform a \tt + qobject_cast, which means that if the object being pointed by this + QSharedPointer is not of type \tt X, the returned object will be + null. + + Note: the template type \c X must have the same const and volatile + qualifiers as the template of this object, or the cast will + fail. Use constCast() if you need to drop those qualifiers. + + \sa qSharedPointerObjectCast() +*/ + +/*! \fn QWeakPointer<T> QSharedPointer::toWeakRef() const Returns a weak reference object that shares the pointer referenced by this object. + + \sa QWeakPointer::QWeakPointer(const QSharedPointer<T> &) */ /*! @@ -465,10 +487,78 @@ */ /*! + \fn T *QWeakPointer::data() const + \since 4.6 + + Returns the value of the pointer being tracked by this QWeakPointer, + \b without ensuring that it cannot get deleted. To have that guarantee, + use toStrongRef(), which returns a QSharedPointer object. If this + function can determine that the pointer has already been deleted, it + returns 0. + + It is ok to obtain the value of the pointer and using that value itself, + like for example in debugging statements: + + \code + qDebug("Tracking %p", weakref.data()); + \endcode + + However, dereferencing the pointer is only allowed if you can guarantee + by external means that the pointer does not get deleted. For example, + if you can be certain that no other thread can delete it, nor the + functions that you may call. + + If that is the case, then the following code is valid: + + \code + // this pointer cannot be used in another thread + // so other threads cannot delete it + QWeakPointer<int> weakref = obtainReference(); + + Object *obj = weakref.data(); + if (obj) { + // if the pointer wasn't deleted yet, we know it can't get + // deleted by our own code here nor the functions we call + otherFunction(obj); + } + \endcode + + Use this function with care. + + \sa isNull(), toStrongRef() +*/ + +/*! \fn QSharedPointer<T> QWeakPointer::toStrongRef() const Promotes this weak reference to a strong one and returns a - QSharedPointer object holding that reference. + QSharedPointer object holding that reference. When promoting to + QSharedPointer, this function verifies if the object has been deleted + already or not. If it hasn't, this function increases the reference + count to the shared object, thus ensuring that it will not get + deleted. + + Since this function can fail to obtain a valid strong reference to the + shared object, you should always verify if the conversion succeeded, + by calling QSharedPointer::isNull() on the returned object. + + For example, the following code promotes a QWeakPointer that was held + to a strong reference and, if it succeeded, it prints the value of the + integer that was held: + + \code + QWeakPointer<int> weakref; + + // ... + + QSharedPointer<int> strong = weakref.toStrongRef(); + if (strong) + qDebug() << "The value is:" << *strong; + else + qDebug() << "The value has already been deleted"; + \endcode + + \sa QSharedPointer::QSharedPointer(const QWeakPointer<T> &) */ /*! @@ -723,6 +813,47 @@ */ /*! + \fn QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &other) + \relates QSharedPointer + \since 4.6 + + Returns a shared pointer to the pointer held by \a other, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &other) + \relates QSharedPointer + \relates QWeakPointer + \since 4.6 + + Returns a shared pointer to the pointer held by \a other, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + The \a other object is converted first to a strong reference. If + that conversion fails (because the object it's pointing to has + already been deleted), this function also returns a null + QSharedPointer. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + + +/*! \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other) \relates QWeakPointer @@ -749,29 +880,19 @@ # endif # endif -# if !defined(BACKTRACE_SUPPORTED) -// Dummy implementation of the functions. -// Using QHashDummyValue also means that the QHash below is actually a QSet -typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace; - -static inline Backtrace saveBacktrace() { return Backtrace(); } -static inline void printBacktrace(Backtrace) { } - -# else +# if defined(BACKTRACE_SUPPORTED) # include <sys/types.h> # include <execinfo.h> # include <stdio.h> # include <unistd.h> # include <sys/wait.h> -typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace; - -static inline Backtrace saveBacktrace() __attribute__((always_inline)); -static inline Backtrace saveBacktrace() +static inline QByteArray saveBacktrace() __attribute__((always_inline)); +static inline QByteArray saveBacktrace() { static const int maxFrames = 32; - Backtrace stacktrace; + QByteArray stacktrace; stacktrace.resize(sizeof(void*) * maxFrames); int stack_size = backtrace((void**)stacktrace.data(), maxFrames); stacktrace.resize(sizeof(void*) * stack_size); @@ -779,7 +900,7 @@ static inline Backtrace saveBacktrace() return stacktrace; } -static void printBacktrace(Backtrace stacktrace) +static void printBacktrace(QByteArray stacktrace) { void *const *stack = (void *const *)stacktrace.constData(); int stack_size = stacktrace.size() / sizeof(void*); @@ -830,11 +951,19 @@ static void printBacktrace(Backtrace stacktrace) namespace { QT_USE_NAMESPACE + struct Data { + const volatile void *pointer; +# ifdef BACKTRACE_SUPPORTED + QByteArray backtrace; +# endif + }; + class KnownPointers { public: QMutex mutex; - QHash<void *, Backtrace> values; + QHash<const void *, Data> dPointers; + QHash<const volatile void *, const void *> dataPointers; }; } @@ -842,38 +971,122 @@ Q_GLOBAL_STATIC(KnownPointers, knownPointers) QT_BEGIN_NAMESPACE +namespace QtSharedPointer { + Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); + Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck(); +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckAdd(const volatile void *) +{ + // Qt 4.5 compatibility + // this function is broken by design, so it was replaced with internalSafetyCheckAdd2 + // + // it's broken because we tracked the pointers added and + // removed from QSharedPointer, converted to void*. + // That is, this is supposed to track the "top-of-object" pointer in + // case of multiple inheritance. + // + // However, it doesn't work well in some compilers: + // if you create an object with a class of type A and the last reference + // is dropped of type B, then the value passed to internalSafetyCheckRemove could + // be different than was added. That would leave dangling addresses. + // + // So instead, we track the pointer by the d-pointer instead. +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckRemove(const volatile void *) +{ + // Qt 4.5 compatibility + // see comments above +} + /*! \internal */ -void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr) { + // see comments above for the rationale for this function KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - if (kp->values.contains(actual)) { - printBacktrace(knownPointers()->values.value(actual)); - qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked " - "by another QSharedPointerData object", actual); + Q_ASSERT(!kp->dPointers.contains(d_ptr)); + + //qDebug("Adding d=%p value=%p", d_ptr, ptr); + + const void *other_d_ptr = kp->dataPointers.value(ptr, 0); + if (other_d_ptr) { +# ifdef BACKTRACE_SUPPORTED + printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace); +# endif + qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked " + "by another QSharedPointer object %p", ptr, other_d_ptr); } - kp->values.insert(actual, saveBacktrace()); + Data data; + data.pointer = ptr; +# ifdef BACKTRACE_SUPPORTED + data.backtrace = saveBacktrace(); +# endif + + kp->dPointers.insert(d_ptr, data); + kp->dataPointers.insert(ptr, d_ptr); + Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); } /*! \internal */ -void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr) { KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - kp->values.remove(actual); + + QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr); + if (it == kp->dPointers.end()) { + qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. " + "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout " + "in your code.", d_ptr); + } + + QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer); + Q_ASSERT(it2 != kp->dataPointers.end()); + + //qDebug("Removing d=%p value=%p", d_ptr, it->pointer); + + // remove entries + kp->dataPointers.erase(it2); + kp->dPointers.erase(it); + Q_ASSERT(kp->dPointers.size() == kp->dataPointers.size()); +} + +/*! + \internal + Called by the QSharedPointer autotest +*/ +void QtSharedPointer::internalSafetyCheckCleanCheck() +{ +# ifdef QT_BUILD_INTERNAL + KnownPointers *const kp = knownPointers(); + Q_ASSERT_X(kp, "internalSafetyCheckSelfCheck()", "Called after global statics deletion!"); + + if (kp->dPointers.size() != kp->dataPointers.size()) + qFatal("Internal consistency error: the number of pointers is not equal!"); + + if (!kp->dPointers.isEmpty()) + qFatal("Pointer cleaning failed: %d entries remaining", kp->dPointers.size()); +# endif } QT_END_NAMESPACE diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index cd6bc62..abd83ad 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -93,6 +93,7 @@ public: template <class X> QSharedPointer<X> staticCast() const; template <class X> QSharedPointer<X> dynamicCast() const; template <class X> QSharedPointer<X> constCast() const; + template <class X> QSharedPointer<X> objectCast() const; }; template <class T> @@ -136,6 +137,8 @@ template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QS template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src); template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src); template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src); +template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src); +template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src); template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src); diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index b928795..25373b3 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -48,7 +48,9 @@ #pragma qt_sync_stop_processing #endif +#include <new> #include <QtCore/qatomic.h> +#include <QtCore/qobject.h> // for qobject_cast QT_BEGIN_HEADER @@ -83,6 +85,11 @@ QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr); template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr); +#ifndef QT_NO_QOBJECT +template <class X, class T> +QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr); +#endif + namespace QtSharedPointer { template <class T> class InternalRefCount; template <class T> class ExternalRefCount; @@ -91,8 +98,8 @@ namespace QtSharedPointer { template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); // used in debug mode to verify the reuse of pointers - Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); - Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *); template <class T, typename Klass, typename RetVal> inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)()) @@ -100,13 +107,15 @@ namespace QtSharedPointer { template <class T, typename Deleter> inline void executeDeleter(T *t, Deleter d) { d(t); } + template <class T> inline void normalDeleter(T *t) { delete t; } + + // this uses partial template specialization + // the only compilers that didn't support this were MSVC 6.0 and 2002 + template <class T> struct RemovePointer; + template <class T> struct RemovePointer<T *> { typedef T Type; }; + template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; + template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; }; - // - // Depending on its template parameter, QSharedPointer derives from either - // QtSharedPointer::InternalRefCount or from QtSharedPointer::ExternalRefCount. - // Both of these classes derive from QtSharedPointer::Basic, which provides common - // operations, - // template <class T> class Basic { @@ -128,7 +137,7 @@ namespace QtSharedPointer { inline T *operator->() const { return data(); } protected: - inline Basic() : value(0 * sizeof(T)) { } + inline Basic() : value(0) { } // ~Basic(); inline void verifyReconstruction(const T *ptr) @@ -145,17 +154,8 @@ namespace QtSharedPointer { inline void internalConstruct(T *ptr) { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd(ptr); -#endif value = ptr; } - inline void internalDestroy() - { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (value) internalSafetyCheckRemove(value); -#endif - } #if defined(Q_NO_TEMPLATE_FRIENDS) public: @@ -176,48 +176,168 @@ namespace QtSharedPointer { virtual inline bool destroy() { return false; } }; + // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit) template <class T, typename Deleter> - struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData + struct CustomDeleter { - T *ptr; Deleter deleter; + T *ptr; - inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d) - : ptr(p), deleter(d) + inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {} + }; + // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit) + // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC) + + struct ExternalRefCountWithDestroyFn: public ExternalRefCountData + { + typedef void (*DestroyerFn)(ExternalRefCountData *); + DestroyerFn destroyer; + + inline ExternalRefCountWithDestroyFn(DestroyerFn d) + : destroyer(d) { } - inline bool destroy() { executeDeleter(ptr, deleter); return true; } + + inline bool destroy() { destroyer(this); return true; } + inline void operator delete(void *ptr) { ::operator delete(ptr); } + }; + // sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit) + + template <class T, typename Deleter> + struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithCustomDeleter Self; + typedef ExternalRefCountWithDestroyFn Parent; + typedef CustomDeleter<T, Deleter> Next; + Next extra; + + static inline void deleter(ExternalRefCountData *self) + { + Self *realself = static_cast<Self *>(self); + executeDeleter(realself->extra.ptr, realself->extra.deleter); + + // delete the deleter too + realself->extra.~Next(); + } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } + + static inline Self *create(T *ptr, Deleter userDeleter) + { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else + DestroyerFn destroy = &deleter; +# endif + Self *d = static_cast<Self *>(::operator new(sizeof(Self))); + + // initialize the two sub-objects + new (&d->extra) Next(ptr, userDeleter); + new (d) Parent(destroy); // can't throw + + return d; + } + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithCustomDeleter(); + ~ExternalRefCountWithCustomDeleter(); + }; + + template <class T> + struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithDestroyFn Parent; + T data; + + static void deleter(ExternalRefCountData *self) + { + ExternalRefCountWithContiguousData *that = + static_cast<ExternalRefCountWithContiguousData *>(self); + that->data.~T(); + } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } + + static inline ExternalRefCountData *create(T **ptr) + { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else + DestroyerFn destroy = &deleter; +# endif + ExternalRefCountWithContiguousData *d = + static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData))); + + // initialize the d-pointer sub-object + // leave d->data uninitialized + new (d) Parent(destroy); // can't throw + + *ptr = &d->data; + return d; + } + + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithContiguousData(); + ~ExternalRefCountWithContiguousData(); }; template <class T> class ExternalRefCount: public Basic<T> { - typedef ExternalRefCountData Data; - typedef void (*DeleterFunction)(T *); protected: + typedef ExternalRefCountData Data; + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline bool deref() { - if (!d->strongref.deref()) - this->internalDestroy(); + if (!d->strongref.deref()) { + internalDestroy(); + } return d->weakref.deref(); } inline void internalConstruct(T *ptr) { - Basic<T>::internalConstruct(ptr); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + internalConstruct<void (*)(T *)>(ptr, normalDeleter); +#else Q_ASSERT(!d); if (ptr) d = new Data; + internalFinishConstruction(ptr); +#endif } template <typename Deleter> inline void internalConstruct(T *ptr, Deleter deleter) { - Basic<T>::internalConstruct(ptr); Q_ASSERT(!d); if (ptr) - d = new ExternalRefCountWithSpecializedDeleter<T, Deleter>(ptr, deleter); + d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter); + internalFinishConstruction(ptr); + } + + inline void internalCreate() + { + T *ptr; + d = ExternalRefCountWithContiguousData<T>::create(&ptr); + Basic<T>::internalConstruct(ptr); + } + + inline void internalFinishConstruction(T *ptr) + { + Basic<T>::internalConstruct(ptr); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd2(d, ptr); +#endif } inline ExternalRefCount() : d(0) { } @@ -233,7 +353,6 @@ namespace QtSharedPointer { inline void internalDestroy() { - Basic<T>::internalDestroy(); if (!d->destroy()) delete this->value; } @@ -251,12 +370,22 @@ namespace QtSharedPointer { inline void internalSet(Data *o, T *actual) { if (d == o) return; - if (o && !o->strongref) - o = 0; if (o) { Basic<T>::verifyReconstruction(actual); - o->weakref.ref(); - o->strongref.ref(); + + // increase the strongref, but never up from zero + register int tmp = o->strongref; + while (tmp > 0) { + // try to increment from "tmp" to "tmp + 1" + if (o->strongref.testAndSetRelaxed(tmp, tmp + 1)) + break; // succeeded + tmp = o->strongref; // failed, try again + } + + if (tmp) + o->weakref.ref(); + else + o = 0; } if (d && !deref()) delete d; @@ -264,9 +393,7 @@ namespace QtSharedPointer { this->value = d && d->strongref ? actual : 0; } -#if defined(QT_BUILD_INTERNAL) - public: -#endif + protected: Data *d; private: @@ -336,9 +463,29 @@ public: return qSharedPointerConstCast<X, T>(*this); } +#ifndef QT_NO_QOBJECT + template <class X> + QSharedPointer<X> objectCast() const + { + return qSharedPointerObjectCast<X, T>(*this); + } +#endif + inline void clear() { *this = QSharedPointer<T>(); } QWeakPointer<T> toWeakRef() const; + +public: + static inline QSharedPointer<T> create() + { + QSharedPointer<T> result; + result.internalCreate(); + + // now initialize the data + new (result.data()) T(); + result.internalFinishConstruction(result.data()); + return result; + } }; template <class T> @@ -357,6 +504,7 @@ public: inline operator bool() const { return isNull() ? 0 : &QWeakPointer::value; } #endif inline bool operator !() const { return isNull(); } + inline T *data() const { return d == 0 || d->strongref == 0 ? 0 : value; } inline QWeakPointer() : d(0), value(0) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } @@ -557,6 +705,34 @@ QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src) return qSharedPointerCast<X, T>(src).toWeakRef(); } +#ifndef QT_NO_QOBJECT +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src) +{ + register X *ptr = qobject_cast<X *>(src.data()); + return QtSharedPointer::copyAndSetPointer(ptr, src); +} +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src) +{ + return qSharedPointerObjectCast<X>(src.toStrongRef()); +} + +template <class X, class T> +inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type> +qobject_cast(const QSharedPointer<T> &src) +{ + return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); +} +template <class X, class T> +inline QSharedPointer<typename QtSharedPointer::RemovePointer<X>::Type> +qobject_cast(const QWeakPointer<T> &src) +{ + return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); +} + +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ca2fd1a..87e812f 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_TEXTCODEC #include <qtextcodec.h> #endif +#include <private/qutfcodec_p.h> #include <qdatastream.h> #include <qlist.h> #include "qlocale.h" @@ -964,7 +965,8 @@ int QString::toWCharArray(wchar_t *array) const Constructs a string initialized with the first \a size characters of the QChar array \a unicode. - QString makes a deep copy of the string data. + QString makes a deep copy of the string data. The unicode data is copied as + is and the Byte Order Mark is preserved if present. */ QString::QString(const QChar *unicode, int size) { @@ -3481,7 +3483,7 @@ QByteArray QString::toAscii() const return toLatin1(); } -#ifndef Q_WS_MAC +#if !defined(Q_WS_MAC) && defined(Q_OS_UNIX) static QByteArray toLocal8Bit_helper(const QChar *data, int length) { #ifndef QT_NO_TEXTCODEC @@ -3716,13 +3718,13 @@ QByteArray qt_winQString2MB(const QChar *ch, int uclen) BOOL used_def; QByteArray mb(4096, 0); int len; - while (!(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)ch, uclen, + while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen, mb.data(), mb.size()-1, 0, &used_def))) { int r = GetLastError(); if (r == ERROR_INSUFFICIENT_BUFFER) { mb.resize(1+WideCharToMultiByte(CP_ACP, 0, - (const WCHAR*)ch, uclen, + (const wchar_t*)ch, uclen, 0, 0, 0, &used_def)); // and try again... } else { @@ -3743,9 +3745,9 @@ QString qt_winMB2QString(const char *mb, int mblen) if (!mb || !mblen) return QString(); const int wclen_auto = 4096; - WCHAR wc_auto[wclen_auto]; + wchar_t wc_auto[wclen_auto]; int wclen = wclen_auto; - WCHAR *wc = wc_auto; + wchar_t *wc = wc_auto; int len; while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, wc, wclen))) @@ -3758,7 +3760,7 @@ QString qt_winMB2QString(const char *mb, int mblen) } else { wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, 0, 0); - wc = new WCHAR[wclen]; + wc = new wchar_t[wclen]; // and try again... } } else { @@ -3801,11 +3803,6 @@ QString QString::fromLocal8Bit(const char *str, int size) return QString(); if (size == 0 || (!*str && size < 0)) return QLatin1String(""); -#if defined(Q_OS_WIN32) - if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - return qt_winMB2QString(str, size); - } -#endif #if !defined(QT_NO_TEXTCODEC) if (size < 0) size = qstrlen(str); @@ -3850,74 +3847,7 @@ QString QString::fromUtf8(const char *str, int size) if (size < 0) size = qstrlen(str); - QString result(size, Qt::Uninitialized); // worst case - ushort *qch = result.d->data; - uint uc = 0; - uint min_uc = 0; - int need = 0; - int error = -1; - uchar ch; - int i = 0; - - // skip utf8-encoded byte order mark - if (size >= 3 - && (uchar)str[0] == 0xef && (uchar)str[1] == 0xbb && (uchar)str[2] == 0xbf) - i += 3; - - for (; i < size; ++i) { - ch = str[i]; - if (need) { - if ((ch&0xc0) == 0x80) { - uc = (uc << 6) | (ch & 0x3f); - need--; - if (!need) { - if (uc > 0xffffU && uc < 0x110000U) { - // surrogate pair - *qch++ = QChar::highSurrogate(uc); - uc = QChar::lowSurrogate(uc); - } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) { - // overlong seqence, UTF16 surrogate or BOM - uc = QChar::ReplacementCharacter; - } - *qch++ = uc; - } - } else { - i = error; - need = 0; - *qch++ = QChar::ReplacementCharacter; - } - } else { - if (ch < 128) { - *qch++ = ch; - } else if ((ch & 0xe0) == 0xc0) { - uc = ch & 0x1f; - need = 1; - error = i; - min_uc = 0x80; - } else if ((ch & 0xf0) == 0xe0) { - uc = ch & 0x0f; - need = 2; - error = i; - min_uc = 0x800; - } else if ((ch&0xf8) == 0xf0) { - uc = ch & 0x07; - need = 3; - error = i; - min_uc = 0x10000; - } else { - // Error - *qch++ = QChar::ReplacementCharacter; - } - } - } - if (need) { - // we have some invalid characters remaining we need to add to the string - for (int i = error; i < size; ++i) - *qch++ = QChar::ReplacementCharacter; - } - - result.truncate(qch - result.d->data); - return result; + return QUtf8::convertToUnicode(str, size, 0); } /*! @@ -3940,7 +3870,7 @@ QString QString::fromUtf16(const ushort *unicode, int size) while (unicode[size] != 0) ++size; } - return QString((const QChar *)unicode, size); + return QUtf16::convertToUnicode((const char *)unicode, size*2, 0); } @@ -3964,20 +3894,7 @@ QString QString::fromUcs4(const uint *unicode, int size) while (unicode[size] != 0) ++size; } - - QString s(size * 2, Qt::Uninitialized); // worst case - ushort *uc = s.d->data; - for (int i = 0; i < size; ++i) { - uint u = unicode[i]; - if (u > 0xffff) { - // decompose into a surrogate pair - *uc++ = QChar::highSurrogate(u); - u = QChar::lowSurrogate(u); - } - *uc++ = u; - } - s.resize(uc - s.d->data); - return s; + return QUtf32::convertToUnicode((const char *)unicode, size*4, 0); } /*! @@ -4699,16 +4616,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, return ucstrcmp(data1, length1, data2, length2); #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - int res; - QT_WA({ - const TCHAR* s1 = (TCHAR*)data1; - const TCHAR* s2 = (TCHAR*)data2; - res = CompareStringW(GetUserDefaultLCID(), 0, s1, length1, s2, length2); - } , { - QByteArray s1 = toLocal8Bit_helper(data1, length1); - QByteArray s2 = toLocal8Bit_helper(data2, length2); - res = CompareStringA(GetUserDefaultLCID(), 0, s1.data(), s1.length(), s2.data(), s2.length()); - }); + int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2); switch (res) { case CSTR_LESS_THAN: @@ -6122,6 +6030,7 @@ QString QString::repeated(int times) const return result; } +void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from); /*! \overload \fn QString QString::normalized(NormalizationForm mode, QChar::UnicodeVersion version) const @@ -6131,42 +6040,48 @@ QString QString::repeated(int times) const */ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const { + QString copy = *this; + qt_string_normalize(©, mode, version, 0); + return copy; +} + +void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from) +{ bool simple = true; - for (int i = 0; i < d->size; ++i) { - if (d->data[i] >= 0x80) { + const QChar *p = data->constData(); + int len = data->length(); + for (int i = from; i < len; ++i) { + if (p[i].unicode() >= 0x80) { simple = false; break; } } if (simple) - return *this; + return; - QString s = *this; + QString &s = *data; if (version != CURRENT_VERSION) { for (int i = 0; i < NumNormalizationCorrections; ++i) { const NormalizationCorrection &n = uc_normalization_corrections[i]; if (n.version > version) { + int pos = from; if (n.ucs4 > 0xffff) { ushort ucs4High = QChar::highSurrogate(n.ucs4); ushort ucs4Low = QChar::lowSurrogate(n.ucs4); ushort oldHigh = QChar::highSurrogate(n.old_mapping); ushort oldLow = QChar::lowSurrogate(n.old_mapping); - int pos = 0; - while (pos < s.d->size - 1) { - if (s.d->data[pos] == ucs4High && s.d->data[pos + 1] == ucs4Low) { - s.detach(); - s.d->data[pos] = oldHigh; - s.d->data[pos + 1] = oldLow; + while (pos < s.length() - 1) { + if (s.at(pos).unicode() == ucs4High && s.at(pos + 1).unicode() == ucs4Low) { + s[pos] = oldHigh; + s[pos + 1] = oldLow; ++pos; } ++pos; } } else { - int pos = 0; - while (pos < s.d->size) { - if (s.d->data[pos] == n.ucs4) { - s.detach(); - s.d->data[pos] = n.old_mapping; + while (pos < s.length()) { + if (s.at(pos).unicode() == n.ucs4) { + s[pos] = n.old_mapping; } ++pos; } @@ -6174,15 +6089,14 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi } } } - s = decomposeHelper(s, mode < QString::NormalizationForm_KD, version); + decomposeHelper(data, mode < QString::NormalizationForm_KD, version, from); - s = canonicalOrderHelper(s, version); + canonicalOrderHelper(data, version, from); if (mode == QString::NormalizationForm_D || mode == QString::NormalizationForm_KD) - return s; - - return composeHelper(s); + return; + composeHelper(data, from); } @@ -6567,7 +6481,7 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, const QChar &fillCha ArgEscapeData d = findArgEscapes(*this); if (d.occurrences == 0) { - qWarning("QString::arg: Argument missing: %s, %lld", toLocal8Bit().data(), a); + qWarning() << "QString::arg: Argument missing:" << *this << ',' << a; return *this; } @@ -6610,7 +6524,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, const QChar &fillCh ArgEscapeData d = findArgEscapes(*this); if (d.occurrences == 0) { - qWarning("QString::arg: Argument missing: %s, %llu", toLocal8Bit().data(), a); + qWarning() << "QString::arg: Argument missing:" << *this << ',' << a; return *this; } diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 6bb0d8e..235c603 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1235,6 +1235,8 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef QT_END_NAMESPACE +QT_END_HEADER + #ifdef QT_USE_FAST_CONCATENATION #include <QtCore/qstringbuilder.h> #endif diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 852c072..463c32d 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -69,7 +69,7 @@ private: }; -template <typename T> class QConcatenable {}; +template <typename T> struct QConcatenable {}; template <typename A, typename B> class QStringBuilder @@ -163,7 +163,7 @@ template <> struct QConcatenable<QString> static inline void appendTo(const QString &a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; @@ -175,7 +175,7 @@ template <> struct QConcatenable<QStringRef> static inline void appendTo(QStringRef a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; @@ -202,6 +202,18 @@ template <> struct QConcatenable<const char *> *out++ = QLatin1Char(*a++); } }; + +template <> struct QConcatenable<QByteArray> +{ + typedef QByteArray type; + static int size(const QByteArray &ba) { return qstrnlen(ba.constData(), ba.size()); } + static inline void appendTo(const QByteArray &ba, QChar *&out) + { + const char *data = ba.constData(); + while (*data) + *out++ = QLatin1Char(*data++); + } +}; #endif template <typename A, typename B> diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 5a2b37a..5c550af 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -41,6 +41,7 @@ #include <qstringlist.h> #include <qset.h> +#include <qstringmatcher.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 665c0d0..f36567a 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -47,7 +47,6 @@ #include <QtCore/qlist.h> #include <QtCore/qregexp.h> #include <QtCore/qstring.h> -#include <QtCore/qstringmatcher.h> #ifdef QT_INCLUDE_COMPAT #include <Qt3Support/q3valuelist.h> #endif diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h index 2b8edc9..61b7a95 100644 --- a/src/corelib/tools/qstringmatcher.h +++ b/src/corelib/tools/qstringmatcher.h @@ -81,13 +81,14 @@ private: // explicitely allow anonymous unions for RVCT to prevent compiler warnings #pragma anon_unions #endif + struct Data { + uchar q_skiptable[256]; + const QChar *uc; + int len; + }; union { uint q_data[256]; - struct { - uchar q_skiptable[256]; - const QChar *uc; - int len; - } p; + Data p; }; }; diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp index 04aed39..e32fc03 100644 --- a/src/corelib/tools/qtimeline.cpp +++ b/src/corelib/tools/qtimeline.cpp @@ -555,6 +555,8 @@ void QTimeLine::setCurveShape(CurveShape shape) /*! \property QTimeLine::easingCurve + \since 4.6 + Specifies the easing curve that the timeline will use. If both easing curve and curveShape are set, the last set property will override the previous one. (If valueForTime() is reimplemented it will diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h index 2a1c2c2..2d1ad42 100644 --- a/src/corelib/tools/qtimeline.h +++ b/src/corelib/tools/qtimeline.h @@ -136,7 +136,7 @@ protected: private: Q_DISABLE_COPY(QTimeLine) - Q_DECLARE_SCOPED_PRIVATE(QTimeLine) + Q_DECLARE_PRIVATE(QTimeLine) }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 9fc9c03..3a7b35c 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -253,11 +253,7 @@ public: typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; -#ifndef QT_NO_STL typedef ptrdiff_t difference_type; -#else - typedef int difference_type; -#endif typedef iterator Iterator; typedef const_iterator ConstIterator; typedef int size_type; @@ -418,7 +414,9 @@ void QVector<T>::free(Data *x) { if (QTypeInfo<T>::isComplex) { T* b = x->array; - T* i = b + reinterpret_cast<QVectorData *>(x)->size; + union { QVectorData *d; Data *p; } u; + u.p = x; + T* i = b + u.d->size; while (i-- != b) i->~T(); } diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 1162238..e6c6169 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -5,6 +5,7 @@ HEADERS += \ tools/qbitarray.h \ tools/qbytearray.h \ tools/qbytearraymatcher.h \ + tools/qbytedata_p.h \ tools/qcache.h \ tools/qchar.h \ tools/qcontainerfwd.h \ @@ -113,4 +114,4 @@ HEADERS += tools/qharfbuzz_p.h INCLUDEPATH += ../3rdparty/md5 \ ../3rdparty/md4 -!macx-icc:unix:!symbian:LIBS += -lm +!macx-icc:unix:!symbian:!vxworks:LIBS += -lm diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 79b9bf2..cbf367e 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -334,12 +334,17 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const from the PrematureEndOfDocumentError error and continues parsing the new data with the next call to readNext(). - For example, if you read data from the network using QHttp, you - would connect its \l{QHttp::readyRead()}{readyRead()} signal to a - custom slot. In this slot, you read all available data with - \l{QHttp::readAll()}{readAll()} and pass it to the XML stream reader - using addData(). Then you call your custom parsing function that - reads the XML events from the reader. + For example, if your application reads data from the network using a + \l{QNetworkAccessManager} {network access manager}, you would issue + a \l{QNetworkRequest} {network request} to the manager and receive a + \l{QNetworkReply} {network reply} in return. Since a QNetworkReply + is a QIODevice, you connect its \l{QNetworkReply::readyRead()} + {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in + the code snippet shown in the discussion for QNetworkAccessManager. + In this slot, you read all available data with + \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML + stream reader using addData(). Then you call your custom parsing + function that reads the XML events from the reader. \section1 Performance and memory consumption @@ -567,7 +572,7 @@ bool QXmlStreamReader::atEnd() const returns true, hasError() returns true, and this function returns QXmlStreamReader::Invalid. - The exception is when error() return PrematureEndOfDocumentError. + The exception is when error() returns PrematureEndOfDocumentError. This error is reported when the end of an otherwise well-formed chunk of XML is reached, but the chunk doesn't represent a complete XML document. In that case, parsing \e can be resumed by calling diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h index 3215624..7be7138 100644 --- a/src/corelib/xml/qxmlstream.h +++ b/src/corelib/xml/qxmlstream.h @@ -392,7 +392,7 @@ public: private: Q_DISABLE_COPY(QXmlStreamReader) - Q_DECLARE_SCOPED_PRIVATE(QXmlStreamReader) + Q_DECLARE_PRIVATE(QXmlStreamReader) QScopedPointer<QXmlStreamReaderPrivate> d_ptr; }; @@ -465,7 +465,7 @@ public: private: Q_DISABLE_COPY(QXmlStreamWriter) - Q_DECLARE_SCOPED_PRIVATE(QXmlStreamWriter) + Q_DECLARE_PRIVATE(QXmlStreamWriter) QScopedPointer<QXmlStreamWriterPrivate> d_ptr; }; #endif // QT_NO_XMLSTREAMWRITER diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index e6c914f..68477af 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -54,6 +54,10 @@ #ifndef QXMLSTREAM_P_H #define QXMLSTREAM_P_H +#if defined(Q_OS_VXWORKS) && defined(ERROR) +# undef ERROR +#endif + class QXmlStreamReader_Table { public: |