diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-18 11:33:26 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-18 11:33:26 (GMT) |
commit | e6e60b096bb8b5e5073e32220c74810e80bf2d25 (patch) | |
tree | ca247002a4193d0deeee3b4be369e830c7b4f778 /src | |
parent | 5a350be913139e2b994878c62ce06eb88604abbe (diff) | |
parent | c23d4d6644bff2195fbb6aa84d3425dc2d31491a (diff) | |
download | Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.zip Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.tar.gz Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/gui/graphicsview/qgraphicsitem_p.h
Diffstat (limited to 'src')
32 files changed, 447 insertions, 225 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index d3fa6a8..2977c7f 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1454,11 +1454,11 @@ QByteArray QIODevice::peek(qint64 maxSize) } /*! - Blocks until data is available for reading and the readyRead() + Blocks until new data is available for reading and the readyRead() signal has been emitted, or until \a msecs milliseconds have passed. If msecs is -1, this function will not time out. - Returns true if data is available for reading; otherwise returns + Returns true if new data is available for reading; otherwise returns false (if the operation timed out or if an error occurred). This function can operate without an event loop. It is diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ced6dd5..3b70f44 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -663,6 +663,74 @@ const QString::Null QString::null = { }; formats, the \e precision represents the maximum number of significant digits (trailing zeroes are omitted). + \section1 More Efficient String Construction + + Using the QString \c{'+'} operator, it is easy to construct a + complex string from multiple substrings. You will often write code + like this: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 0 + + There is nothing wrong with either of these string constructions, + but there are a few hidden inefficiencies. Beginning with Qt 4.6, + you can eliminate them. + + First, multiple uses of the \c{'+'} operator usually means + multiple memory allocations. When concatenating \e{n} substrings, + where \e{n > 2}, there can be as many as \e{n - 1} calls to the + memory allocator. + + Second, QLatin1String does not store its length internally but + calls qstrlen() when it needs to know its length. + + In 4.6, an internal template class \c{QStringBuilder} has been + added along with a few helper functions. This class is marked + internal and does not appear in the documentation, because you + aren't meant to instantiate it in your code. Its use will be + automatic, as described below. The class is found in + \c {src/corelib/tools/qstringbuilder.cpp} if you want to have a + look at it. + + \c{QStringBuilder} uses expression templates and reimplements the + \c{'%'} operator so that when you use \c{'%'} for string + concatenation instead of \c{'+'}, multiple substring + concatenations will be postponed until the final result is about + to be assigned to a QString. At this point, the amount of memory + required for the final result is known. The memory allocator is + then called \e{once} to get the required space, and the substrings + are copied into it one by one. + + \c{QLatin1Literal} is a second internal class that can replace + QLatin1String, which can't be changed for compatibility reasons. + \c{QLatin1Literal} stores its length, thereby saving time when + \c{QStringBuilder} computes the amount of memory required for the + final string. + + Additional efficiency is gained by inlining and reduced reference + counting (the QString created from a \c{QStringBuilder} typically + has a ref count of 1, whereas QString::append() needs an extra + test). + + There are three ways you can access this improved method of string + construction. The straightforward way is to include + \c{QStringBuilder} wherever you want to use it, and use the + \c{'%'} operator instead of \c{'+'} when concatenating strings: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 5 + + A more global approach is to include this define: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 3 + + and use \c{'%'} instead of \c{'+'} for string concatenation + everywhere. The third approach, which is the most convenient but + not entirely source compatible, is to include two defines: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 4 + + and the \c{'+'} will automatically be performed as the + \c{QStringBuilder} \c{'%'} everywhere. + \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef */ diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index 17e2cec..fbb784e 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -43,6 +43,7 @@ /*! \class QLatin1Literal + \internal \reentrant \since 4.6 @@ -83,6 +84,7 @@ /*! \class QStringBuilder + \internal \reentrant \since 4.6 diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 688130b..a0d061b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -56,6 +56,7 @@ #include "qgraphicsitem.h" #include "qset.h" #include "qpixmapcache.h" +#include "qgraphicsview_p.h" #include <QtCore/qpoint.h> @@ -158,6 +159,8 @@ public: geometryChanged(0), inDestructor(0), isObject(0), + ignoreVisible(0), + ignoreOpacity(0), acceptTouchEvents(0), acceptedTouchBeginEvent(0), globalStackingOrder(-1), @@ -181,7 +184,7 @@ public: void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; - + // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); @@ -250,7 +253,7 @@ public: } } } - + struct ExtraStruct { ExtraStruct(Extra type, QVariant value) : type(type), value(value) @@ -262,7 +265,7 @@ public: bool operator<(Extra extra) const { return type < extra; } }; - + QList<ExtraStruct> extras; QGraphicsItemCache *maybeExtraItemCache() const; @@ -337,6 +340,15 @@ public: return calcEffectiveOpacity(); } + inline qreal combineOpacityFromParent(qreal parentOpacity) const + { + if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + return parentOpacity * opacity; + } + return opacity; + } + inline bool childrenCombineOpacity() const { if (!children.size()) @@ -423,8 +435,8 @@ public: quint32 cacheMode : 2; quint32 hasBoundingRegionGranularity : 1; quint32 isWidget : 1; - quint32 dirty : 1; - quint32 dirtyChildren : 1; + quint32 dirty : 1; + quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; @@ -441,9 +453,11 @@ public: quint32 geometryChanged : 1; quint32 inDestructor : 1; quint32 isObject : 1; + quint32 ignoreVisible : 1; + quint32 ignoreOpacity : 1; quint32 acceptTouchEvents : 1; quint32 acceptedTouchBeginEvent : 1; - quint32 unused : 12; // feel free to use + quint32 unused : 10; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 13b1b5a..7428d79 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5180,14 +5180,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item) { if (!item->d_ptr->visible) return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity(); if (!invisibleButChildIgnoresParentOpacity) @@ -5337,7 +5330,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); + + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) + item->paint(painter, &styleOptionTmp, widget); + else + drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); if (savePainter) painter->restore(); @@ -5421,6 +5418,11 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->dirtyChildren = 1; } + if (force) + item->d_ptr->ignoreVisible = 1; + if (ignoreOpacity) + item->d_ptr->ignoreOpacity = 1; + QGraphicsItem *p = item->d_ptr->parent; while (p && !p->d_ptr->dirtyChildren) { p->d_ptr->dirtyChildren = 1; @@ -5428,34 +5430,58 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren) +static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, + const QRectF &rect, const QTransform &xform) +{ + Q_ASSERT(view); + Q_ASSERT(item); + if (item->hasBoundingRegionGranularity) + return view->updateRegion(xform.map(QRegion(rect.toRect()))); + return view->updateRect(xform.mapRect(rect).toRect()); +} + +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, + qreal parentOpacity) { Q_Q(QGraphicsScene); - // Calculate the full scene transform for this item. + bool wasDirtyParentViewBoundingRects = false; bool wasDirtyParentSceneTransform = false; - if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) { - item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : QTransform(); - item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); - item->d_ptr->dirtySceneTransform = 0; - wasDirtyParentSceneTransform = true; + qreal opacity = parentOpacity; + + if (item) { + wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; + const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity == 0.0; + + if (item->d_ptr->dirtySceneTransform && !itemIsHidden && !item->d_ptr->itemIsUntransformable() + && !(itemIsFullyTransparent && item->d_ptr->childrenCombineOpacity())) { + // Calculate the full scene transform for this item. + item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform + : QTransform(); + item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); + item->d_ptr->dirtySceneTransform = 0; + wasDirtyParentSceneTransform = true; + } + + if (itemIsHidden || itemIsFullyTransparent || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { + // Make sure we don't process invisible items or items with no content. + item->d_ptr->dirty = 0; + item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + } } // Process item. - bool wasDirtyParentViewBoundingRects = false; if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); const bool untransformableItem = item->d_ptr->itemIsUntransformable(); - const QRectF itemBoundingRect = item->boundingRect(); + const QRectF itemBoundingRect = adjustedItemBoundingRect(item); if (item->d_ptr->geometryChanged) { // Update growingItemsBoundingRect. - if (!hasSceneRect) { - QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - _q_adjustRect(&itemSceneBoundingRect); - growingItemsBoundingRect |= itemSceneBoundingRect; - } + if (!hasSceneRect) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect); item->d_ptr->geometryChanged = 0; } @@ -5484,11 +5510,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool break; } + QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { wasDirtyParentViewBoundingRects = true; - QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport); - rect.translate(viewPrivate->dirtyScrollOffset); - viewPrivate->updateRect(rect); + paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); + if (!viewPrivate->updateRect(paintedViewBoundingRect)) + paintedViewBoundingRect = QRect(); } if (!item->d_ptr->dirty) @@ -5496,7 +5523,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (uninitializedDirtyRect) { dirtyRect = itemBoundingRect; - _q_adjustRect(&dirtyRect); if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; @@ -5507,17 +5533,19 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (dirtyRect.isEmpty()) continue; // Discard updates outside the bounding rect. - QTransform deviceTransform = item->d_ptr->sceneTransform; - if (view->isTransformed()) { - if (!untransformableItem) - deviceTransform *= view->viewportTransform(); - else - deviceTransform = item->deviceTransform(view->viewportTransform()); + bool valid = false; + if (untransformableItem) { + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, + item->deviceTransform(view->viewportTransform())); + } else if (!view->isTransformed()) { + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform); + } else { + QTransform deviceTransform = item->d_ptr->sceneTransform; + deviceTransform *= view->viewportTransform(); + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform); } - if (item->d_ptr->hasBoundingRegionGranularity) - viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect()))); - else - viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect()); + if (!valid) + paintedViewBoundingRect = QRect(); } } } @@ -5530,12 +5558,18 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); } + const bool parentIgnoresVisible = item && item->d_ptr->ignoreVisible; + const bool parentIgnoresOpacity = item && item->d_ptr->ignoreOpacity; for (int i = 0; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; if (wasDirtyParentViewBoundingRects) child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1; + if (parentIgnoresVisible) + child->d_ptr->ignoreVisible = 1; + if (parentIgnoresOpacity) + child->d_ptr->ignoreOpacity = 1; if (allChildrenDirty) { child->d_ptr->dirty = 1; @@ -5558,7 +5592,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } - processDirtyItemsRecursive(child, dirtyAncestorContainsChildren); + processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b3f168c..983486f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -271,7 +271,8 @@ public: void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false); - void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false); + void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, + qreal parentOpacity = qreal(1.0)); inline void resetDirtyItem(QGraphicsItem *item) { @@ -283,6 +284,8 @@ public: item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; item->d_ptr->fullUpdatePending = 0; + item->d_ptr->ignoreVisible = 0; + item->d_ptr->ignoreOpacity = 0; } QStyle *style; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 47a492b..6ac2914 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -846,19 +846,22 @@ void QGraphicsViewPrivate::processPendingUpdates() dirtyRegion = QRegion(); } -void QGraphicsViewPrivate::updateRegion(const QRegion &r) +bool QGraphicsViewPrivate::updateRegion(const QRegion &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) + return false; + + const QRect boundingRect = r.boundingRect(); + if (!boundingRect.intersects(viewport->rect())) + return false; // Update region outside viewport. - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; viewport->update(); break; case QGraphicsView::BoundingRectViewportUpdate: - dirtyBoundingRect |= r.boundingRect(); + dirtyBoundingRect |= boundingRect; if (dirtyBoundingRect.contains(viewport->rect())) { fullUpdatePending = true; viewport->update(); @@ -876,18 +879,20 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) } break; } - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } -void QGraphicsViewPrivate::updateRect(const QRect &r) +bool QGraphicsViewPrivate::updateRect(const QRect &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate + || !r.intersects(viewport->rect())) { + return false; + } - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; @@ -907,10 +912,11 @@ void QGraphicsViewPrivate::updateRect(const QRect &r) else dirtyRegion += r.adjusted(-2, -2, 2, 2); break; - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems) @@ -3288,10 +3294,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Determine the exposed region d->exposedRegion = event->region(); - if (!d->accelerateScrolling) - d->exposedRegion = viewport()->rect(); - else if (d->viewportUpdateMode == BoundingRectViewportUpdate) - d->exposedRegion = event->rect(); QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); // Set up the painter @@ -3305,8 +3307,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event) painter.setRenderHints(d->renderHints, true); // Set up viewport transform - const QTransform viewTransform = viewportTransform(); - painter.setWorldTransform(viewTransform); + const bool viewTransformed = isTransformed(); + if (viewTransformed) + painter.setWorldTransform(viewportTransform()); + const QTransform viewTransform = painter.worldTransform(); // Draw background if ((d->cacheMode & CacheBackground) @@ -3331,16 +3335,21 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!d->backgroundPixmapExposed.isEmpty()) { QPainter backgroundPainter(&d->backgroundPixmap); backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); - backgroundPainter.setTransform(viewportTransform()); + if (viewTransformed) + backgroundPainter.setTransform(viewTransform); backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); drawBackground(&backgroundPainter, exposedSceneRect); d->backgroundPixmapExposed = QRegion(); } // Blit the background from the background pixmap - painter.setWorldTransform(QTransform()); - painter.drawPixmap(QPoint(), d->backgroundPixmap); - painter.setWorldTransform(viewTransform); + if (viewTransformed) { + painter.setWorldTransform(QTransform()); + painter.drawPixmap(QPoint(), d->backgroundPixmap); + painter.setWorldTransform(viewTransform); + } else { + painter.drawPixmap(QPoint(), d->backgroundPixmap); + } } else { if (!(d->optimizationFlags & DontSavePainterState)) painter.save(); @@ -3363,8 +3372,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const int numItems = itemList.size(); QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); - for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); + for (int i = 0; i < numItems; ++i) { + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, + d->exposedRegion, allItems); + } // Draw the items. drawItems(&painter, numItems, itemArray, styleOptionArray); d->freeStyleOptionsArray(styleOptionArray); diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 903ca2b..5682138 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -171,8 +171,8 @@ public: dirtyBoundingRect = QRect(); dirtyRegion = QRegion(); } - void updateRect(const QRect &rect); - void updateRegion(const QRegion ®ion); + bool updateRect(const QRect &rect); + bool updateRegion(const QRegion ®ion); bool updateSceneSlotReimplementedChecked; QRegion exposedRegion; diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 9b25730..f1b0d19 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -827,6 +827,8 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e */ void QListView::mouseMoveEvent(QMouseEvent *e) { + if (!isVisible()) + return; Q_D(QListView); QAbstractItemView::mouseMoveEvent(e); if (state() == DragSelectingState diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index fef51f9..19c5928 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -4617,6 +4617,46 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) } #endif +struct qt_tablet_motion_data +{ + Time timestamp; + int tabletMotionType; + bool error; // found a reason to stop searching +}; + +static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + + if (event->type == MotionNotify) + return true; + + data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between. + return false; +} + +static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + + if (event->type == data->tabletMotionType) { + if (data->timestamp > 0) { + if ((reinterpret_cast<const XDeviceMotionEvent*>(event))->time > data->timestamp) { + data->error = true; + return false; + } + } + return true; + } + + data->error = event->type != MotionNotify; // we stop compression when another event gets in between. + return false; +} + bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet) { #if defined (Q_OS_IRIX) @@ -4643,7 +4683,6 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet qreal rotation = 0; int deviceType = QTabletEvent::NoDevice; int pointerType = QTabletEvent::UnknownPointer; - XEvent xinputMotionEvent; XEvent mouseMotionEvent; const XDeviceMotionEvent *motion = 0; XDeviceButtonEvent *button = 0; @@ -4651,8 +4690,6 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet QEvent::Type t; Qt::KeyboardModifiers modifiers = 0; bool reinsertMouseEvent = false; - bool neverFoundMouseEvent = true; - XEvent xinputMotionEventNext; XEvent mouseMotionEventSave; #if !defined (Q_OS_IRIX) XID device_id; @@ -4660,72 +4697,41 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet if (ev->type == tablet->xinput_motion) { motion = reinterpret_cast<const XDeviceMotionEvent*>(ev); - for (;;) { - // get the corresponding mouseMotionEvent for motion - if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) { + + // Do event compression. Skip over tablet+mouse move events if there are newer ones. + qt_tablet_motion_data tabletMotionData; + tabletMotionData.tabletMotionType = tablet->xinput_motion; + while (true) { + // Find first mouse event since we expect them in pairs inside Qt + tabletMotionData.error =false; + tabletMotionData.timestamp = 0; + if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) { mouseMotionEventSave = mouseMotionEvent; reinsertMouseEvent = true; - neverFoundMouseEvent = false; - - if (mouseMotionEvent.xmotion.time > motion->time) { - XEvent xinputMotionEventLoop = *ev; - - // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event - while (mouseMotionEvent.xmotion.time > (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEventLoop))->time) { - if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - } - else { - break; - } - } - motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent); - } - - // get the next xinputMotionEvent, for the next loop run - if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) { - XPutBackEvent(X11->display, &mouseMotionEvent); - reinsertMouseEvent = false; - break; - } - - if (mouseMotionEvent.xmotion.time != motion->time) { - // reinsert in order - if (mouseMotionEvent.xmotion.time >= motion->time) { - XPutBackEvent(X11->display, &mouseMotionEvent); - XPutBackEvent(X11->display, &xinputMotionEventNext); - // next entry in queue is xinputMotionEventNext - } - else { - XPutBackEvent(X11->display, &xinputMotionEventNext); - XPutBackEvent(X11->display, &mouseMotionEvent); - // next entry in queue is mouseMotionEvent - } - reinsertMouseEvent = false; - break; - } - } - else { + } else { break; } - xinputMotionEvent = xinputMotionEventNext; - motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent)); - } + // Now discard any duplicate tablet events. + XEvent dummy; + tabletMotionData.error = false; + tabletMotionData.timestamp = mouseMotionEvent.xmotion.time; + while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy); + } - if (reinsertMouseEvent) { - XPutBackEvent(X11->display, &mouseMotionEventSave); + // now check if there are more recent tablet motion events since we'll compress the current one with + // newer ones in that case + tabletMotionData.error = false; + tabletMotionData.timestamp = 0; + if (! XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + break; // done with compression + } + motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy); } - if (neverFoundMouseEvent) { - XEvent xinputMotionEventLoop; - bool eventFound = false; - // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent - while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - eventFound = true; - } - if (eventFound) motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent); + if (reinsertMouseEvent) { + XPutBackEvent(X11->display, &mouseMotionEventSave); } t = QEvent::TabletMove; diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 3857e30..34de252 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1253,7 +1253,8 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e) void QMenuBar::leaveEvent(QEvent *) { Q_D(QMenuBar); - if(!hasFocus() && !d->popupState) + if((!hasFocus() && !d->popupState) || + (d->currentAction && d->currentAction->menu() == 0)) d->setCurrentAction(0); } diff --git a/src/network/access/qnetworkaccesscache_p.h b/src/network/access/qnetworkaccesscache_p.h index 3fdfbb4..439b3a0 100644 --- a/src/network/access/qnetworkaccesscache_p.h +++ b/src/network/access/qnetworkaccesscache_p.h @@ -64,6 +64,9 @@ QT_BEGIN_NAMESPACE class QNetworkRequest; class QUrl; +// this class is not about caching files but about +// caching objects used by QNetworkAccessManager, e.g. existing TCP connections +// or credentials. class QNetworkAccessCache: public QObject { Q_OBJECT diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 9be433d..d6276a3 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -82,11 +82,11 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, return 0; } -class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject +class QNetworkAccessCachedFtpConnection: public QFtp, public QNetworkAccessCache::CacheableObject { // Q_OBJECT public: - QNetworkAccessFtpFtp() + QNetworkAccessCachedFtpConnection() { setExpires(true); setShareable(false); @@ -148,11 +148,11 @@ void QNetworkAccessFtpBackend::open() } state = LoggingIn; - QNetworkAccessCache* cache = QNetworkAccessManagerPrivate::getCache(this); + QNetworkAccessCache* objectCache = QNetworkAccessManagerPrivate::getObjectCache(this); QByteArray cacheKey = makeCacheKey(url); - if (!cache->requestEntry(cacheKey, this, + if (!objectCache->requestEntry(cacheKey, this, SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) { - ftp = new QNetworkAccessFtpFtp; + ftp = new QNetworkAccessCachedFtpConnection; #ifndef QT_NO_NETWORKPROXY if (proxy.type() == QNetworkProxy::FtpCachingProxy) ftp->setProxy(proxy.hostName(), proxy.port()); @@ -160,7 +160,7 @@ void QNetworkAccessFtpBackend::open() ftp->connectToHost(url.host(), url.port(DefaultFtpPort)); ftp->login(url.userName(), url.password()); - cache->addEntry(cacheKey, ftp); + objectCache->addEntry(cacheKey, ftp); ftpConnectionReady(ftp); } @@ -207,7 +207,7 @@ void QNetworkAccessFtpBackend::downstreamReadyWrite() void QNetworkAccessFtpBackend::ftpConnectionReady(QNetworkAccessCache::CacheableObject *o) { - ftp = static_cast<QNetworkAccessFtpFtp *>(o); + ftp = static_cast<QNetworkAccessCachedFtpConnection *>(o); connect(ftp, SIGNAL(done(bool)), SLOT(ftpDone())); connect(ftp, SIGNAL(rawCommandReply(int,QString)), SLOT(ftpRawCommandReply(int,QString))); connect(ftp, SIGNAL(readyRead()), SLOT(ftpReadyRead())); @@ -227,7 +227,7 @@ void QNetworkAccessFtpBackend::disconnectFromFtp() disconnect(ftp, 0, this, 0); QByteArray key = makeCacheKey(url()); - QNetworkAccessManagerPrivate::getCache(this)->releaseEntry(key); + QNetworkAccessManagerPrivate::getObjectCache(this)->releaseEntry(key); ftp = 0; } @@ -278,7 +278,7 @@ void QNetworkAccessFtpBackend::ftpDone() // we're not connected, so remove the cache entry: QByteArray key = makeCacheKey(url()); - QNetworkAccessManagerPrivate::getCache(this)->removeEntry(key); + QNetworkAccessManagerPrivate::getObjectCache(this)->removeEntry(key); disconnect(ftp, 0, this, 0); ftp->dispose(); diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h index 9626403..bb6d766 100644 --- a/src/network/access/qnetworkaccessftpbackend_p.h +++ b/src/network/access/qnetworkaccessftpbackend_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QNetworkAccessFtpIODevice; -class QNetworkAccessFtpFtp; +class QNetworkAccessCachedFtpConnection; class QNetworkAccessFtpBackend: public QNetworkAccessBackend { @@ -101,7 +101,7 @@ public slots: private: friend class QNetworkAccessFtpIODevice; - QPointer<QNetworkAccessFtpFtp> ftp; + QPointer<QNetworkAccessCachedFtpConnection> ftp; QIODevice *uploadDevice; qint64 totalBytes; int helpId, sizeId, mdtmId; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 460cbe3..71808d4 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -270,12 +270,12 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const return code; } -class QNetworkAccessHttpBackendCache: public QHttpNetworkConnection, +class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection, public QNetworkAccessCache::CacheableObject { // Q_OBJECT public: - QNetworkAccessHttpBackendCache(const QString &hostName, quint16 port, bool encrypt) + QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt) : QHttpNetworkConnection(hostName, port, encrypt) { setExpires(true); @@ -311,11 +311,15 @@ QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend() void QNetworkAccessHttpBackend::disconnectFromHttp() { if (http) { + // This is abut disconnecting signals, not about disconnecting TCP connections disconnect(http, 0, this, 0); - QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this); + + // Get the object cache that stores our QHttpNetworkConnection objects + QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this); cache->releaseEntry(cacheKey); } + // This is abut disconnecting signals, not about disconnecting TCP connections if (httpReply) disconnect(httpReply, 0, this, 0); @@ -582,16 +586,20 @@ void QNetworkAccessHttpBackend::open() // check if we have an open connection to this host cacheKey = makeCacheKey(this, theProxy); - QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this); - if ((http = static_cast<QNetworkAccessHttpBackendCache *>(cache->requestEntryNow(cacheKey))) == 0) { + QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this); + // the http object is actually a QHttpNetworkConnection + http = static_cast<QNetworkAccessCachedHttpConnection *>(cache->requestEntryNow(cacheKey)); + if (http == 0) { // no entry in cache; create an object - http = new QNetworkAccessHttpBackendCache(url.host(), url.port(), encrypt); + // the http object is actually a QHttpNetworkConnection + http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt); #ifndef QT_NO_NETWORKPROXY http->setTransparentProxy(transparentProxy); http->setCacheProxy(cacheProxy); #endif + // cache the QHttpNetworkConnection corresponding to this cache key cache->addEntry(cacheKey, http); } diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index e0801ce..dec69d0 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE -class QNetworkAccessHttpBackendCache; +class QNetworkAccessCachedHttpConnection; class QNetworkAccessHttpBackendIODevice; @@ -106,7 +106,7 @@ private slots: private: QHttpNetworkReply *httpReply; - QPointer<QNetworkAccessHttpBackendCache> http; + QPointer<QNetworkAccessCachedHttpConnection> http; QByteArray cacheKey; QNetworkAccessBackendUploadIODevice *uploadDevice; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 0ae920b..ed2f220 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -836,7 +836,7 @@ void QNetworkAccessManagerPrivate::addCredentials(const QNetworkProxy &p, QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache; auth->insert(QString(), authenticator->user(), authenticator->password()); - cache.addEntry(cacheKey, auth); // replace the existing one, if there's any + objectCache.addEntry(cacheKey, auth); // replace the existing one, if there's any if (realm.isEmpty()) { break; @@ -870,13 +870,13 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QNetworkProxy &p, QByteArray cacheKey = proxyAuthenticationKey(proxy, realm); if (cacheKey.isEmpty()) return 0; - if (!cache.hasEntry(cacheKey)) + if (!objectCache.hasEntry(cacheKey)) return 0; QNetworkAuthenticationCache *auth = - static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey)); + static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey)); QNetworkAuthenticationCredential *cred = auth->findClosestMatch(QString()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); // proxy cache credentials always have exactly one item Q_ASSERT_X(cred, "QNetworkAccessManager", @@ -917,15 +917,15 @@ void QNetworkAccessManagerPrivate::addCredentials(const QUrl &url, copy.setUserName(authenticator->user()); do { QByteArray cacheKey = authenticationKey(copy, realm); - if (cache.hasEntry(cacheKey)) { + if (objectCache.hasEntry(cacheKey)) { QNetworkAuthenticationCache *auth = - static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey)); + static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey)); auth->insert(domain, authenticator->user(), authenticator->password()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); } else { QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache; auth->insert(domain, authenticator->user(), authenticator->password()); - cache.addEntry(cacheKey, auth); + objectCache.addEntry(cacheKey, auth); } if (copy.userName().isEmpty()) { @@ -959,19 +959,19 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QUrl &url, realm = authentication->realm(); QByteArray cacheKey = authenticationKey(url, realm); - if (!cache.hasEntry(cacheKey)) + if (!objectCache.hasEntry(cacheKey)) return 0; QNetworkAuthenticationCache *auth = - static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey)); + static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey)); QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); return cred; } void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager) { - manager->d_func()->cache.clear(); + manager->d_func()->objectCache.clear(); } QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index c80613b..bcf9a2b 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -98,10 +98,12 @@ public: QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request); + // this is the cache for storing downloaded files QAbstractNetworkCache *networkCache; + QNetworkCookieJar *cookieJar; - QNetworkAccessCache cache; + #ifndef QT_NO_NETWORKPROXY QNetworkProxy proxy; QNetworkProxyFactory *proxyFactory; @@ -109,8 +111,12 @@ public: bool cookieJarCreated; - static inline QNetworkAccessCache *getCache(QNetworkAccessBackend *backend) - { return &backend->manager->cache; } + + // this cache can be used by individual backends to cache e.g. their TCP connections to a server + // and use the connections for multiple requests. + QNetworkAccessCache objectCache; + static inline QNetworkAccessCache *getObjectCache(QNetworkAccessBackend *backend) + { return &backend->manager->objectCache; } Q_AUTOTEST_EXPORT static void clearCache(QNetworkAccessManager *manager); Q_DECLARE_PUBLIC(QNetworkAccessManager) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 19bfe51..d099382 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1658,13 +1658,13 @@ bool QAbstractSocket::waitForConnected(int msecs) } /*! - This function blocks until data is available for reading and the + This function blocks until new data is available for reading and the \l{QIODevice::}{readyRead()} signal has been emitted. The function will timeout after \a msecs milliseconds; the default timeout is 30000 milliseconds. The function returns true if the readyRead() signal is emitted and - there is data available for reading; otherwise it returns false + there is new data available for reading; otherwise it returns false (if an error occurred or the operation timed out). \sa waitForBytesWritten() diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index d2cd0d6..9d8cfb0 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -71,9 +71,10 @@ After loading a certificate, you can find information about the certificate, its subject, and its issuer, by calling one of the many accessor functions, including version(), serialNumber(), - issuerInfo() and subjectInfo(). You can call notValidBefore() and - notValidAfter() to check when the certificate was issued, and when - it expires. The publicKey() function returns the certificate + issuerInfo() and subjectInfo(). You can call effectiveDate() and + expiryDate() to check when the certificate starts being + effective and when it expires. + The publicKey() function returns the certificate subject's public key as a QSslKey. You can call issuerInfo() or subjectInfo() to get detailed information about the certificate issuer and its subject. diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 84ad4d5..b594f5b 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -662,6 +662,7 @@ public: , txop(QTransform::TxNone) , inverseScale(1) , moveToCount(0) + , last_created_state(0) , shader_ctx(0) , grad_palette(0) , drawable_texture(0) @@ -788,6 +789,8 @@ public: void updateGLMatrix() const; + mutable QPainterState *last_created_state; + QGLContext *shader_ctx; GLuint grad_palette; @@ -2219,6 +2222,8 @@ void QOpenGLPaintEnginePrivate::updateDepthClip() { Q_Q(QOpenGLPaintEngine); + ++q->state()->depthClipId; + glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); @@ -5501,9 +5506,20 @@ void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) void QOpenGLPaintEngine::setState(QPainterState *s) { Q_D(QOpenGLPaintEngine); + QOpenGLPaintEngineState *new_state = static_cast<QOpenGLPaintEngineState *>(s); + QOpenGLPaintEngineState *old_state = state(); + QPaintEngineEx::setState(s); + + // are we in a save() ? + if (s == d->last_created_state) { + d->last_created_state = 0; + return; + } + if (isActive()) { - d->updateDepthClip(); + if (old_state->depthClipId != new_state->depthClipId) + d->updateDepthClip(); penChanged(); brushChanged(); opacityChanged(); @@ -5515,12 +5531,15 @@ void QOpenGLPaintEngine::setState(QPainterState *s) QPainterState *QOpenGLPaintEngine::createState(QPainterState *orig) const { + const Q_D(QOpenGLPaintEngine); + QOpenGLPaintEngineState *s; if (!orig) s = new QOpenGLPaintEngineState(); else s = new QOpenGLPaintEngineState(*static_cast<QOpenGLPaintEngineState *>(orig)); + d->last_created_state = s; return s; } @@ -5534,11 +5553,13 @@ QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other) clipRegion = other.clipRegion; hasClipping = other.hasClipping; fastClip = other.fastClip; + depthClipId = other.depthClipId; } QOpenGLPaintEngineState::QOpenGLPaintEngineState() { hasClipping = false; + depthClipId = 0; } QOpenGLPaintEngineState::~QOpenGLPaintEngineState() diff --git a/src/opengl/qpaintengine_opengl_p.h b/src/opengl/qpaintengine_opengl_p.h index 891cbd6..439782b 100644 --- a/src/opengl/qpaintengine_opengl_p.h +++ b/src/opengl/qpaintengine_opengl_p.h @@ -69,6 +69,7 @@ public: QRegion clipRegion; bool hasClipping; QRect fastClip; + uint depthClipId; }; class QOpenGLPaintEngine : public QPaintEngineEx diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 52f6a37..905fec3 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -129,18 +129,14 @@ int QDirectFBPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const if (!dfbSurface) return 0; - int w, h; - dfbSurface->GetSize(dfbSurface, &w, &h); - switch (metric) { case QPaintDevice::PdmWidth: - return w; case QPaintDevice::PdmHeight: - return h; + return (metric == PdmWidth ? size().width() : size().height()); case QPaintDevice::PdmWidthMM: - return (w * 1000) / dotsPerMeterX(); + return (size().width() * 1000) / dotsPerMeterX(); case QPaintDevice::PdmHeightMM: - return (h * 1000) / dotsPerMeterY(); + return (size().height() * 1000) / dotsPerMeterY(); case QPaintDevice::PdmPhysicalDpiX: case QPaintDevice::PdmDpiX: return (dotsPerMeterX() * 254) / 10000; // 0.0254 meters-per-inch diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c239248..1c86466 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -72,9 +72,10 @@ void QDirectFBPixmapData::resize(int width, int height) } format = screen->pixelFormat(); - dfbSurface = QDirectFBScreen::instance()->createDFBSurface(QSize(width, height), - format, - QDirectFBScreen::TrackSurface); + dfbSurface = screen->createDFBSurface(QSize(width, height), + format, + QDirectFBScreen::TrackSurface); + d = screen->depth(); alpha = false; if (!dfbSurface) { invalidate(); @@ -195,8 +196,8 @@ void QDirectFBPixmapData::fromImage(const QImage &i, invalidate(); return; } - w = metric(QPaintDevice::PdmWidth); - h = metric(QPaintDevice::PdmHeight); + w = img.width(); + h = img.height(); is_null = (w <= 0 || h <= 0); d = metric(QPaintDevice::PdmDepth); setSerialNumber(++global_ser_no); @@ -209,7 +210,8 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) return; } - IDirectFBSurface *src = static_cast<const QDirectFBPixmapData*>(data)->directFBSurface(); + const QDirectFBPixmapData *otherData = static_cast<const QDirectFBPixmapData*>(data); + IDirectFBSurface *src = otherData->directFBSurface(); alpha = data->hasAlphaChannel(); format = (alpha ? QDirectFBScreen::instance()->alphaPixmapFormat() @@ -232,6 +234,9 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) } const DFBRectangle blitRect = { rect.x(), rect.y(), rect.width(), rect.height() }; + w = rect.width(); + h = rect.height(); + d = otherData->d; DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); #if (Q_DIRECTFB_VERSION >= 0x010000) dfbSurface->ReleaseSource(dfbSurface); @@ -303,9 +308,6 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, return QPixmap(data); } - int w, h; - dfbSurface->GetSize(dfbSurface, &w, &h); - const QSize size = transform.mapRect(QRect(0, 0, w, h)).size(); if (size.isEmpty()) return QPixmap(); @@ -326,6 +328,8 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, const DFBRectangle destRect = { 0, 0, size.width(), size.height() }; data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect); + data->w = size.width(); + data->h = size.height(); #if (Q_DIRECTFB_VERSION >= 0x010000) data->dfbSurface->ReleaseSource(data->dfbSurface); #endif @@ -338,7 +342,7 @@ QImage QDirectFBPixmapData::toImage() const return QImage(); #ifndef QT_NO_DIRECTFB_PREALLOCATED - QImage ret(size(), QDirectFBScreen::getImageFormat(dfbSurface)); + QImage ret(w, h, QDirectFBScreen::getImageFormat(dfbSurface)); if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { if (hasAlphaChannel()) { imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL); @@ -387,6 +391,7 @@ void QDirectFBPixmapData::invalidate() { setSerialNumber(0); alpha = false; + d = w = h = 0; format = QImage::Format_Invalid; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 5d89994..62fef5b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -751,12 +751,7 @@ QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ return new QDirectFBPixmapData(type); } -#ifdef QT_NO_DEBUG -struct FlagDescription; -static const FlagDescription *accelerationDescriptions = 0; -static const FlagDescription *blitDescriptions = 0; -static const FlagDescription *drawDescriptions = 0; -#else +#ifndef QT_NO_DEBUG struct FlagDescription { const char *name; uint flag; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index c2c9a59..4239156 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -118,6 +118,7 @@ public: SurfaceCreationOptions options); void releaseDFBSurface(IDirectFBSurface *surface); + using QScreen::depth; static int depth(DFBSurfacePixelFormat format); static DFBSurfacePixelFormat getSurfacePixelFormat(QImage::Format format); diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp index 9cca8ad..20de788 100644 --- a/src/scripttools/debugging/qscriptdebugger.cpp +++ b/src/scripttools/debugging/qscriptdebugger.cpp @@ -75,10 +75,6 @@ #include "qscriptdebuggerjob_p_p.h" #include "qscriptxmlparser_p.h" -#include "qscriptenginedebuggerfrontend_p.h" -#include "qscriptdebuggerbackend_p.h" -#include <QtScript/qscriptengine.h> - #include "private/qobject_p.h" #include <QtScript/qscriptcontext.h> @@ -1946,6 +1942,12 @@ QToolBar *QScriptDebugger::createStandardToolBar(QWidget *widgetParent, QObject return tb; } +bool QScriptDebugger::isInteractive() const +{ + Q_D(const QScriptDebugger); + return d->interactive; +} + /*! \reimp */ diff --git a/src/scripttools/debugging/qscriptdebugger_p.h b/src/scripttools/debugging/qscriptdebugger_p.h index 9ed7e0a..ba27200 100644 --- a/src/scripttools/debugging/qscriptdebugger_p.h +++ b/src/scripttools/debugging/qscriptdebugger_p.h @@ -172,6 +172,8 @@ public: bool eventFilter(QObject *, QEvent *e); + bool isInteractive() const; + Q_SIGNALS: void stopped() const; void started() const; diff --git a/src/scripttools/debugging/qscriptdebuggerbackend.cpp b/src/scripttools/debugging/qscriptdebuggerbackend.cpp index 9eaf571..7f4211c 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend.cpp +++ b/src/scripttools/debugging/qscriptdebuggerbackend.cpp @@ -412,14 +412,15 @@ void QScriptDebuggerBackend::attachTo(QScriptEngine *engine) detach(); d->agent = new QScriptDebuggerAgent(d, engine); QScriptValue global = engine->globalObject(); + d->origTraceFunction = global.property(QString::fromLatin1("print")); global.setProperty(QString::fromLatin1("print"), traceFunction()); // global.setProperty(QString::fromLatin1("qAssert"), assertFunction()); + d->origFileNameFunction = global.property(QString::fromLatin1("__FILE__")); global.setProperty(QString::fromLatin1("__FILE__"), fileNameFunction(), - QScriptValue::PropertyGetter | QScriptValue::PropertySetter - | QScriptValue::ReadOnly); + QScriptValue::PropertyGetter | QScriptValue::ReadOnly); + d->origLineNumberFunction = global.property(QString::fromLatin1("__LINE__")); global.setProperty(QString::fromLatin1("__LINE__"), lineNumberFunction(), - QScriptValue::PropertyGetter | QScriptValue::PropertySetter - | QScriptValue::ReadOnly); + QScriptValue::PropertyGetter | QScriptValue::ReadOnly); engine->setAgent(d->agent); } @@ -433,21 +434,25 @@ void QScriptDebuggerBackend::attachTo(QScriptEngine *engine) void QScriptDebuggerBackend::detach() { Q_D(QScriptDebuggerBackend); - if (!d->agent) - return; - QScriptEngine *eng = d->agent->engine(); - if (eng && eng->agent() == d->agent) { - eng->setAgent(0); - QScriptValue global = eng->globalObject(); - if (global.property(QString::fromLatin1("print")).strictlyEquals(traceFunction())) - global.setProperty(QString::fromLatin1("print"), QScriptValue()); -// global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); - if (global.property(QString::fromLatin1("__FILE__")).strictlyEquals(fileNameFunction())) - global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue()); - if (global.property(QString::fromLatin1("__LINE__")).strictlyEquals(lineNumberFunction())) - global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue()); - d->agent->nullifyBackendPointer(); - d->agent = 0; // agent is owned by engine + if (d->agent) { + QScriptEngine *eng = d->agent->engine(); + if (eng && eng->agent() == d->agent) { + eng->setAgent(0); + QScriptValue global = eng->globalObject(); + global.setProperty(QString::fromLatin1("print"), d->origTraceFunction); + d->origTraceFunction = QScriptValue(); +// global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); + global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue(), + QScriptValue::PropertyGetter); + global.setProperty(QString::fromLatin1("__FILE__"), d->origFileNameFunction); + d->origFileNameFunction = QScriptValue(); + global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue(), + QScriptValue::PropertyGetter); + global.setProperty(QString::fromLatin1("__LINE__"), d->origLineNumberFunction); + d->origLineNumberFunction = QScriptValue(); + d->agent->nullifyBackendPointer(); + d->agent = 0; // agent is owned by engine + } } d->pendingEvaluateLineNumber = -1; diff --git a/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h b/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h index de18304..a356762 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h +++ b/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h @@ -57,6 +57,7 @@ #include <QtCore/qhash.h> #include <QtCore/qlist.h> +#include <QtScript/qscriptvalue.h> #include "qscriptdebuggerbackend_p.h" @@ -66,7 +67,6 @@ class QEvent; class QString; class QScriptContext; class QScriptEngine; -class QScriptValue; class QScriptValueIterator; class QScriptObjectSnapshot; class QScriptDebuggerAgent; @@ -126,6 +126,10 @@ public: QObject *eventReceiver; QScriptDebuggerBackend *q_ptr; + + QScriptValue origTraceFunction; + QScriptValue origFileNameFunction; + QScriptValue origLineNumberFunction; }; QT_END_NAMESPACE diff --git a/src/scripttools/debugging/qscriptenginedebugger.cpp b/src/scripttools/debugging/qscriptenginedebugger.cpp index 948a01a..f2245cc 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.cpp +++ b/src/scripttools/debugging/qscriptenginedebugger.cpp @@ -126,7 +126,7 @@ public: mode in which it accepts input from the user. The evaluationResumed() signal is emitted when script evaluation is resumed, i.e, when execution control is given back to the script - engine. + engine. The state() function returns the debugger's current state. When calling QScriptEngine::evaluate() it is useful to pass a descriptive script name (file name) as second argument, as this is @@ -226,6 +226,16 @@ public: \value GoToLineAction Shows the "Go to Line" dialog. */ +/*! + \enum QScriptEngineDebugger::DebuggerState + \since 4.6 + + This enum specifies the current state of the debugger. + + \value RunningState The debugger is running. (Script evaluation is allowed.) + \value SuspendedState The debugger has suspended script evaluation. +*/ + class QScriptEngineDebuggerPrivate : public QObjectPrivate { @@ -387,6 +397,20 @@ void QScriptEngineDebugger::detach() } /*! + \since 4.6 + + Returns the current state of the debugger. + + \sa evaluationResumed() + \sa evaluationSuspended() +*/ +QScriptEngineDebugger::DebuggerState QScriptEngineDebugger::state() const +{ + Q_D(const QScriptEngineDebugger); + return !d->debugger || !d->debugger->isInteractive() ? SuspendedState : RunningState; +} + +/*! Returns a pointer to the instance of the specified standard \a widget. The widgets available are defined by the DebuggerWidget diff --git a/src/scripttools/debugging/qscriptenginedebugger.h b/src/scripttools/debugging/qscriptenginedebugger.h index 0fd4963..b9061a2 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.h +++ b/src/scripttools/debugging/qscriptenginedebugger.h @@ -92,6 +92,11 @@ public: GoToLineAction }; + enum DebuggerState { + RunningState, + SuspendedState + }; + QScriptEngineDebugger(QObject *parent = 0); ~QScriptEngineDebugger(); @@ -108,6 +113,8 @@ public: QWidget *widget(DebuggerWidget widget) const; QAction *action(DebuggerAction action) const; + DebuggerState state() const; + Q_SIGNALS: void evaluationSuspended(); void evaluationResumed(); |