diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-24 15:18:05 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-24 15:18:05 (GMT) |
commit | 723dfce0f2af6d93d2c1b50f5e44ad3cf63e058c (patch) | |
tree | f8e1c8693aceea8f1d2fc03d9ad1555b0a441a27 /src/corelib | |
parent | f90d8f3fe7e39a20b93a2ddfe0704bc48f3bd5f9 (diff) | |
parent | dab9d7c67ed2eda150c8da9e41db75f7eeeecd0d (diff) | |
download | Qt-723dfce0f2af6d93d2c1b50f5e44ad3cf63e058c.zip Qt-723dfce0f2af6d93d2c1b50f5e44ad3cf63e058c.tar.gz Qt-723dfce0f2af6d93d2c1b50f5e44ad3cf63e058c.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/gui/kernel/qapplication_x11.cpp
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/concurrent/qtconcurrentthreadengine.cpp | 89 | ||||
-rw-r--r-- | src/corelib/concurrent/qtconcurrentthreadengine.h | 69 | ||||
-rw-r--r-- | src/corelib/concurrent/qthreadpool.cpp | 10 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 4 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_unix.cpp | 20 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 4 | ||||
-rw-r--r-- | src/corelib/statemachine/qstate.cpp | 6 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 92 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine_p.h | 1 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 46 | ||||
-rw-r--r-- | src/corelib/tools/qrect.cpp | 62 | ||||
-rw-r--r-- | src/corelib/tools/qrect.h | 2 | ||||
-rw-r--r-- | src/corelib/xml/qxmlstream.cpp | 3 |
13 files changed, 202 insertions, 206 deletions
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.cpp b/src/corelib/concurrent/qtconcurrentthreadengine.cpp index 5356e82..150540a 100644 --- a/src/corelib/concurrent/qtconcurrentthreadengine.cpp +++ b/src/corelib/concurrent/qtconcurrentthreadengine.cpp @@ -47,6 +47,81 @@ QT_BEGIN_NAMESPACE namespace QtConcurrent { +ThreadEngineBarrier::ThreadEngineBarrier() +:count(0) { } + +void ThreadEngineBarrier::acquire() +{ + forever { + int localCount = int(count); + if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount -1)) + return; + } else { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return; + } + } +} + +int ThreadEngineBarrier::release() +{ + forever { + int localCount = int(count); + if (localCount == -1) { + if (count.testAndSetOrdered(-1, 0)) { + semaphore.release(); + return 0; + } + } else if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return qAbs(localCount + 1); + } else { + if (count.testAndSetOrdered(localCount, localCount - 1)) + return localCount - 1; + } + } +} + +// Wait until all threads have been released +void ThreadEngineBarrier::wait() +{ + forever { + int localCount = int(count); + if (localCount == 0) + return; + + Q_ASSERT(localCount > 0); // multiple waiters are not allowed. + if (count.testAndSetOrdered(localCount, -localCount)) { + semaphore.acquire(); + return; + } + } +} + +int ThreadEngineBarrier::currentCount() +{ + return int(count); +} + +// releases a thread, unless this is the last thread. +// returns true if the thread was released. +bool ThreadEngineBarrier::releaseUnlessLast() +{ + forever { + int localCount = int(count); + if (qAbs(localCount) == 1) { + return false; + } else if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return true; + } else { + if (count.testAndSetOrdered(localCount, localCount - 1)) + return true; + } + } +} + ThreadEngineBase::ThreadEngineBase() :futureInterface(0), threadPool(QThreadPool::globalInstance()) { @@ -66,7 +141,7 @@ void ThreadEngineBase::startSingleThreaded() void ThreadEngineBase::startBlocking() { start(); - semaphore.acquire(); + barrier.acquire(); startThreads(); bool throttled = false; @@ -88,10 +163,10 @@ void ThreadEngineBase::startBlocking() #endif if (throttled == false) { - semaphore.release(); + barrier.release(); } - semaphore.wait(); + barrier.wait(); finish(); exceptionStore.throwPossibleException(); } @@ -138,9 +213,9 @@ bool ThreadEngineBase::startThreadInternal() if (this->isCanceled()) return false; - semaphore.acquire(); + barrier.acquire(); if (!threadPool->tryStart(this)) { - semaphore.release(); + barrier.release(); return false; } return true; @@ -155,7 +230,7 @@ void ThreadEngineBase::startThreads() void ThreadEngineBase::threadExit() { const bool asynchronous = futureInterface != 0; - const int lastThread = (semaphore.release() == 0); + const int lastThread = (barrier.release() == 0); if (lastThread && asynchronous) this->asynchronousFinish(); @@ -166,7 +241,7 @@ void ThreadEngineBase::threadExit() // this function returns one. bool ThreadEngineBase::threadThrottleExit() { - return semaphore.releaseUnlessLast(); + return barrier.releaseUnlessLast(); } void ThreadEngineBase::run() // implements QRunnable. diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.h b/src/corelib/concurrent/qtconcurrentthreadengine.h index 6f1c7e7..286c2b8 100644 --- a/src/corelib/concurrent/qtconcurrentthreadengine.h +++ b/src/corelib/concurrent/qtconcurrentthreadengine.h @@ -51,6 +51,8 @@ #include <QtCore/qdebug.h> #include <QtCore/qtconcurrentexception.h> #include <QtCore/qwaitcondition.h> +#include <QtCore/qatomic.h> +#include <QtCore/qsemaphore.h> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -61,55 +63,24 @@ QT_MODULE(Core) namespace QtConcurrent { -// A Semaphore that can wait until all resources are returned. -class ThreadEngineSemaphore +// The ThreadEngineBarrier counts worker threads, and allows one +// thread to wait for all others to finish. Tested for its use in +// QtConcurrent, requires more testing for use as a general class. +class ThreadEngineBarrier { -public: - ThreadEngineSemaphore() - :count(0) { } - - void acquire() - { - QMutexLocker lock(&mutex); - ++count; - } - - int release() - { - QMutexLocker lock(&mutex); - if (--count == 0) - waitCondition.wakeAll(); - return count; - } - - // Wait until all resources are released. - void wait() - { - QMutexLocker lock(&mutex); - if (count != 0) - waitCondition.wait(&mutex); - } - - int currentCount() - { - return count; - } - - // releases a resource, unless this is the last resource. - // returns true if a resource was released. - bool releaseUnlessLast() - { - QMutexLocker lock(&mutex); - if (count == 1) - return false; - --count; - return true; - } - private: - QMutex mutex; - int count; - QWaitCondition waitCondition; + // The thread count is maintained as an integer in the count atomic + // variable. The count can be either positive or negative - a negative + // count signals that a thread is waiting on the barrier. + QAtomicInt count; + QSemaphore semaphore; +public: + ThreadEngineBarrier(); + void acquire(); + int release(); + void wait(); + int currentCount(); + bool releaseUnlessLast(); }; enum ThreadFunctionResult { ThrottleThread, ThreadFinished }; @@ -152,7 +123,7 @@ private: protected: QFutureInterfaceBase *futureInterface; QThreadPool *threadPool; - ThreadEngineSemaphore semaphore; + ThreadEngineBarrier barrier; QtConcurrent::internal::ExceptionStore exceptionStore; }; @@ -199,7 +170,7 @@ public: QFuture<T> future = QFuture<T>(futureInterfaceTyped()); start(); - semaphore.acquire(); + barrier.acquire(); threadPool->start(this); return future; } diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp index 83374da..9c53b7e 100644 --- a/src/corelib/concurrent/qthreadpool.cpp +++ b/src/corelib/concurrent/qthreadpool.cpp @@ -222,6 +222,8 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) int QThreadPoolPrivate::activeThreadCount() const { + // To improve scalability this function is called without holding + // the mutex lock -- keep it thread-safe. return (allThreads.count() - expiredThreads.count() - waitingThreads @@ -481,6 +483,12 @@ bool QThreadPool::tryStart(QRunnable *runnable) return false; Q_D(QThreadPool); + + // To improve scalability perform a check on the thread count + // before locking the mutex. + if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount) + return false; + QMutexLocker locker(&d->mutex); return d->tryStart(runnable); } @@ -527,7 +535,6 @@ void QThreadPool::setExpiryTimeout(int expiryTimeout) int QThreadPool::maxThreadCount() const { Q_D(const QThreadPool); - QMutexLocker locker(&d->mutex); return d->maxThreadCount; } @@ -556,7 +563,6 @@ void QThreadPool::setMaxThreadCount(int maxThreadCount) int QThreadPool::activeThreadCount() const { Q_D(const QThreadPool); - QMutexLocker locker(&d->mutex); return d->activeThreadCount(); } diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0721c39..b4b98e1 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -279,6 +279,10 @@ namespace QT_NAMESPACE {} # endif #endif +#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) +#error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." +#endif + #if defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN) # undef Q_OS_UNIX #elif !defined(Q_OS_UNIX) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 144436c..4743a47 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -558,24 +558,8 @@ static bool _q_isMacHidden(const QString &path) FSRef fsRef; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), - kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); - } else -#endif - { - QFileInfo fi(path); - FSRef parentRef; - err = FSPathMakeRef(reinterpret_cast<const UInt8 *>(fi.absoluteDir().absolutePath().toUtf8().constData()), - &parentRef, 0); - if (err == noErr) { - QString fileName = fi.fileName(); - err = FSMakeFSRefUnicode(&parentRef, fileName.length(), - reinterpret_cast<const UniChar *>(fileName.unicode()), - kTextEncodingUnknown, &fsRef); - } - } + err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), + kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); if (err != noErr) return false; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index b0247f8..e6a471c 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -643,8 +643,8 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) /*! Sends \a event to \a receiver: \a {receiver}->event(\a event). Returns the value that is returned from the receiver's event - handler. Note that this function is called for all events send to - any object is all threads. + handler. Note that this function is called for all events sent to + any object in any thread. For certain types of events (e.g. mouse and key events), the event will be propagated to the receiver's parent and so on up to diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index fd7ddef..83dd869 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -240,7 +240,7 @@ void QState::assignProperty(QObject *object, const char *name, } /*! - Returns this state group's error state. + Returns this state's error state. \sa QStateMachine::errorState(), QStateMachine::setErrorState() */ @@ -253,7 +253,9 @@ QAbstractState *QState::errorState() const /*! Sets this state's error state to be the given \a state. If the error state is not set, or if it is set to 0, the state will inherit its parent's error - state recursively. + 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() */ diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 682dd97..bf3ee31 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -156,16 +156,14 @@ QT_BEGIN_NAMESPACE transitions, e.g., \l{QSignalTransition}s as in this example. See the QState class description for further details. - If an error is encountered, the machine will enter the - \l{errorState}{error state}, which is a special state created by - the machine. The types of errors possible are described by the + If an error is encountered, the machine will look for an + \l{errorState}{error state}, and if one is available, it will + enter this state. The types of errors possible are described by the \l{QStateMachine::}{Error} enum. After the error state is entered, the type of the error can be retrieved with error(). The execution - of the state graph will not stop when the error state is entered. - So it is possible to handle the error, for instance, by connecting - to the \l{QAbstractState::}{entered()} signal of the error state. - It is also possible to set a custom error state with - setErrorState(). + of the state graph will not stop when the error state is entered. If + no error state applies to the erroneous state, the machine will stop + executing and an error message will be printed to the console. \omit This stuff will be moved elsewhere This is @@ -238,7 +236,6 @@ QStateMachinePrivate::QStateMachinePrivate() error = QStateMachine::NoError; globalRestorePolicy = QStateMachine::DoNotRestoreProperties; rootState = 0; - initialErrorStateForRoot = 0; signalEventGenerator = 0; #ifndef QT_NO_ANIMATION animationsEnabled = true; @@ -984,27 +981,25 @@ void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArra QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) { - // If the user sets the root state's error state to 0, we return the initial error state - if (context == 0) - return initialErrorStateForRoot; - // Find error state recursively in parent hierarchy if not set explicitly for context state QAbstractState *errorState = 0; - - QState *s = qobject_cast<QState*>(context); - if (s) - errorState = s->errorState(); + if (context != 0) { + QState *s = qobject_cast<QState*>(context); + if (s != 0) + errorState = s->errorState(); - if (!errorState) - errorState = findErrorState(context->parentState()); + if (errorState == 0) + errorState = findErrorState(context->parentState()); + } return errorState; } void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext) { + Q_Q(QStateMachine); + error = errorCode; - switch (errorCode) { case QStateMachine::NoInitialStateError: Q_ASSERT(currentContext != 0); @@ -1036,16 +1031,19 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta QAbstractState *currentErrorState = findErrorState(currentContext); // Avoid infinite loop if the error state itself has an error - if (currentContext == currentErrorState) { - Q_ASSERT(currentContext != initialErrorStateForRoot); // RootErrorState is broken - currentErrorState = initialErrorStateForRoot; - } + if (currentContext == currentErrorState) + currentErrorState = 0; - Q_ASSERT(currentErrorState != 0); Q_ASSERT(currentErrorState != rootState); - - QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); - addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); + + if (currentErrorState != 0) { + QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); + addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); + } else { + qWarning("Unrecoverable error detected in running state machine: %s", + qPrintable(errorString)); + q->stop(); + } } #ifndef QT_NO_ANIMATION @@ -1148,9 +1146,6 @@ void QStateMachinePrivate::_q_start() return; } QAbstractState *initial = rootState->initialState(); - if (initial == 0) - setError(QStateMachine::NoInitialStateError, rootState); - configuration.clear(); qDeleteAll(internalEventQueue); internalEventQueue.clear(); @@ -1483,27 +1478,6 @@ QStateMachine::~QStateMachine() namespace { -class RootErrorState : public QAbstractState -{ -public: - RootErrorState(QState *parent) - : QAbstractState(parent) - { - setObjectName(QString::fromLatin1("DefaultErrorState")); - } - - void onEntry(QEvent *) - { - QAbstractStatePrivate *d = QAbstractStatePrivate::get(this); - QStateMachine *machine = d->machine(); - - qWarning("Unrecoverable error detected in running state machine: %s", - qPrintable(machine->errorString())); - } - - void onExit(QEvent *) {} -}; - class RootState : public QState { public: @@ -1526,9 +1500,7 @@ QState *QStateMachine::rootState() const Q_D(const QStateMachine); if (!d->rootState) { const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0); - const_cast<QStateMachinePrivate*>(d)->initialErrorStateForRoot = new RootErrorState(d->rootState); d->rootState->setParent(const_cast<QStateMachine*>(this)); - d->rootState->setErrorState(d->initialErrorStateForRoot); } return d->rootState; } @@ -1552,17 +1524,13 @@ QAbstractState *QStateMachine::errorState() const 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 the states for which a more specific error state has not been set. + 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(). - - The default error state will print a warning to the console containing the information returned by - errorString(). By setting a new error state on either the state machine itself, or on specific - states, you can fine tune error handling in the state machine. + error message returned by errorString(). - If the root state's error state is set to 0, or if the error state selected by the machine itself - contains an error, the default error state will be used. + 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() */ diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index f3c6a27..1335b93 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -175,7 +175,6 @@ public: QString errorString; QSet<QAbstractState *> pendingErrorStates; QSet<QAbstractState *> pendingErrorStatesForDefaultEntry; - QAbstractState *initialErrorStateForRoot; #ifndef QT_NO_ANIMATION bool animationsEnabled; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index cbdd32c..8c1a0ff 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -1011,21 +1011,17 @@ static QString macMonthName(int month, bool short_format) if (month < 0 || month > 11) return QString(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDateFormatterRef> formatter - = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), - kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); - QCFType<CFArrayRef> values - = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, - short_format ? kCFDateFormatterShortMonthSymbols - : kCFDateFormatterMonthSymbols)); - if (values != 0) { - CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month)); - return QCFString::toQString(cfstring); - } + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values + = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortMonthSymbols + : kCFDateFormatterMonthSymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month)); + return QCFString::toQString(cfstring); } -#endif return QString(); } @@ -1035,20 +1031,16 @@ static QString macDayName(int day, bool short_format) if (day < 1 || day > 7) return QString(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDateFormatterRef> formatter - = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), - kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); - QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, - short_format ? kCFDateFormatterShortWeekdaySymbols - : kCFDateFormatterWeekdaySymbols)); - if (values != 0) { - CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7)); - return QCFString::toQString(cfstring); - } + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortWeekdaySymbols + : kCFDateFormatterWeekdaySymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7)); + return QCFString::toQString(cfstring); } -#endif return QString(); } diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 2082794..b4fe070 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2154,48 +2154,42 @@ bool QRectF::contains(const QRectF &r) const QRectF QRectF::operator|(const QRectF &r) const { - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - if (l1 == r1) // null rect + if (isNull()) return r; + if (r.isNull()) + return *this; - qreal l2 = r.xp; - qreal r2 = r.xp; - if (r.w < 0) - l2 += r.w; + qreal left = xp; + qreal right = xp; + if (w < 0) + left += w; else - r2 += r.w; - if (l2 == r2) // null rect - return *this; + right += w; - qreal t1 = yp; - qreal b1 = yp; + if (r.w < 0) { + left = qMin(left, r.xp + r.w); + right = qMax(right, r.xp); + } else { + left = qMin(left, r.xp); + right = qMax(right, r.xp + r.w); + } + + qreal top = yp; + qreal bottom = yp; if (h < 0) - t1 += h; + top += h; else - b1 += h; - if (t1 == b1) // null rect - return r; + bottom += h; - qreal t2 = r.yp; - qreal b2 = r.yp; - if (r.h < 0) - t2 += r.h; - else - b2 += r.h; - if (t2 == b2) // null rect - return *this; + if (r.h < 0) { + top = qMin(top, r.yp + r.h); + bottom = qMax(bottom, r.yp); + } else { + top = qMin(top, r.yp); + bottom = qMax(bottom, r.yp + r.h); + } - QRectF tmp; - tmp.xp = qMin(l1, l2); - tmp.yp = qMin(t1, t2); - tmp.w = qMax(r1, r2) - tmp.xp; - tmp.h = qMax(b1, b2) - tmp.yp; - return tmp; + return QRectF(left, top, right - left, bottom - top); } /*! diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 0740fe5..efdc24d 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -653,7 +653,7 @@ inline QRectF::QRectF(const QRect &r) } inline bool QRectF::isNull() const -{ return qIsNull(w) && qIsNull(h); } +{ return w == 0. && h == 0.; } inline bool QRectF::isEmpty() const { return w <= 0. || h <= 0.; } diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index f1487f7..1fc2a9f 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -3410,11 +3410,12 @@ void QXmlStreamWriter::writeComment(const QString &text) { Q_D(QXmlStreamWriter); Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-'))); - if (!d->finishStartElement() && d->autoFormatting) + if (!d->finishStartElement(false) && d->autoFormatting) d->indent(d->tagStack.size()); d->write("<!--"); d->write(text); d->write("-->"); + d->inStartElement = d->lastWasStartElement = false; } |