From b1d187399b79b980bc49cb9f78320466da54f977 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 16 Apr 2010 06:42:09 +0200 Subject: Don't resolve geometry shaders every time... This was a huge extra cost in all QPainter::begin's on GL target surfaces Reviewed-by: Rhys Weatherley --- src/opengl/qglextensions.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index ef3c4cd..8e2bbd4 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -235,11 +235,6 @@ bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx) bool qt_resolve_glsl_extensions(QGLContext *ctx) { - // Geometry shaders are optional... - glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT")); - glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT")); - glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT")); - glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT")); #if defined(QT_OPENGL_ES_2) // The GLSL shader functions are always present in OpenGL/ES 2.0. @@ -254,6 +249,12 @@ bool qt_resolve_glsl_extensions(QGLContext *ctx) if (glCreateShader) return true; + // Geometry shaders are optional... + glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT")); + glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT")); + glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT")); + glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT")); + glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader")); if (glCreateShader) { glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource")); -- cgit v0.12 From edc6e0218b5fad73476f1f18529b5ec48a3e100f Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 19 Apr 2010 07:25:15 +0200 Subject: Swapped x and y values in qt_painterpath_check_crossing Reviewed-by: Kim --- src/gui/painting/qpainterpath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index f78de34..965b84c 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1914,7 +1914,7 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF case QPainterPath::MoveToElement: if (i > 0 - && qFuzzyCompare(last_pt.x(), last_start.y()) + && qFuzzyCompare(last_pt.x(), last_start.x()) && qFuzzyCompare(last_pt.y(), last_start.y()) && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(), last_start.x(), last_start.y(), rect)) -- cgit v0.12 From c799eeffc43a186747f06a7d36a747cce59925dd Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 19 Apr 2010 07:26:44 +0200 Subject: Don't crash when calling drawPixmapFragements with a null pixmap --- src/gui/painting/qpaintengineex.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 9366513..a78cafb 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -974,6 +974,9 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/) { + if (pixmap.isNull()) + return; + qreal oldOpacity = state()->opacity; QTransform oldTransform = state()->matrix; -- cgit v0.12 From 8fffbc7768be28fb2b31727bf79b2e2357ce9814 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 19 Apr 2010 10:17:30 +0200 Subject: Use QGLContextPrivate to track attribarray enabled state. Reviewed-by: Trond Reviewed-by: Tom --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index c89d34f..955a129 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -573,9 +573,9 @@ void QGL2PaintEngineExPrivate::resetGLState() glStencilMask(0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_ALWAYS, 0, 0xff); - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glDisableVertexAttribArray(QT_OPACITY_ATTR); + ctx->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false); + ctx->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false); + ctx->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); #ifndef QT_OPENGL_ES_2 glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib() #endif -- cgit v0.12 From 5ce428cf7f20cd37f4cf0d92ddcceddd07c5a0db Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 16 Apr 2010 18:20:37 +0200 Subject: QX11GL: Fix bug with pixmaps drawn on multiple top-levels Reviewed-By: TrustMe --- src/opengl/qpixmapdata_x11gl_egl.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index 3ab385a..4d726b6 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -66,7 +66,8 @@ QT_BEGIN_NAMESPACE // different contexts: Q_GLOBAL_STATIC(QEglContext, qt_x11gl_rgbContext); -Q_GLOBAL_STATIC(QEglContext, qt_x11gl_argbContext) +Q_GLOBAL_STATIC(QEglContext, qt_x11gl_argbContext); +Q_GLOBAL_STATIC_WITH_ARGS(QGLContext, qt_x11gl_fake_shared_context, (QX11GLPixmapData::glFormat())); QEglContext* QX11GLPixmapData::rgbContext = 0; QEglContext* QX11GLPixmapData::argbContext = 0; @@ -112,7 +113,13 @@ bool QX11GLPixmapData::hasX11GLPixmaps() if (!argbContext) { argbContext = qt_x11gl_argbContext(); argbContext->setConfig(argbConfig); - argbContext->createContext(); + bool success = argbContext->createContext(rgbContext); + if (!success) { + qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared"); + success = argbContext->createContext(); + if (!success) + argbContext = rgbContext; // Might work, worth a shot at least. + } } if (!argbContext->isValid()) @@ -258,6 +265,14 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const ctx = new QGLContext(glFormat()); Q_ASSERT(ctx->d_func()->eglContext == 0); ctx->d_func()->eglContext = hasAlphaChannel() ? argbContext : rgbContext; + + // While we use a seperate QGLContext for each pixmap, the underlying QEglContext is + // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking + // each pixmap's QGLContext is sharing with this central one. The only place this is + // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing. + ctx->d_func()->sharing = true; + QGLContextGroup::addShare(ctx, qt_x11gl_fake_shared_context()); + // Update the glFormat for the QGLContext: qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config()); } -- cgit v0.12 From bce9c47d5437812b137c47ff3c602ff23ffa5e22 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 19 Apr 2010 10:27:29 +0200 Subject: Mac: Fix off-by-one in vertical position for elided and non-elided text In the code path that draws the elided text, we would truncate the position before passing it to the painter. With a font engine that supports fractional values (mac), this would potentially give us the wrong position compared to the code path that draws the complete text, which essentially rounds off the number. The result was that when you resized the width an item view to make its items elide the text, then they would potentially shift up or down by one pixel. Task-number: QTBUG-9879 Reviewed-by: Gunnar --- src/gui/styles/qcommonstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index b0e2d37..8036728 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -981,7 +981,7 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt qreal y = position.y() + line.y() + line.ascent(); p->save(); p->setFont(option->font); - p->drawText(int(x), int(y), elidedText); + p->drawText(QPointF(x, y), elidedText); p->restore(); break; } -- cgit v0.12 From 1e83011e2ac4a33b39d12807b71cd3bb3511a263 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 19 Apr 2010 10:57:08 +0200 Subject: Odf export: Remove double namespace in tab-stops and fix table padding According to the specification, the correct name of the tab-stops element is style:tab-stops (and similar with style:tab-stop). The style namespace seems to have been added twice by mistake in QTextOdfWriter. Also: Fix a copy-paste bug when outputting left, right and bottom padding for table cells. Reviewed-by: Thomas Zander --- src/gui/text/qtextodfwriter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index d369bff0..7992de5 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -493,10 +493,10 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format.nonBreakableLines() ? QString::fromLatin1("true") : QString::fromLatin1("false")); if (format.hasProperty(QTextFormat::TabPositions)) { QList tabs = format.tabPositions(); - writer.writeStartElement(styleNS, QString::fromLatin1("style-tab-stops")); + writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops")); QList::Iterator iterator = tabs.begin(); while(iterator != tabs.end()) { - writer.writeEmptyElement(styleNS, QString::fromLatin1("style-tab-stop")); + writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop")); writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) ); QString type; switch(iterator->type) { @@ -511,7 +511,7 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat ++iterator; } - writer.writeEndElement(); // style-tab-stops + writer.writeEndElement(); // tab-stops } writer.writeEndElement(); // paragraph-properties @@ -698,11 +698,11 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe if (padding > 0) writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding)); if (format.bottomPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.bottomPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding())); if (format.leftPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.leftPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding())); if (format.rightPadding() > 0) - writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.rightPadding())); + writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding())); } if (format.hasProperty(QTextFormat::TextVerticalAlignment)) { -- cgit v0.12 From d935191592bfe275b6122841de8fa76778be02af Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 19 Apr 2010 12:52:18 +0100 Subject: Add a test to QListView to check initialisation of style option index, similar to QTreeView test. Reviewed-by: Olivier Goffart Merge-request: 565 --- tests/auto/qlistview/tst_qlistview.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/auto/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp index f5c32cd..330f803 100644 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ b/tests/auto/qlistview/tst_qlistview.cpp @@ -124,6 +124,7 @@ private slots: void taskQTBUG_2678_spacingAndWrappedText(); void taskQTBUG_5877_skippingItemInPageDownUp(); void taskQTBUG_9455_wrongScrollbarRanges(); + void styleOptionViewItem(); }; // Testing get/set functions @@ -1971,5 +1972,35 @@ void tst_QListView::taskQTBUG_9455_wrongScrollbarRanges() QCOMPARE(w.verticalScrollBar()->maximum(), w.contentsSize().height() - w.viewport()->geometry().height()); } +void tst_QListView::styleOptionViewItem() +{ + class MyDelegate : public QStyledItemDelegate + { + public: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + { + QVERIFY(qstyleoption_cast(&option)); + QStyleOptionViewItemV4 opt(option); + initStyleOption(&opt, index); + + QCOMPARE(opt.index, index); + + QStyledItemDelegate::paint(painter, option, index); + } + }; + + QListView view; + QStandardItemModel model; + view.setModel(&model); + MyDelegate delegate; + view.setItemDelegate(&delegate); + model.appendRow(QList() + << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); + + // Run test + view.showMaximized(); + QApplication::processEvents(); +} + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" -- cgit v0.12 From d97c42b7fdb4b370ec5a09ef5d6f04e2e22f241d Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Mon, 19 Apr 2010 16:26:42 +0200 Subject: Fixed a crash when declaring an animation with Q_GLOBAL_STATIC Reviewed-By: gabi Task-Number: QTBUG-10017 --- src/corelib/animation/qabstractanimation.cpp | 77 ++++++++++++++++++---------- src/corelib/animation/qabstractanimation_p.h | 11 ++-- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 82b3003..01570ad 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -173,11 +173,12 @@ QUnifiedTimer::QUnifiedTimer() : time.invalidate(); } -QUnifiedTimer *QUnifiedTimer::instance() + +QUnifiedTimer *QUnifiedTimer::instance(bool create) { QUnifiedTimer *inst; #ifndef QT_NO_THREAD - if (!unifiedTimer()->hasLocalData()) { + if (create && !unifiedTimer()->hasLocalData()) { inst = new QUnifiedTimer; unifiedTimer()->setLocalData(inst); } else { @@ -190,10 +191,16 @@ QUnifiedTimer *QUnifiedTimer::instance() return inst; } +QUnifiedTimer *QUnifiedTimer::instance() +{ + return instance(true); +} + void QUnifiedTimer::ensureTimerUpdate() { - if (isPauseTimerActive) - updateAnimationsTime(); + QUnifiedTimer *inst = QUnifiedTimer::instance(false); + if (inst && inst->isPauseTimerActive) + inst->updateAnimationsTime(); } void QUnifiedTimer::updateAnimationsTime() @@ -219,6 +226,13 @@ void QUnifiedTimer::updateAnimationsTime() } } +void QUnifiedTimer::updateAnimationTimer() +{ + QUnifiedTimer *inst = QUnifiedTimer::instance(false); + if (inst) + inst->restartAnimationTimer(); +} + void QUnifiedTimer::restartAnimationTimer() { if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) { @@ -269,34 +283,41 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopLevel) { - registerRunningAnimation(animation); + QUnifiedTimer *inst = instance(true); //we create the instance if needed + inst->registerRunningAnimation(animation); if (isTopLevel) { Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer); QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true; - animationsToStart << animation; - if (!startStopAnimationTimer.isActive()) - startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); + inst->animationsToStart << animation; + if (!inst->startStopAnimationTimer.isActive()) + inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst); } } void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) { - unregisterRunningAnimation(animation); + QUnifiedTimer *inst = QUnifiedTimer::instance(false); + if (inst) { + //at this point the unified timer should have been created + //but it might also have been already destroyed in case the application is shutting down - if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer) - return; + inst->unregisterRunningAnimation(animation); - int idx = animations.indexOf(animation); - if (idx != -1) { - animations.removeAt(idx); - // this is needed if we unregister an animation while its running - if (idx <= currentAnimationIdx) - --currentAnimationIdx; + if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer) + return; - if (animations.isEmpty() && !startStopAnimationTimer.isActive()) - startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); - } else { - animationsToStart.removeOne(animation); + int idx = inst->animations.indexOf(animation); + if (idx != -1) { + inst->animations.removeAt(idx); + // this is needed if we unregister an animation while its running + if (idx <= inst->currentAnimationIdx) + --inst->currentAnimationIdx; + + if (inst->animations.isEmpty() && !inst->startStopAnimationTimer.isActive()) + inst->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, inst); + } else { + inst->animationsToStart.removeOne(animation); + } } QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false; } @@ -371,11 +392,11 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped; if (oldState == QAbstractAnimation::Running) { if (newState == QAbstractAnimation::Paused && hasRegisteredTimer) - QUnifiedTimer::instance()->ensureTimerUpdate(); + QUnifiedTimer::ensureTimerUpdate(); //the animation, is not running any more - QUnifiedTimer::instance()->unregisterAnimation(q); + QUnifiedTimer::unregisterAnimation(q); } else if (newState == QAbstractAnimation::Running) { - QUnifiedTimer::instance()->registerAnimation(q, isTopLevel); + QUnifiedTimer::registerAnimation(q, isTopLevel); } q->updateState(newState, oldState); @@ -397,7 +418,7 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) if (oldState == QAbstractAnimation::Stopped) { if (isTopLevel) { // currentTime needs to be updated if pauseTimer is active - QUnifiedTimer::instance()->ensureTimerUpdate(); + QUnifiedTimer::ensureTimerUpdate(); q->setCurrentTime(totalCurrentTime); } } @@ -456,7 +477,7 @@ QAbstractAnimation::~QAbstractAnimation() d->state = Stopped; emit stateChanged(oldState, d->state); if (oldState == QAbstractAnimation::Running) - QUnifiedTimer::instance()->unregisterAnimation(this); + QUnifiedTimer::unregisterAnimation(this); } } @@ -555,14 +576,14 @@ void QAbstractAnimation::setDirection(Direction direction) // the commands order below is important: first we need to setCurrentTime with the old direction, // then update the direction on this and all children and finally restart the pauseTimer if needed if (d->hasRegisteredTimer) - QUnifiedTimer::instance()->ensureTimerUpdate(); + QUnifiedTimer::ensureTimerUpdate(); d->direction = direction; updateDirection(direction); if (d->hasRegisteredTimer) // needed to update the timer interval in case of a pause animation - QUnifiedTimer::instance()->restartAnimationTimer(); + QUnifiedTimer::updateAnimationTimer(); emit directionChanged(direction); } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 2282cdb..fcfe824 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -124,9 +124,10 @@ private: public: //XXX this is needed by dui static Q_CORE_EXPORT QUnifiedTimer *instance(); + static QUnifiedTimer *instance(bool create); - void registerAnimation(QAbstractAnimation *animation, bool isTopLevel); - void unregisterAnimation(QAbstractAnimation *animation); + static void registerAnimation(QAbstractAnimation *animation, bool isTopLevel); + static void unregisterAnimation(QAbstractAnimation *animation); //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL void setTimingInterval(int interval) @@ -151,13 +152,13 @@ public: this is used for updating the currentTime of all animations in case the pause timer is active or, otherwise, only of the animation passed as parameter. */ - void ensureTimerUpdate(); + static void ensureTimerUpdate(); /* this will evaluate the need of restarting the pause timer in case there is still some pause animations running. */ - void restartAnimationTimer(); + static void updateAnimationTimer(); protected: void timerEvent(QTimerEvent *); @@ -187,6 +188,8 @@ private: void registerRunningAnimation(QAbstractAnimation *animation); void unregisterRunningAnimation(QAbstractAnimation *animation); + void restartAnimationTimer(); + void updateAnimationsTime(); int closestPauseAnimationTimeToFinish(); }; -- cgit v0.12 From d738414926bc575a37c6ae6c6cca68d01439b2ef Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 20 Apr 2010 09:49:39 +0200 Subject: Fixed pixel-bleeding when stretching subrected pixmaps. When stretching a subrect of a pixmap we need to clamp the sampling to the subrect. This was done for the ARGB32_Premultiplied target format but not for the generic fallback. This patch adapts the code so that the two code paths are equivalent. Reviewed-by: Samuel --- src/gui/painting/qdrawhelper.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index b440fce..bfa1136 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -674,6 +674,11 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int image_width = data->texture.width; int image_height = data->texture.height; + int image_x1 = data->texture.x1; + int image_y1 = data->texture.y1; + int image_x2 = data->texture.x2; + int image_y2 = data->texture.y2; + const qreal cx = x + 0.5; const qreal cy = y + 0.5; @@ -708,17 +713,17 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * y2 = y1 + 1; y2 %= image_height; } else { - if (x1 < 0) { - x2 = x1 = 0; - } else if (x1 >= image_width - 1) { - x2 = x1 = image_width - 1; + if (x1 < image_x1) { + x2 = x1 = image_x1; + } else if (x1 >= image_x2 - 1) { + x2 = x1 = image_x2 - 1; } else { x2 = x1 + 1; } - if (y1 < 0) { - y2 = y1 = 0; - } else if (y1 >= image_height - 1) { - y2 = y1 = image_height - 1; + if (y1 < image_y1) { + y2 = y1 = image_y1; + } else if (y1 >= image_y2 - 1) { + y2 = y1 = image_y2 - 1; } else { y2 = y1 + 1; } -- cgit v0.12 From 67ffe10585bc683cd160cef95fef55e8301a6ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 19 Apr 2010 12:31:21 +0200 Subject: Fixed image drawing inconsistencies when drawing 1x1 images/subrects. We special cased 1x1 source rects by calling fillRect() with a solid color, but that produces slightly different rasterization leading to gaps when drawing 9-patch images for example. This patch makes us only use the optimized path for scaling transforms or simpler. Task-number: QTBUG-10018 Reviewed-by: Gunnar Sletta --- src/gui/painting/qpaintengine_raster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 8f14583..9148ac2 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2552,7 +2552,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe int sr_t = qFloor(sr.top()); int sr_b = qCeil(sr.bottom()) - 1; - if (!s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { + if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { // as fillRect will apply the aliased coordinate delta we need to // subtract it here as we don't use it for image drawing QTransform old = s->matrix; -- cgit v0.12 From 434d2312b63090cfd2ba7e0f3728b5b225bcaeec Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 19 Apr 2010 19:13:20 +0200 Subject: QDialog: user-moved dialog would not show on the same place after hide The Qt::WA_Moved was not being set during the move event as notified by the window manager. This is a behavior change for 4.7, but we think it's more user friendly than the previous behavior. Reviewed-by: mbm Task-number: QTBUG-9991 --- src/gui/dialogs/qdialog.cpp | 14 ++++++++------ src/gui/dialogs/qdialog.h | 2 -- src/gui/kernel/qwidget.cpp | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index a6bd78a..e4f45ba 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -393,7 +393,6 @@ void QDialogPrivate::resetModalitySetByOpen() resetModalityTo = -1; } -#if defined(Q_WS_WINCE) || defined(Q_WS_S60) #ifdef Q_WS_WINCE_WM void QDialogPrivate::_q_doneAction() { @@ -408,12 +407,12 @@ void QDialogPrivate::_q_doneAction() bool QDialog::event(QEvent *e) { bool result = QWidget::event(e); -#ifdef Q_WS_WINCE +#if defined(Q_WS_WINCE) if (e->type() == QEvent::OkRequest) { accept(); result = true; - } -#else + } else +#elif defined(Q_WS_S60) if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Resize )) { if (!testAttribute(Qt::WA_Moved)) { Qt::WindowStates state = windowState(); @@ -422,11 +421,14 @@ bool QDialog::event(QEvent *e) if (state != windowState()) setWindowState(state); } - } + } else #endif + if (e->type() == QEvent::Move) { + setAttribute(Qt::WA_Moved, true); // as explicit as the user wants it to be + } + return result; } -#endif /*! Returns the modal dialog's result code, \c Accepted or \c Rejected. diff --git a/src/gui/dialogs/qdialog.h b/src/gui/dialogs/qdialog.h index 777256a..7ab0cb6 100644 --- a/src/gui/dialogs/qdialog.h +++ b/src/gui/dialogs/qdialog.h @@ -107,9 +107,7 @@ public Q_SLOTS: protected: QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0); -#if defined(Q_WS_WINCE) || defined(Q_WS_S60) bool event(QEvent *e); -#endif void keyPressEvent(QKeyEvent *); void closeEvent(QCloseEvent *); void showEvent(QShowEvent *); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 10fa4b9..046bc7f 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -7307,9 +7307,9 @@ void QWidgetPrivate::show_helper() setVisible(false). - \note If you are working with QDialog or its subclasses and you invoke - the show() function after this function, the dialog will be displayed in - its original position. + \note Since Qt 4.7, when calling hide() and then show() on QDialog + derived widgets will show on the previous (as in "Where the user moved it to") + position. \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close() */ -- cgit v0.12 From a057a48cbac8acbf54a121c63a795480d3f9a8c0 Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Tue, 20 Apr 2010 13:49:14 +0200 Subject: Added QIcon::name() This only works with icons loaded with QIcon::fromTheme() for now. Merge-request: 2367 Reviewed-by: Olivier Goffart Reviewed-by: jbache --- src/gui/image/qicon.cpp | 19 +++++++++++++++++++ src/gui/image/qicon.h | 2 ++ src/gui/image/qiconengine.cpp | 20 ++++++++++++++++++++ src/gui/image/qiconengine.h | 5 ++++- src/gui/image/qiconloader.cpp | 6 ++++++ tests/auto/qicon/tst_qicon.cpp | 23 +++++++++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index fad51f4..bc52e99 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -879,6 +879,25 @@ QList QIcon::availableSizes(Mode mode, State state) const } /*! + \since 4.7 + + Returns the name used to create the icon, if available. + + Depending on the way the icon was created, it may have an associated + name. This is the case for icons created with fromTheme() or icons + using a QIconEngine which supports the QIconEngineV2::IconNameHook. + + \sa fromTheme(), QIconEngine +*/ +QString QIcon::name() const +{ + if (!d || !d->engine || d->engine_version < 2) + return QString(); + QIconEngineV2 *engine = static_cast(d->engine); + return engine->iconName(); +} + +/*! \since 4.6 Sets the search paths for icon themes to \a paths. diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 2812703..faef07b 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -81,6 +81,8 @@ public: QSize actualSize(const QSize &size, Mode mode = Normal, State state = Off) const; + QString name() const; + void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const; inline void paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const { paint(painter, QRect(x, y, w, h), alignment, mode, state); } diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index 4c7c728..050d48d 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -183,6 +183,10 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI that should be filled with icon sizes. Engines that work in terms of a scalable, vectorial format normally return an empty list. + \value IconNameHook Allows to query the name used to create the + icon, for example when instantiating an icon using + QIcon::fromTheme(). + \sa virtual_hook() */ @@ -301,4 +305,20 @@ QList QIconEngineV2::availableSizes(QIcon::Mode mode, QIcon::State state) return arg.sizes; } +/*! + \since 4.7 + + Returns the name used to create the engine, if available. + + \note This is a helper method and the actual work is done by + virtual_hook() method, hence this method depends on icon engine support + and may not work with all icon engines. + */ +QString QIconEngineV2::iconName() +{ + QString name; + virtual_hook(QIconEngineV2::IconNameHook, reinterpret_cast(&name)); + return name; +} + QT_END_NAMESPACE diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 1f9266b..6d8b6ad 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -80,7 +80,7 @@ public: virtual void virtual_hook(int id, void *data); public: - enum IconEngineHook { AvailableSizesHook = 1 }; + enum IconEngineHook { AvailableSizesHook = 1, IconNameHook }; struct AvailableSizesArgument { @@ -92,6 +92,9 @@ public: // ### Qt 5: make this function const and virtual. QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off); + + // ### Qt 5: make this function const and virtual. + QString iconName(); }; QT_END_NAMESPACE diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 72ec2e8..a515ef8 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -554,6 +554,12 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) } } break; + case QIconEngineV2::IconNameHook: + { + QString &name = *reinterpret_cast(data); + name = m_iconName; + } + break; default: QIconEngineV2::virtual_hook(id, data); } diff --git a/tests/auto/qicon/tst_qicon.cpp b/tests/auto/qicon/tst_qicon.cpp index fae9cc0..e68664c 100644 --- a/tests/auto/qicon/tst_qicon.cpp +++ b/tests/auto/qicon/tst_qicon.cpp @@ -76,6 +76,7 @@ private slots: void svg(); void addFile(); void availableSizes(); + void name(); void streamAvailableSizes_data(); void streamAvailableSizes(); void fromTheme(); @@ -550,6 +551,28 @@ void tst_QIcon::availableSizes() } } +void tst_QIcon::name() +{ + { + // No name if icon does not come from a theme + QIcon icon(":/image.png"); + QString name = icon.name(); + QVERIFY(name.isEmpty()); + } + + { + // Getting the name of an icon coming from a theme should work + QString searchPath = QLatin1String(":/icons"); + QIcon::setThemeSearchPaths(QStringList() << searchPath); + QString themeName("testtheme"); + QIcon::setThemeName(themeName); + + QIcon icon = QIcon::fromTheme("appointment-new"); + QString name = icon.name(); + QCOMPARE(name, QLatin1String("appointment-new")); + } +} + void tst_QIcon::streamAvailableSizes_data() { QTest::addColumn("icon"); -- cgit v0.12 From 13732b74e07fe10e95f2601f6cf2d0be78467eaa Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Tue, 20 Apr 2010 15:24:13 +0200 Subject: Fixed assert failure when trying to load invalid SVG file. Task-number: QTBUG-10022 Reviewed-by: Trond --- src/svg/qsvghandler.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 038aeb4..b6e771f 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -3525,7 +3525,11 @@ void QSvgHandler::parse() // namespaceUri is empty. The only possible strategy at // this point is to do what everyone else seems to do and // ignore the reported namespaceUri completely. - startElement(xml->name().toString(), xml->attributes()); + if (!startElement(xml->name().toString(), xml->attributes())) { + delete m_doc; + m_doc = 0; + return; + } break; case QXmlStreamReader::EndElement: endElement(xml->name()); @@ -3570,6 +3574,9 @@ bool QSvgHandler::startElement(const QString &localName, m_whitespaceMode.push(QSvgText::Default); } + if (!m_doc && localName != QLatin1String("svg")) + return false; + if (FactoryMethod method = findGroupFactory(localName)) { //group node = method(m_doc ? m_nodes.top() : 0, attributes, this); -- cgit v0.12 From dab8d4c77795ed195f23e427945267e9e9a4df20 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 30 Mar 2010 18:01:06 +0200 Subject: Micro optimisations in QMutexLocker Reviewed-by: Thiago --- src/corelib/thread/qmutex.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 677412e..509f300 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -95,21 +95,23 @@ class Q_CORE_EXPORT QMutexLocker { public: inline explicit QMutexLocker(QMutex *m) - : val(reinterpret_cast(m)) { - Q_ASSERT_X((val & quintptr(1u)) == quintptr(0), + Q_ASSERT_X((reinterpret_cast(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); - relock(); + if (m) { + m->lock(); + val = reinterpret_cast(m) | quintptr(1u); + } else { + val = 0; + } } inline ~QMutexLocker() { unlock(); } inline void unlock() { - if (val) { - if ((val & quintptr(1u)) == quintptr(1u)) { - val &= ~quintptr(1u); - mutex()->unlock(); - } + if ((val & quintptr(1u)) == quintptr(1u)) { + val &= ~quintptr(1u); + mutex()->unlock(); } } -- cgit v0.12 From c90b3ec191430e8b6bf5526124919df0bd0cf518 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 30 Mar 2010 18:01:49 +0200 Subject: Benchmark emission of signal connected to nothing --- tests/benchmarks/corelib/kernel/qobject/main.cpp | 9 +++++++-- tests/benchmarks/corelib/kernel/qobject/object.cpp | 3 +++ tests/benchmarks/corelib/kernel/qobject/object.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/benchmarks/corelib/kernel/qobject/main.cpp b/tests/benchmarks/corelib/kernel/qobject/main.cpp index 7f24ebd..8d05fcd 100644 --- a/tests/benchmarks/corelib/kernel/qobject/main.cpp +++ b/tests/benchmarks/corelib/kernel/qobject/main.cpp @@ -69,6 +69,7 @@ void QObjectBenchmark::signal_slot_benchmark_data() QTest::newRow("simple function") << 0; QTest::newRow("single signal/slot") << 1; QTest::newRow("multi signal/slot") << 2; + QTest::newRow("unconnected signal") << 3; } void QObjectBenchmark::signal_slot_benchmark() @@ -110,9 +111,13 @@ void QObjectBenchmark::signal_slot_benchmark() QBENCHMARK { singleObject.emitSignal0(); } - } else { + } else if (type == 2) { QBENCHMARK { - multiObject.emitSignal0(); + multiObject.emitSignal0(); + } + } else if (type == 3) { + QBENCHMARK { + singleObject.emitSignal1(); } } } diff --git a/tests/benchmarks/corelib/kernel/qobject/object.cpp b/tests/benchmarks/corelib/kernel/qobject/object.cpp index d775a32..3920e97 100644 --- a/tests/benchmarks/corelib/kernel/qobject/object.cpp +++ b/tests/benchmarks/corelib/kernel/qobject/object.cpp @@ -42,6 +42,9 @@ void Object::emitSignal0() { emit signal0(); } +void Object::emitSignal1() +{ emit signal1(); } + void Object::slot0() { } diff --git a/tests/benchmarks/corelib/kernel/qobject/object.h b/tests/benchmarks/corelib/kernel/qobject/object.h index 7e4933f..8f8fbe9 100644 --- a/tests/benchmarks/corelib/kernel/qobject/object.h +++ b/tests/benchmarks/corelib/kernel/qobject/object.h @@ -48,6 +48,7 @@ class Object : public QObject Q_OBJECT public: void emitSignal0(); + void emitSignal1(); signals: void signal0(); void signal1(); -- cgit v0.12 From 7f207df8cc63762e32803505aaf6e9b320fd6ba5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 30 Mar 2010 18:03:24 +0200 Subject: Optimize QMetaObject::activate Mainly by inlining what should be inlined Reviewed-by: Thiago --- src/corelib/kernel/qobject.cpp | 27 +++------------------------ src/corelib/kernel/qobject_p.h | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c13d829..3a37cb1 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -101,7 +101,7 @@ static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0); /** \internal * mutex to be locked when accessing the connectionlists or the senders list */ -static QMutex *signalSlotLock(const QObject *o) +static inline QMutex *signalSlotLock(const QObject *o) { if (!signalSlotMutexes) { QMutexPool *mp = new QMutexPool; @@ -393,27 +393,6 @@ void QObjectPrivate::cleanConnectionLists() } } -QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -void QObjectPrivate::resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender) -{ - // ref is set to zero when this object is deleted during the metacall - if (currentSender->ref == 1) - receiver->d_func()->currentSender = previousSender; - // if we've recursed, we need to tell the caller about the objects deletion - if (previousSender) - previousSender->ref = currentSender->ref; -} - - typedef QMultiHash GuardHash; Q_GLOBAL_STATIC(GuardHash, guardHash) Q_GLOBAL_STATIC(QMutex, guardHashLock) @@ -3231,9 +3210,9 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign argv ? argv : empty_argv); } - QMutexLocker locker(signalSlotLock(sender)); QThreadData *currentThreadData = QThreadData::current(); + QMutexLocker locker(signalSlotLock(sender)); QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists; if (!connectionLists) { locker.unlock(); @@ -3329,7 +3308,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign if (connectionLists->orphaned) { if (!connectionLists->inUse) delete connectionLists; - } else { + } else if (connectionLists->dirty) { sender->d_func()->cleanConnectionLists(); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 341b3e9..4800e6a 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -156,9 +156,9 @@ public: void removePendingChildInsertedEvents(QObject *child); #endif - static Sender *setCurrentSender(QObject *receiver, + static inline Sender *setCurrentSender(QObject *receiver, Sender *sender); - static void resetCurrentSender(QObject *receiver, + static inline void resetCurrentSender(QObject *receiver, Sender *currentSender, Sender *previousSender); static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); @@ -215,9 +215,29 @@ public: inline bool QObjectPrivate::isSignalConnected(uint signal_index) const { return signal_index >= sizeof(connectedSignals) * 8 + || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) || qt_signal_spy_callback_set.signal_begin_callback - || qt_signal_spy_callback_set.signal_end_callback - || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))); + || qt_signal_spy_callback_set.signal_end_callback); +} + +inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, + Sender *sender) +{ + Sender *previousSender = receiver->d_func()->currentSender; + receiver->d_func()->currentSender = sender; + return previousSender; +} + +inline void QObjectPrivate::resetCurrentSender(QObject *receiver, + Sender *currentSender, + Sender *previousSender) +{ + // ref is set to zero when this object is deleted during the metacall + if (currentSender->ref == 1) + receiver->d_func()->currentSender = previousSender; + // if we've recursed, we need to tell the caller about the objects deletion + if (previousSender) + previousSender->ref = currentSender->ref; } -- cgit v0.12 From 495032429b400b44fdcc585585a5c7220c572c68 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Tue, 20 Apr 2010 13:30:17 +0200 Subject: Fixes keyboard shortcuts for QGraphicsTextItem. The event ShortcutOverride was not handled by QGraphicsTextItem. Autotest included. Task-number: QTBUG-7333 Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++ tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 38 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9759b39..20ea262 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10086,6 +10086,9 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event) #endif //QT_NO_IM } break; + case QEvent::ShortcutOverride: + dd->sendControlEvent(event); + return true; default: break; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 03ce45a..e2f7f18 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include "../../shared/util.h" @@ -426,6 +427,7 @@ private slots: void itemIsInFront(); void scenePosChange(); void updateMicroFocus(); + void textItem_shortcuts(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -10060,6 +10062,42 @@ void tst_QGraphicsItem::updateMicroFocus() QTRY_COMPARE(ic2.nbUpdates, 0); } +void tst_QGraphicsItem::textItem_shortcuts() +{ + QWidget w; + QVBoxLayout l; + w.setLayout(&l); + QGraphicsScene scene; + QGraphicsView view(&scene); + l.addWidget(&view); + QPushButton b("Push Me"); + l.addWidget(&b); + + QGraphicsTextItem *item = scene.addText("Troll Text"); + item->setFlag(QGraphicsItem::ItemIsFocusable); + item->setTextInteractionFlags(Qt::TextEditorInteraction); + w.show(); + QTest::qWaitForWindowShown(&w); + + item->setFocus(); + QTRY_VERIFY(item->hasFocus()); + QVERIFY(item->textCursor().selectedText().isEmpty()); + + // Shortcut should work (select all) + QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); + QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText()); + QTextCursor tc = item->textCursor(); + tc.clearSelection(); + item->setTextCursor(tc); + QVERIFY(item->textCursor().selectedText().isEmpty()); + + // Shortcut should also work if the text item has the focus and another widget + // has the same shortcut. + b.setShortcut(QKeySequence("CTRL+A")); + QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); + QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText()); +} + void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() { struct Item : public QGraphicsTextItem -- cgit v0.12 From 90bac7f779b642ef1db5363012a994784ad029c4 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 20 Apr 2010 17:41:06 +0200 Subject: Build fix for mingw This was preventing the activeQt tools to build Don't know exactly why though.... Task-number: 10003 Reviewed-by: Zeno Albisser --- src/src.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src.pro b/src/src.pro index c74b0ca..1c76d18 100644 --- a/src/src.pro +++ b/src/src.pro @@ -5,12 +5,12 @@ unset(SRC_SUBDIRS) win32:SRC_SUBDIRS += src_winmain symbian:SRC_SUBDIRS += src_s60main SRC_SUBDIRS += src_corelib src_xml src_network src_sql src_testlib -win32:SRC_SUBDIRS += src_activeqt !symbian:contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus !contains(QT_CONFIG, no-gui): SRC_SUBDIRS += src_gui !wince*:!symbian:!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support !wince*:!symbian-abld:!symbian-sbsv2:include(tools/tools.pro) +win32:SRC_SUBDIRS += src_activeqt contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg -- cgit v0.12 From a087cfe4049292b726a5fea34f552ad86b44c2ae Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 20 Apr 2010 18:04:22 +0200 Subject: Document that QFileSystemWatcher needs to be destroyed before ~QCoreApp Fixes: QT-3305 Rev-By: Denis --- src/corelib/io/qfilesystemwatcher.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 00af3fd..18c3c9f 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -426,6 +426,11 @@ QFileSystemWatcher::QFileSystemWatcher(const QStringList &paths, QObject *parent /*! Destroys the file system watcher. + + \note To avoid deadlocks on shutdown, all instances of QFileSystemWatcher + need to be destroyed before QCoreApplication. Note that passing + QCoreApplication::instance() as the parent object when creating + QFileSystemWatcher is not sufficient. */ QFileSystemWatcher::~QFileSystemWatcher() { -- cgit v0.12 From 48b2025663c93003cd00b807bb74d220c933b78b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 20 Apr 2010 18:17:38 +0200 Subject: Optimize ~QObject By avoiding to lock mutextes when not needed. According to experiment, many object are destroyed without any connection attached to them. (80% with qml, 50% with creator) d->currentSender does not need to be protected by the mutex since we are in the destructor. We do not need Q_TRY since the mutex is grenteed to exist if there is connections. We do not need to call QCoreApplication::removePostedEvents if there is not events to process. And d->postedEvents can be checked outside of the lock since it cannot be incremented anymore in the destructor Reviewed-by: Roberto Raggi Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3a37cb1..6a6db51 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -859,19 +859,14 @@ QObject::~QObject() if (d->declarativeData) QAbstractDeclarativeData::destroyed(d->declarativeData, this); - { - QMutex *signalSlotMutex = 0; - QT_TRY { - signalSlotMutex = signalSlotLock(this); - } QT_CATCH(const std::bad_alloc &) { - // out of memory - swallow to prevent a crash - } - QMutexLocker locker(signalSlotMutex); + // set ref to zero to indicate that this object has been deleted + if (d->currentSender != 0) + d->currentSender->ref = 0; + d->currentSender = 0; - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; + if (d->connectionLists || d->senders) { + QMutex *signalSlotMutex = signalSlotLock(this); + QMutexLocker locker(signalSlotMutex); // disconnect all receivers if (d->connectionLists) { @@ -889,7 +884,7 @@ QObject::~QObject() } QMutex *m = signalSlotLock(c->receiver); - bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); if (c->receiver) { *c->prev = c->next; @@ -917,7 +912,7 @@ QObject::~QObject() QObject *sender = node->sender; QMutex *m = signalSlotLock(sender); node->prev = &node; - bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { m->unlock(); @@ -951,7 +946,8 @@ QObject::~QObject() qt_removeObject(this); - QCoreApplication::removePostedEvents(this); + if (d->postedEvents) + QCoreApplication::removePostedEvents(this, 0); if (d->parent) // remove it from parent object d->setParent_helper(0); -- cgit v0.12 From ad0c6b17cde4a3ce0041d1a54b96ccb5a6792520 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 21 Apr 2010 13:24:27 +0200 Subject: Fixes wrong QGraphicsView's viewport cursor reset. The cursor was reset even when it had not been previously saved. Autotest included. Task-number: QTBUG-7438 Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsview.cpp | 12 ++++++----- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 28 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a767987..114de85 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -733,11 +733,13 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor() } // Restore the original viewport cursor. - hasStoredOriginalCursor = false; - if (dragMode == QGraphicsView::ScrollHandDrag) - viewport->setCursor(Qt::OpenHandCursor); - else - viewport->setCursor(originalCursor); + if (hasStoredOriginalCursor) { + hasStoredOriginalCursor = false; + if (dragMode == QGraphicsView::ScrollHandDrag) + viewport->setCursor(Qt::OpenHandCursor); + else + viewport->setCursor(originalCursor); + } } #endif diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 1c19fab..5e889f4 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -239,6 +239,7 @@ private slots: void QTBUG_4151_clipAndIgnore_data(); void QTBUG_4151_clipAndIgnore(); void QTBUG_5859_exposedRect(); + void QTBUG_7438_cursor(); }; void tst_QGraphicsView::initTestCase() @@ -4063,5 +4064,32 @@ void tst_QGraphicsView::QTBUG_5859_exposedRect() QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect); } +void tst_QGraphicsView::QTBUG_7438_cursor() +{ +#ifndef QT_NO_CURSOR +#if defined(Q_OS_WINCE) + QSKIP("Qt/CE does not have regular cursor support", SkipAll); +#endif + QGraphicsScene scene; + QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20)); + item->setFlag(QGraphicsItem::ItemIsMovable); + + QGraphicsView view(&scene); + view.setFixedSize(400, 400); + view.show(); + QTest::qWaitForWindowShown(&view); + + QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape()); + view.viewport()->setCursor(Qt::PointingHandCursor); + QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor); + sendMouseMove(view.viewport(), view.mapFromScene(0, 0)); + QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor); + sendMousePress(view.viewport(), view.mapFromScene(0, 0)); + QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor); + sendMouseRelease(view.viewport(), view.mapFromScene(0, 0)); + QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor); +#endif +} + QTEST_MAIN(tst_QGraphicsView) #include "tst_qgraphicsview.moc" -- cgit v0.12