From b888c9cca5ba2994344533c7602d22e1bc8e5db3 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 21 Mar 2011 16:27:45 +1000 Subject: Text bounding rect calculated incorrectly if non-top aligned. QRect::setY() affects the size of the rectangle, so the height of the bounding rect was too small. Use moveTop() instead, which does not affect the size of the rectangle. Change-Id: If41ba6a28c9a7370f054dab20995a198f822ae2b Task-number: QTBUG-18194 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativetext.cpp | 4 ++-- .../qdeclarativetext/tst_qdeclarativetext.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index fdc1a71..720692c 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -1416,10 +1416,10 @@ QRectF QDeclarativeText::boundingRect() const case AlignTop: break; case AlignBottom: - rect.setY(h - rect.height()); + rect.moveTop(h - rect.height()); break; case AlignVCenter: - rect.setY((h - rect.height()) / 2); + rect.moveTop((h - rect.height()) / 2); break; } diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 581b58c..ca6e87a 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -658,6 +658,24 @@ void tst_qdeclarativetext::verticalAlignment() } } + //confirm that bounding rect is correctly positioned. + QString componentStr = "import QtQuick 1.0\nText { height: 80; text: \"Hello\" }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeText *textObject = qobject_cast(textComponent.create()); + QVERIFY(textObject != 0); + QRectF br = textObject->boundingRect(); + QVERIFY(br.y() == 0); + + textObject->setVAlign(QDeclarativeText::AlignVCenter); + br = textObject->boundingRect(); + QCOMPARE(qFloor(br.y()), qFloor((80.0 - br.height())/2)); + + textObject->setVAlign(QDeclarativeText::AlignBottom); + br = textObject->boundingRect(); + QCOMPARE(qFloor(br.y()), qFloor(80.0 - br.height())); + + delete textObject; } void tst_qdeclarativetext::font() -- cgit v0.12 From de4bd221124e0a133858839b4b824165a9eb7dff Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 22 Mar 2011 10:16:54 +0100 Subject: Remove useless profile reference. The profile has been empty since the plugin functionality was moved into QtMultimedia itself (d73df73c556b0a225fdde7341549ed834bc691f4). RevBy: Miikka Heikkinen --- src/plugins/audio/audio.pro | 3 --- src/plugins/plugins.pro | 1 - 2 files changed, 4 deletions(-) delete mode 100644 src/plugins/audio/audio.pro diff --git a/src/plugins/audio/audio.pro b/src/plugins/audio/audio.pro deleted file mode 100644 index b7a775b..0000000 --- a/src/plugins/audio/audio.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = - diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index afa0901..e778ab7 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -13,5 +13,4 @@ embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers !symbian:!contains(QT_CONFIG, no-gui):SUBDIRS += accessible symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon -contains(QT_CONFIG, multimedia): SUBDIRS *= audio contains(QT_CONFIG, declarative): SUBDIRS *= qmltooling -- cgit v0.12 From 48c5a020c6ad6ee5ef1721d422f10bbc40dd1557 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Tue, 22 Mar 2011 11:03:13 +0200 Subject: Change Symbian to use destroyed swap behaviour in GL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Destroyed swap behaviour is a little bit faster than preserved swap with heavily animated UIs like QML. Task-number: QTBUG-18270 Reviewed-by: Samuel Rødal --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 4 --- src/opengl/opengl.pro | 2 +- src/opengl/qgl_symbian.cpp | 21 ++++++++---- src/opengl/qgltexturepool.cpp | 7 ++-- src/opengl/qwindowsurface_gl.cpp | 40 +++++++++++++++++----- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index c8786fb..5c8d2b6 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -90,10 +90,6 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_SYMBIAN) -#define QT_GL_NO_SCISSOR_TEST -#endif - #if defined(Q_WS_WIN) extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 6bbf99b..6d79584 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -148,7 +148,7 @@ embedded { } symbian { - DEFINES += QGL_USE_TEXTURE_POOL + DEFINES += QGL_USE_TEXTURE_POOL QGL_NO_PRESERVED_SWAP SOURCES -= qpixmapdata_gl.cpp SOURCES += qgl_symbian.cpp \ qpixmapdata_poolgl.cpp \ diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp index 78624a2..7caaabd 100644 --- a/src/opengl/qgl_symbian.cpp +++ b/src/opengl/qgl_symbian.cpp @@ -228,13 +228,20 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as d->eglSurface = QEgl::createSurface(device(), d->eglContext->config()); -#if !defined(QGL_NO_PRESERVED_SWAP) - eglGetError(); // Clear error state first. - eglSurfaceAttrib(QEgl::display(), d->eglSurface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - if (eglGetError() != EGL_SUCCESS) { - qWarning("QGLContext: could not enable preserved swap"); - } + eglGetError(); // Clear error state first. + +#ifdef QGL_NO_PRESERVED_SWAP + eglSurfaceAttrib(QEgl::display(), d->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); + + if (eglGetError() != EGL_SUCCESS) + qWarning("QGLContext: could not enable destroyed swap behaviour"); +#else + eglSurfaceAttrib(QEgl::display(), d->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + + if (eglGetError() != EGL_SUCCESS) + qWarning("QGLContext: could not enable preserved swap behaviour"); #endif setWindowCreated(true); diff --git a/src/opengl/qgltexturepool.cpp b/src/opengl/qgltexturepool.cpp index 61a88c3..a5472ec 100644 --- a/src/opengl/qgltexturepool.cpp +++ b/src/opengl/qgltexturepool.cpp @@ -135,8 +135,11 @@ void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture) if (data) removeFromLRU(data); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &texture); + QGLWidget *shareWidget = qt_gl_share_widget(); + if (shareWidget) { + QGLShareContextScope ctx(shareWidget->context()); + glDeleteTextures(1, &texture); + } } void QGLTexturePool::useTexture(QGLPixmapData *data) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 11a9eb0..ed541ce 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -371,6 +371,10 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window) d_ptr->q_ptr = this; d_ptr->geometry_updated = false; d_ptr->did_paint = false; + +#ifdef QGL_NO_PRESERVED_SWAP + setPartialUpdateSupport(false); +#endif } QGLWindowSurface::~QGLWindowSurface() @@ -467,8 +471,16 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) if (haveNOKSwapRegion) qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates."; } - bool swapBehaviourPreserved = (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) - || (ctx->d_func()->eglContext->configAttrib(EGL_SURFACE_TYPE)&EGL_SWAP_BEHAVIOR_PRESERVED_BIT)); + + bool swapBehaviourPreserved = ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR); + if (ctx->d_func()->eglContext->configAttrib(EGL_SURFACE_TYPE)&EGL_SWAP_BEHAVIOR_PRESERVED_BIT) { + EGLint swapBehavior; + if (eglQuerySurface(ctx->d_func()->eglContext->display(), ctx->d_func()->eglSurface + , EGL_SWAP_BEHAVIOR, &swapBehavior)) { + swapBehaviourPreserved = (swapBehavior == EGL_BUFFER_PRESERVED); + } + } + if (!swapBehaviourPreserved && !haveNOKSwapRegion) setPartialUpdateSupport(false); // Force full-screen updates else @@ -514,6 +526,8 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, void QGLWindowSurface::beginPaint(const QRegion &) { + updateGeometry(); + if (!context()) return; @@ -874,14 +888,22 @@ void QGLWindowSurface::updateGeometry() { ctx->d_func()->eglSurface = QEgl::createSurface(ctx->device(), ctx->d_func()->eglContext->config()); -#if !defined(QGL_NO_PRESERVED_SWAP) - eglGetError(); // Clear error state first. - eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurface, - EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); - if (eglGetError() != EGL_SUCCESS) { - qWarning("QGLWindowSurface: could not restore preserved swap behaviour"); + eglGetError(); // Clear error state. + if (hasPartialUpdateSupport()) { + eglSurfaceAttrib(ctx->d_func()->eglContext->display(), + ctx->d_func()->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + + if (eglGetError() != EGL_SUCCESS) + qWarning("QGLWindowSurface: could not enable preserved swap behaviour"); + } else { + eglSurfaceAttrib(ctx->d_func()->eglContext->display(), + ctx->d_func()->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); + + if (eglGetError() != EGL_SUCCESS) + qWarning("QGLWindowSurface: could not enable destroyed swap behaviour"); } -#endif } #endif -- cgit v0.12 From 933b7f7fe5344adeee7f6e9565897b606555d23f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 Mar 2011 12:15:03 +0200 Subject: Changed maximum heap size for qmlflickr on Symbian. 32 MB is certainly not enough to load large (e.g. 12 Mpix or bigger) images. Now it is changed to 128 MB. Reviewed-by: Jani Hautakangas --- demos/embedded/qmlflickr/qmlflickr.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demos/embedded/qmlflickr/qmlflickr.pro b/demos/embedded/qmlflickr/qmlflickr.pro index 39b316a..8d4e032 100644 --- a/demos/embedded/qmlflickr/qmlflickr.pro +++ b/demos/embedded/qmlflickr/qmlflickr.pro @@ -8,5 +8,6 @@ symbian { TARGET.UID3 = 0x$$qmlflickr_uid3 # defined in deployment.pri include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) TARGET.CAPABILITY = NetworkServices - TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 + # Maximum heap size set to 128 MB in order to allow loading large images. + TARGET.EPOCHEAPSIZE = 0x20000 0x8000000 } -- cgit v0.12 From 30dbb938701963c92fc911f59c72720741e556d1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 22 Mar 2011 13:24:21 +0200 Subject: Implement tiled image and pixmap drawing in VG paint engine. The vgWritePixel-based "fallback" in drawImage can only be used when the transformation is simple and no opacity is set. The tiled drawing introduced here will serve as an additional fallback for the more complex cases and will allow drawing large (12 Mpix or more) pixmaps and images with transformation and semi-transparency even when the complete image data would not fit into the GPU memory. Task-number: QTBUG-18251 Reviewed-by: Jani Hautakangas --- src/openvg/qpaintengine_vg.cpp | 101 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 44dceea..570adfd 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3071,6 +3071,95 @@ static void drawVGImage(QVGPaintEnginePrivate *d, vgDrawImage(vgImg); } +static void drawImageTiled(QVGPaintEnginePrivate *d, + const QRectF &r, + const QImage &image, + const QRectF &sr = QRectF()) +{ + const int minTileSize = 16; + int tileWidth = 512; + int tileHeight = tileWidth; + + VGImageFormat tileFormat = qt_vg_image_to_vg_format(image.format()); + VGImage tile = VG_INVALID_HANDLE; + QVGImagePool *pool = QVGImagePool::instance(); + while (tile == VG_INVALID_HANDLE && tileWidth >= minTileSize) { + tile = pool->createPermanentImage(tileFormat, tileWidth, tileHeight, + VG_IMAGE_QUALITY_FASTER); + if (tile == VG_INVALID_HANDLE) { + tileWidth /= 2; + tileHeight /= 2; + } + } + if (tile == VG_INVALID_HANDLE) { + qWarning("drawImageTiled: Failed to create %dx%d tile, giving up", tileWidth, tileHeight); + return; + } + + VGfloat opacityMatrix[20] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, d->opacity, + 0.0f, 0.0f, 0.0f, 0.0f + }; + VGImage tileWithOpacity = VG_INVALID_HANDLE; + if (d->opacity != 1) { + tileWithOpacity = pool->createPermanentImage(VG_sARGB_8888_PRE, + tileWidth, tileHeight, VG_IMAGE_QUALITY_FASTER); + if (tileWithOpacity == VG_INVALID_HANDLE) + qWarning("drawImageTiled: Failed to create extra tile, ignoring opacity"); + } + + QRect sourceRect = sr.toRect(); + if (sourceRect.isNull()) + sourceRect = QRect(0, 0, image.width(), image.height()); + + VGfloat scaleX = r.width() / sourceRect.width(); + VGfloat scaleY = r.height() / sourceRect.height(); + + d->setImageOptions(); + + for (int y = sourceRect.y(); y < sourceRect.height(); y += tileHeight) { + int h = qMin(tileHeight, sourceRect.height() - y); + if (h < 1) + break; + for (int x = sourceRect.x(); x < sourceRect.width(); x += tileWidth) { + int w = qMin(tileWidth, sourceRect.width() - x); + if (w < 1) + break; + + int bytesPerPixel = image.depth() / 8; + const uchar *sptr = image.constBits() + x * bytesPerPixel + y * image.bytesPerLine(); + vgImageSubData(tile, sptr, image.bytesPerLine(), tileFormat, 0, 0, w, h); + + QTransform transform(d->imageTransform); + transform.translate(r.x() + x, r.y() + y); + transform.scale(scaleX, scaleY); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + VGImage actualTile = tile; + if (tileWithOpacity != VG_INVALID_HANDLE) { + vgColorMatrix(tileWithOpacity, actualTile, opacityMatrix); + if (w < tileWidth || h < tileHeight) + actualTile = vgChildImage(tileWithOpacity, 0, 0, w, h); + else + actualTile = tileWithOpacity; + } else if (w < tileWidth || h < tileHeight) { + actualTile = vgChildImage(tile, 0, 0, w, h); + } + vgDrawImage(actualTile); + + if (actualTile != tile && actualTile != tileWithOpacity) + vgDestroyImage(actualTile); + } + } + + vgDestroyImage(tile); + if (tileWithOpacity != VG_INVALID_HANDLE) + vgDestroyImage(tileWithOpacity); +} + // Used by qpixmapfilter_vg.cpp to draw filtered VGImage's. void qt_vg_drawVGImage(QPainter *painter, const QPointF& pos, VGImage vgImg) { @@ -3170,7 +3259,7 @@ void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) vgpd->source.beginDataAccess(); drawImage(pos, vgpd->source.imageRef()); - vgpd->source.endDataAccess(); + vgpd->source.endDataAccess(true); } else { drawImage(pos, *(pd->buffer())); } @@ -3219,7 +3308,10 @@ void QVGPaintEngine::drawImage } else { // Monochrome images need to use the vgChildImage() path. vgImg = toVGImage(image, flags); - drawVGImage(d, r, vgImg, image.size(), sr); + if (vgImg == VG_INVALID_HANDLE) + drawImageTiled(d, r, image, sr); + else + drawVGImage(d, r, vgImg, image.size(), sr); } } vgDestroyImage(vgImg); @@ -3246,7 +3338,10 @@ void QVGPaintEngine::drawImage(const QPointF &pos, const QImage &image) } else { vgImg = toVGImageWithOpacity(image, d->opacity); } - drawVGImage(d, pos, vgImg); + if (vgImg == VG_INVALID_HANDLE) + drawImageTiled(d, QRectF(pos, image.size()), image); + else + drawVGImage(d, pos, vgImg); vgDestroyImage(vgImg); } -- cgit v0.12 From 5054d7ecdb3bd3fc1c5bf77a99b1675c26ba9795 Mon Sep 17 00:00:00 2001 From: Timo Turunen Date: Tue, 22 Mar 2011 15:21:10 +0200 Subject: Changes for 4.7.3 Reviewed-by: Trust Me --- dist/changes-4.7.3 | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/dist/changes-4.7.3 b/dist/changes-4.7.3 index e69de29..fa8a71e 100644 --- a/dist/changes-4.7.3 +++ b/dist/changes-4.7.3 @@ -0,0 +1,47 @@ +Qt 4.7.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 4.7.0. For more details, +refer to the online documentation included in this distribution. The +documentation is also available online: + +http://qt.nokia.com/doc/4.7 + +The Qt version 4.7 series is binary compatible with the 4.6.x series. +Applications compiled for 4.6 will continue to run with 4.7. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker or the Merge Request queue +of the public source repository. + +Qt Bug Tracker: http://bugreports.qt.nokia.com +Merge Request: http://qt.gitorious.org + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Qt for Symbian +-------------- + +- Bearer Management +* [QTBUG-15108] Deadlock between SymbianEngine mutex and +QNetworkConfigurationPrivate mutex in the symbian bearer code +* [QTBUG-17627] qnetworksession.h Q_DECLARE_METATYPE breaks building +QtMobility QtBearer depending applications + +- GraphicsView +* [QTBUG-17966] Major regression in QGraphicsView OpenVG backend + +- Declarative +* [QTBUG-17503] Export qml debugging symbols on Symbian + +- Widgets +* [QTBUG-17786] BC between Qt 4.7.3 and 4.6.3 QTreeView::indexRowSizeHint +doesn't return correct value on Symbian for row when QPushButton widget is +inserted in the treeview + +- Painting +* [QTBUG-17907] tst_QGraphicsTransform::rotation3d test case from +tests/auto/qgraphicstransfor is failed for some rotation angle on +Symbian^3 devices +* [QTBUG-18154] Symbian's QPixmap::logicalDpi[X\Y]() incorrectly +returns MAXINT -- cgit v0.12 From fe3b07884cf2a9c02a5dc3a8fc7aebcd42a5ee91 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 22 Mar 2011 19:45:13 +0100 Subject: sort out stdout vs. stderr usage Task-number: QTBUG-14728 --- tools/linguist/lconvert/main.cpp | 2 +- tools/linguist/lupdate/main.cpp | 71 +++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/tools/linguist/lconvert/main.cpp b/tools/linguist/lconvert/main.cpp index a10a42b..a9960fc 100644 --- a/tools/linguist/lconvert/main.cpp +++ b/tools/linguist/lconvert/main.cpp @@ -65,7 +65,7 @@ static int usage(const QStringList &args) foreach (Translator::FileFormat format, Translator::registeredFileFormats()) loaders += line.arg(format.extension, -5).arg(format.description); - std::cerr << qPrintable(LC::tr("\nUsage:\n" + std::cout << qPrintable(LC::tr("\nUsage:\n" " lconvert [options] [...]\n\n" "lconvert is part of Qt's Linguist tool chain. It can be used as a\n" "stand-alone tool to convert and filter translation data files.\n" diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index 15583e1..f8e6a90 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -61,6 +61,11 @@ static QString m_defaultExtensions; static void printOut(const QString & out) { + std::cout << qPrintable(out); +} + +static void printErr(const QString & out) +{ std::cerr << qPrintable(out); } @@ -151,23 +156,23 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil cd.m_sortContexts = !(options & NoSort); if (QFile(fileName).exists()) { if (!tor.load(fileName, cd, QLatin1String("auto"))) { - printOut(cd.error()); + printErr(cd.error()); *fail = true; continue; } tor.resolveDuplicates(); cd.clearErrors(); if (setCodec && fetchedTor.codec() != tor.codec()) - printOut(LU::tr("lupdate warning: Codec for tr() '%1' disagrees with" + printErr(LU::tr("lupdate warning: Codec for tr() '%1' disagrees with" " existing file's codec '%2'. Expect trouble.\n") .arg(QString::fromLatin1(fetchedTor.codecName()), QString::fromLatin1(tor.codecName()))); if (!targetLanguage.isEmpty() && targetLanguage != tor.languageCode()) - printOut(LU::tr("lupdate warning: Specified target language '%1' disagrees with" + printErr(LU::tr("lupdate warning: Specified target language '%1' disagrees with" " existing file's language '%2'. Ignoring.\n") .arg(targetLanguage, tor.languageCode())); if (!sourceLanguage.isEmpty() && sourceLanguage != tor.sourceLanguageCode()) - printOut(LU::tr("lupdate warning: Specified source language '%1' disagrees with" + printErr(LU::tr("lupdate warning: Specified source language '%1' disagrees with" " existing file's language '%2'. Ignoring.\n") .arg(sourceLanguage, tor.sourceLanguageCode())); } else { @@ -212,11 +217,11 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil out.normalizeTranslations(cd); if (!cd.errors().isEmpty()) { - printOut(cd.error()); + printErr(cd.error()); cd.clearErrors(); } if (!out.save(fileName, cd, QLatin1String("auto"))) { - printOut(cd.error()); + printErr(cd.error()); *fail = true; } } @@ -278,7 +283,7 @@ static void processSources(Translator &fetchedTor, } loadCPP(fetchedTor, sourceFilesCpp, cd); if (!cd.error().isEmpty()) - printOut(cd.error()); + printErr(cd.error()); } static void processProjects( @@ -298,7 +303,7 @@ static void processProject( if (!tmp.isEmpty()) { codecForSource = tmp.last().toLatin1(); if (!QTextCodec::codecForName(codecForSource)) { - printOut(LU::tr("lupdate warning: Codec for source '%1' is invalid." + printErr(LU::tr("lupdate warning: Codec for source '%1' is invalid." " Falling back to codec for tr().\n") .arg(QString::fromLatin1(codecForSource))); codecForSource.clear(); @@ -365,12 +370,12 @@ static void processProjects( if (visitor.contains(QLatin1String("TRANSLATIONS"))) { if (parentTor) { if (topLevel) { - std::cerr << qPrintable(LU::tr("lupdate warning: TS files from command line " - "will override TRANSLATIONS in %1.\n").arg(proFile)); + printErr(LU::tr("lupdate warning: TS files from command line " + "will override TRANSLATIONS in %1.\n").arg(proFile)); goto noTrans; } else if (nestComplain) { - std::cerr << qPrintable(LU::tr("lupdate warning: TS files from command line " - "prevent recursing into %1.\n").arg(proFile)); + printErr(LU::tr("lupdate warning: TS files from command line " + "prevent recursing into %1.\n").arg(proFile)); continue; } } @@ -401,8 +406,8 @@ static void processProjects( noTrans: if (!parentTor) { if (topLevel) - std::cerr << qPrintable(LU::tr("lupdate warning: no TS files specified. Only diagnostics " - "will be produced for '%1'.\n").arg(proFile)); + printErr(LU::tr("lupdate warning: no TS files specified. Only diagnostics " + "will be produced for '%1'.\n").arg(proFile)); Translator tor; processProject(nestComplain, pfi, visitor, options, codecForSource, targetLanguage, sourceLanguage, &tor, fail); @@ -471,7 +476,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-target-language")) { ++i; if (i == argc) { - printOut(LU::tr("The option -target-language requires a parameter.\n")); + printErr(LU::tr("The option -target-language requires a parameter.\n")); return 1; } targetLanguage = args[i]; @@ -479,7 +484,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-source-language")) { ++i; if (i == argc) { - printOut(LU::tr("The option -source-language requires a parameter.\n")); + printErr(LU::tr("The option -source-language requires a parameter.\n")); return 1; } sourceLanguage = args[i]; @@ -487,7 +492,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-disable-heuristic")) { ++i; if (i == argc) { - printOut(LU::tr("The option -disable-heuristic requires a parameter.\n")); + printErr(LU::tr("The option -disable-heuristic requires a parameter.\n")); return 1; } arg = args[i]; @@ -498,14 +503,14 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("number")) { options &= ~HeuristicNumber; } else { - printOut(LU::tr("Invalid heuristic name passed to -disable-heuristic.\n")); + printErr(LU::tr("Invalid heuristic name passed to -disable-heuristic.\n")); return 1; } continue; } else if (arg == QLatin1String("-locations")) { ++i; if (i == argc) { - printOut(LU::tr("The option -locations requires a parameter.\n")); + printErr(LU::tr("The option -locations requires a parameter.\n")); return 1; } if (args[i] == QLatin1String("none")) { @@ -515,7 +520,7 @@ int main(int argc, char **argv) } else if (args[i] == QLatin1String("absolute")) { options |= AbsoluteLocations; } else { - printOut(LU::tr("Invalid parameter passed to -locations.\n")); + printErr(LU::tr("Invalid parameter passed to -locations.\n")); return 1; } continue; @@ -541,7 +546,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-codecfortr")) { ++i; if (i == argc) { - printOut(LU::tr("The -codecfortr option should be followed by a codec name.\n")); + printErr(LU::tr("The -codecfortr option should be followed by a codec name.\n")); return 1; } codecForTr = args[i].toLatin1(); @@ -552,7 +557,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-extensions")) { ++i; if (i == argc) { - printOut(LU::tr("The -extensions option should be followed by an extension list.\n")); + printErr(LU::tr("The -extensions option should be followed by an extension list.\n")); return 1; } extensions = args[i]; @@ -560,7 +565,7 @@ int main(int argc, char **argv) } else if (arg == QLatin1String("-pro")) { ++i; if (i == argc) { - printOut(LU::tr("The -pro option should be followed by a filename of .pro file.\n")); + printErr(LU::tr("The -pro option should be followed by a filename of .pro file.\n")); return 1; } proFiles += args[i]; @@ -570,7 +575,7 @@ int main(int argc, char **argv) if (arg.length() == 2) { ++i; if (i == argc) { - printOut(LU::tr("The -I option should be followed by a path.\n")); + printErr(LU::tr("The -I option should be followed by a path.\n")); return 1; } includePath += args[i]; @@ -579,7 +584,7 @@ int main(int argc, char **argv) } continue; } else if (arg.startsWith(QLatin1String("-")) && arg != QLatin1String("-")) { - printOut(LU::tr("Unrecognized option '%1'.\n").arg(arg)); + printErr(LU::tr("Unrecognized option '%1'.\n").arg(arg)); return 1; } @@ -587,7 +592,7 @@ int main(int argc, char **argv) if (arg.startsWith(QLatin1String("@"))) { QFile lstFile(arg.mid(1)); if (!lstFile.open(QIODevice::ReadOnly)) { - printOut(LU::tr("lupdate error: List file '%1' is not readable.\n") + printErr(LU::tr("lupdate error: List file '%1' is not readable.\n") .arg(lstFile.fileName())); return 1; } @@ -605,7 +610,7 @@ int main(int argc, char **argv) if (!fi.exists() || fi.isWritable()) { tsFileNames.append(QFileInfo(file).absoluteFilePath()); } else { - printOut(LU::tr("lupdate warning: For some reason, '%1' is not writable.\n") + printErr(LU::tr("lupdate warning: For some reason, '%1' is not writable.\n") .arg(file)); } found = true; @@ -613,7 +618,7 @@ int main(int argc, char **argv) } } if (!found) { - printOut(LU::tr("lupdate error: File '%1' has no recognized extension.\n") + printErr(LU::tr("lupdate error: File '%1' has no recognized extension.\n") .arg(file)); return 1; } @@ -623,7 +628,7 @@ int main(int argc, char **argv) foreach (const QString &file, files) { QFileInfo fi(file); if (!fi.exists()) { - printOut(LU::tr("lupdate error: File '%1' does not exist.\n").arg(file)); + printErr(LU::tr("lupdate error: File '%1' does not exist.\n").arg(file)); return 1; } if (file.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive) @@ -682,15 +687,15 @@ int main(int argc, char **argv) } if (!targetLanguage.isEmpty() && tsFileNames.count() != 1) - printOut(LU::tr("lupdate warning: -target-language usually only" + printErr(LU::tr("lupdate warning: -target-language usually only" " makes sense with exactly one TS file.\n")); if (!codecForTr.isEmpty() && tsFileNames.isEmpty()) - printOut(LU::tr("lupdate warning: -codecfortr has no effect without -ts.\n")); + printErr(LU::tr("lupdate warning: -codecfortr has no effect without -ts.\n")); bool fail = false; if (proFiles.isEmpty()) { if (tsFileNames.isEmpty()) - printOut(LU::tr("lupdate warning:" + printErr(LU::tr("lupdate warning:" " no TS files specified. Only diagnostics will be produced.\n")); Translator fetchedTor; @@ -705,7 +710,7 @@ int main(int argc, char **argv) sourceLanguage, targetLanguage, options, &fail); } else { if (!sourceFiles.isEmpty() || !includePath.isEmpty()) { - printOut(LU::tr("lupdate error:" + printErr(LU::tr("lupdate error:" " Both project and source files / include paths specified.\n")); return 1; } -- cgit v0.12 From 551ba5eb80bb8e4e522154f43abf864b8bf5146d Mon Sep 17 00:00:00 2001 From: Xizhi Zhu Date: Wed, 23 Mar 2011 13:00:49 +0200 Subject: Fixes QT-4753 Invalid read in ICD plugin for bearer management. Reviewed-by: Iiro Kause --- src/plugins/bearer/icd/dbusdispatcher.cpp | 9 ++++++--- src/plugins/bearer/icd/qnetworksession_impl.cpp | 14 +++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/plugins/bearer/icd/dbusdispatcher.cpp b/src/plugins/bearer/icd/dbusdispatcher.cpp index 13cd8a9..a317cb4 100644 --- a/src/plugins/bearer/icd/dbusdispatcher.cpp +++ b/src/plugins/bearer/icd/dbusdispatcher.cpp @@ -194,18 +194,21 @@ static bool appendVariantToDBusMessage(const QVariant& argument, &int32_data); break; - case QVariant::String: - str_data = argument.toString().toLatin1().data(); + case QVariant::String: { + QByteArray data = argument.toString().toLatin1(); + str_data = data.data(); dbus_message_iter_append_basic(dbus_iter, DBUS_TYPE_STRING, &str_data); break; + } case QVariant::StringList: str_list = argument.toStringList(); dbus_message_iter_open_container(dbus_iter, DBUS_TYPE_ARRAY, "s", &array_iter); for (idx = 0; idx < str_list.size(); idx++) { - str_data = str_list.at(idx).toLatin1().data(); + QByteArray data = str_list.at(idx).toLatin1(); + str_data = data.data(); dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &str_data); diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index af5d85e..94a6c81 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -621,21 +621,21 @@ static QString get_network_interface() if (ret == 0) { /* No results */ #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?"; + qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?"; #endif - return iface; + return iface; } if (addr_results.first().ip_info.isEmpty()) - return QString(); + return QString(); - const char *address = addr_results.first().ip_info.first().address.toAscii().constData(); + QByteArray data = addr_results.first().ip_info.first().address.toAscii(); struct in_addr addr; - if (inet_aton(address, &addr) == 0) { + if (inet_aton(data.constData(), &addr) == 0) { #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "address" << address << "invalid"; + qDebug() << "address" << data.constData() << "invalid"; #endif - return iface; + return iface; } struct ifaddrs *ifaddr, *ifa; -- cgit v0.12 From 4accdf44eb486e603425c5ee69e05b973915f8a6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 Mar 2011 13:09:52 +0200 Subject: Add missing nullify for the s60 style's background pixmap pointer. Qt apps would crash during orientation change without setting m_background to null after deleting it. Reviewed-by: Sami Merila --- src/gui/styles/qs60style_s60.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index c5149a3..64d2ad2 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -1402,6 +1402,7 @@ QPixmap QS60StylePrivate::backgroundTexture(bool skipCreation) if (m_background->width() != applicationRect.Width() || m_background->height() != applicationRect.Height()) { delete m_background; + m_background = 0; createNewBackground = true; } } -- cgit v0.12 From e06d2bc80672776fc4fb0ca8a3861a4f9d493133 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Wed, 23 Mar 2011 14:36:43 +0200 Subject: GraphicsViews: Focused widget is not visible after orientation change If there is a graphicsview with input widget focused and splitview is open, and we rotate the device from Portrait to Landscape (or vice versa), the input widget is no longer visible in the splitview rect. This only happens if there are scrollbars visible in the view. Reason is that the input widget is tried to ensure visibility for before window surface is valid. In these cases, make the input widget visibility re-location happen after window server indicates that the view is now visible. Task-number: QTBUG-17576 Reviewed-by: Guoqing Zhang --- src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 9d8dd41..767b974 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -330,6 +330,21 @@ bool QCoeFepInputContext::symbianFilterEvent(QWidget *keyWidget, const QSymbianE // This should also happen for commands. reset(); + if (event->windowServerEvent() && event->windowServerEvent()->Type() == EEventWindowVisibilityChanged) { + if (S60->splitViewLastWidget) { + QGraphicsView *gv = qobject_cast(S60->splitViewLastWidget); + const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); + + if (alwaysResize) { + TUint visibleFlags = event->windowServerEvent()->VisibilityChanged()->iFlags; + if (visibleFlags & TWsVisibilityChangedEvent::EPartiallyVisible) + ensureFocusWidgetVisible(S60->splitViewLastWidget); + if (visibleFlags & TWsVisibilityChangedEvent::ENotVisible) + resetSplitViewWidget(true); + } + } + } + return false; } -- cgit v0.12 From 2d2af1cac203bb5d47c6a4b1ce23930bdb03b996 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Wed, 23 Mar 2011 14:42:06 +0200 Subject: GraphicsViews: Focused widget is not visible after orientation change Clean up previous fix a little bit, by merging if-statements. Task-number: QTBUG-17576 Reviewed-by: Guoqing Zhang --- src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 767b974..5fccf96 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -330,18 +330,20 @@ bool QCoeFepInputContext::symbianFilterEvent(QWidget *keyWidget, const QSymbianE // This should also happen for commands. reset(); - if (event->windowServerEvent() && event->windowServerEvent()->Type() == EEventWindowVisibilityChanged) { - if (S60->splitViewLastWidget) { - QGraphicsView *gv = qobject_cast(S60->splitViewLastWidget); - const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); - - if (alwaysResize) { - TUint visibleFlags = event->windowServerEvent()->VisibilityChanged()->iFlags; - if (visibleFlags & TWsVisibilityChangedEvent::EPartiallyVisible) - ensureFocusWidgetVisible(S60->splitViewLastWidget); - if (visibleFlags & TWsVisibilityChangedEvent::ENotVisible) - resetSplitViewWidget(true); - } + if (event->type() == QSymbianEvent::WindowServerEvent + && event->windowServerEvent() + && event->windowServerEvent()->Type() == EEventWindowVisibilityChanged + && S60->splitViewLastWidget) { + + QGraphicsView *gv = qobject_cast(S60->splitViewLastWidget); + const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); + + if (alwaysResize) { + TUint visibleFlags = event->windowServerEvent()->VisibilityChanged()->iFlags; + if (visibleFlags & TWsVisibilityChangedEvent::EPartiallyVisible) + ensureFocusWidgetVisible(S60->splitViewLastWidget); + if (visibleFlags & TWsVisibilityChangedEvent::ENotVisible) + resetSplitViewWidget(true); } } -- cgit v0.12 From 1dbd4a629bb5e2392bf2c7ea096ad3d77a265e5f Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Wed, 23 Mar 2011 15:22:43 +0200 Subject: Prevent crash when connecting signal in splitview If there is no focusitem when connecting a signal, splitview crashes. This is caused by null pointer use. Prevent the crash by checking the pointer. Task-number: QTBUG-16572 Reviewed-by: Guoqing Zhang --- src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 5fccf96..41abe95 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -410,8 +410,11 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) windowToMove->setUpdatesEnabled(false); if (!alwaysResize) { - if (gv->scene()) { - if (gv->scene()->focusItem()) + if (gv->scene() && gv->scene()->focusItem()) { + // Check if the widget contains cursorPositionChanged signal and disconnect from it. + QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); + int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); + if (index != -1) disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); QGraphicsItem *rootItem; foreach (QGraphicsItem *item, gv->scene()->items()) { @@ -501,6 +504,13 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) // states getting changed. if (!moveWithinVisibleArea) { + // Check if the widget contains cursorPositionChanged signal and connect to it. + QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); + if (gv->scene() && gv->scene()->focusItem()) { + int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); + if (index != -1) + connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + } S60->splitViewLastWidget = widget; m_splitViewPreviousWindowStates = windowToMove->windowState(); } @@ -537,13 +547,6 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) } windowToMove->setUpdatesEnabled(true); } else { - if (!moveWithinVisibleArea) { - // Check if the widget contains cursorPositionChanged signal and connect to it. - const char *signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())).constData(); - int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal + 1); - if (index != -1) - connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); - } translateInputWidget(); } -- cgit v0.12 From 9a42d9815b73e5ceb25360af02936bcb0454a965 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Wed, 23 Mar 2011 17:30:45 +0200 Subject: Icon in QMessageBox::question is deformed on Symbian MessageBox icons are deformed on Qt/S60, since style creates all icons with 1:1 width:height ratio. Based on S60 documentation messagebox icons are of 4:3 ratio. This is the same ratio between all the S60 releases. Task-number: QTBUG-14953 Reviewed-by: Laszlo Agocs --- src/gui/styles/qs60style.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index a9e10a3..1320f5e 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -3353,9 +3353,9 @@ bool QS60Style::event(QEvent *e) QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { - const int iconDimension = QS60StylePrivate::pixelMetric(PM_ToolBarIconSize); - const QRect iconSize = (!option) ? QRect(0, 0, iconDimension, iconDimension) : option->rect; QS60StyleEnums::SkinParts part; + qreal iconHeightMultiplier = 1.0; + qreal iconWidthMultiplier = 1.0; QS60StylePrivate::SkinElementFlags adjustedFlags; if (option) adjustedFlags = (option->state & State_Enabled || option->state == 0) ? @@ -3364,15 +3364,20 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, switch(standardIcon) { case SP_MessageBoxWarning: + // By default, S60 messagebox icons have 4:3 ratio. Value is from S60 LAF documentation. + iconHeightMultiplier = 1.33; part = QS60StyleEnums::SP_QgnNoteWarning; break; case SP_MessageBoxInformation: + iconHeightMultiplier = 1.33; part = QS60StyleEnums::SP_QgnNoteInfo; break; case SP_MessageBoxCritical: + iconHeightMultiplier = 1.33; part = QS60StyleEnums::SP_QgnNoteError; break; case SP_MessageBoxQuestion: + iconHeightMultiplier = 1.33; part = QS60StyleEnums::SP_QgnNoteQuery; break; case SP_ArrowRight: @@ -3427,11 +3432,13 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, adjustedFlags |= QS60StylePrivate::SF_PointEast; part = QS60StyleEnums::SP_QgnIndiSubmenu; break; - default: return QCommonStyle::standardIconImplementation(standardIcon, option, widget); } const QS60StylePrivate::SkinElementFlags flags = adjustedFlags; + const int iconDimension = QS60StylePrivate::pixelMetric(PM_ToolBarIconSize); + const QRect iconSize = (!option) ? + QRect(0, 0, iconDimension * iconWidthMultiplier, iconDimension * iconHeightMultiplier) : option->rect; const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), 0, flags)); return cachedPixMap.isNull() ? QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap); -- cgit v0.12 From 70fb72ca17b5176bb551a7ae9f2129b48496c635 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 24 Mar 2011 13:36:57 +1000 Subject: Fix memory leak. Change-Id: I919935399ee1b0e505c85781d481d17345df25c9 Task-number: QT-4330 Reviewed-by: Michael Brasser --- src/declarative/util/qdeclarativeanimation.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index ac9c3c0..67461b0 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2765,6 +2765,8 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, d->endAction->setAnimAction(d->via ? viaData : data, QActionAnimation::DeleteWhenStopped); d->startAction->setAnimAction(d->via ? data : 0, QActionAnimation::DeleteWhenStopped); } + if (!d->via) + delete viaData; } else { delete data; delete viaData; -- cgit v0.12 From f49490a13b664eb00207b2d3d6354071ae81f161 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 10 Dec 2010 16:07:25 +0100 Subject: Make sure num_glyphs pass to HarfBuzz is large enough (Backport from master) Currently we only pass the num_glyphs for the run to HB_ShapeItem, but it can be less then the string length for this run because of Unicode surrogates. Thus, we need to pass at least the length of that run as num_glyphs to HB (given that we have enough space allocated because for the entire string), if that's still not enough, we will do ensureSpace again according to the num_glyphs returned by HB and move remaining glyphs backwards. Task-number: QTBUG-15679 Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 5 ++++- tests/auto/qtextlayout/tst_qtextlayout.cpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index b511b5a..4378c62 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1233,6 +1233,8 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const shaper_item.num_glyphs -= itemBoundaries[k + 1]; } shaper_item.initialGlyphCount = shaper_item.num_glyphs; + if (shaper_item.num_glyphs < shaper_item.item.length) + shaper_item.num_glyphs = shaper_item.item.length; QFontEngine *actualFontEngine = font; uint engineIdx = 0; @@ -1257,7 +1259,8 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const } const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); - moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); + if (shaper_item.num_glyphs > shaper_item.item.length) + moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs); shaper_item.glyphs = g.glyphs; shaper_item.attributes = g.attributes; diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index 2d15566..85e6616 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -125,6 +125,7 @@ private slots: void textWidthVsWIdth(); void textWidthWithStackedTextEngine(); void textWidthWithLineSeparator(); + void textWithSurrogates_qtbug15679(); private: QFont testFont; @@ -1416,5 +1417,24 @@ void tst_QTextLayout::textWidthWithLineSeparator() QCOMPARE(line1.naturalTextWidth(), line2.naturalTextWidth()); } +void tst_QTextLayout::textWithSurrogates_qtbug15679() +{ + QString str = QString::fromUtf8("🀀a🀀"); + QTextLayout layout(str); + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + + qreal x[6]; + for (int i = 0; i < 6; i++) + x[i] = line.cursorToX(i); + + // If the first and third character are using the same + // font, they must have the same advance (since they + // are surrogate pairs, we need to add two for each + // character) + QCOMPARE(x[2] - x[0], x[5] - x[3]); +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" -- cgit v0.12 From 903fdabf3eb808a96e2a869049c2095cde09d2be Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 25 Mar 2011 09:37:46 +1000 Subject: Fix QUnifiedTimer bug Pause animations (like Timer) could trigger a jump to the next tick, which meant that other pause animations would have missed the interval skipped by the pause. Change-Id: Idebe4cbe70b2a1536d684288fc1c5d65e4c5df84 Cherry-pick-of: 0f5feed7dc260eabe1c2784a168e0b2fcc85e1d8 Task-number: QTBUG-18126 Reviewed-by: Leo Cunha Reviewed-by: Michael Brasser --- src/corelib/animation/qabstractanimation.cpp | 8 +++++++- src/corelib/animation/qabstractanimation_p.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 5e6110f..a9bb129 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -167,7 +167,7 @@ Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer) QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), - currentAnimationIdx(0), consistentTiming(false), slowMode(false), + insideTick(false), currentAnimationIdx(0), consistentTiming(false), slowMode(false), slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0) { time.invalidate(); @@ -205,6 +205,10 @@ void QUnifiedTimer::ensureTimerUpdate() void QUnifiedTimer::updateAnimationsTime() { + //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations + if(insideTick) + return; + qint64 totalElapsed = time.elapsed(); // ignore consistentTiming in case the pause timer is active int delta = (consistentTiming && !isPauseTimerActive) ? @@ -222,12 +226,14 @@ void QUnifiedTimer::updateAnimationsTime() //it might happen in some cases that the time doesn't change because events are delayed //when the CPU load is high if (delta) { + insideTick = true; for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } + insideTick = false; currentAnimationIdx = 0; } } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index c0488c8..aeee1f2 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -175,6 +175,7 @@ private: qint64 lastTick; int timingInterval; int currentAnimationIdx; + bool insideTick; bool consistentTiming; bool slowMode; -- cgit v0.12 From cad8cedd21eaf4f115d188d33381063fe75e1c78 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 25 Mar 2011 14:16:36 +0100 Subject: Edited the Tutorials and Examples pages. Renamed links in index.qdoc. Added a link to the eLearning materials and Creator manual. Reviewed-by: David Boddie --- doc/src/getting-started/examples.qdoc | 11 ++- doc/src/getting-started/tutorials.qdoc | 169 +++++++++++++++++++-------------- doc/src/index.qdoc | 5 +- doc/src/qt-webpages.qdoc | 17 ++++ 4 files changed, 127 insertions(+), 75 deletions(-) diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc index 55d37d6..9a8fcaa 100644 --- a/doc/src/getting-started/examples.qdoc +++ b/doc/src/getting-started/examples.qdoc @@ -36,7 +36,8 @@ You can run the examples from the \l{Examples and Demos Launcher} application (except see \l{QML Examples and Demos} {QML Examples} - for special instructions for running those examples). + for special instructions for running those examples). In addition, + Qt Creator can directly run these examples through the Welcome Page. The examples are listed below by functional area. Each example listed in a particular functional area is meant to illustrate how @@ -56,8 +57,14 @@ These examples are provided under the terms of the \l{New and Modified BSD Licenses}{Modified BSD License}. + \section1 Qt Quick Example Code + The \l{QML Examples and Demos} site has a dedicated page for QML examples. - \section1 Examples by Functional Area + \section1 Qt Mobility Example Code + The \l{external: Qt Mobility Examples}{Qt Mobility Examples} page lists + examples that show how the Qt Mobility APIs might be used. + + \section1 Qt Examples by Module or Technology \generatelist{related} */ diff --git a/doc/src/getting-started/tutorials.qdoc b/doc/src/getting-started/tutorials.qdoc index 9fc6699..2849870 100644 --- a/doc/src/getting-started/tutorials.qdoc +++ b/doc/src/getting-started/tutorials.qdoc @@ -36,79 +36,106 @@ \nextpage Qt Examples - A collection of tutorials and "walkthrough" guides are provided with Qt to + A collection of tutorials and \e walkthrough guides are provided with Qt to help new users get started with Qt development. These documents cover a range of topics, from basic use of widgets to step-by-step tutorials that show how an application is put together. - \table - \row - \o{2,1} \l{Widgets Tutorial}{\bold Widgets} - \o{2,1} \l{Address Book Tutorial}{\bold {Address Book}} - \row - \o \image widget-examples.png Widgets - \o - A beginner's guide to getting started with widgets and layouts to create - GUI applications. - - \o \image addressbook-tutorial.png AddressBook - \o - A seven part guide to creating a fully-functioning address book - application. This tutorial is also available with - \l{Tutoriel "Carnet d'adresses"}{French explanation}. - - \row - \o{2,1} \l{A Quick Start to Qt Designer}{\bold{Qt Designer}} - \o{2,1} \l{Qt Linguist Manual: Programmers#Tutorials}{\bold {Qt Linguist}} - \row - \o \image designer-examples.png - \o - A quick guide through \QD showing the basic steps to create a - form with this interactive tool. - - \o \image linguist-examples.png QtLinguist - \o - A guided tour through the translations process, explaining the - tools provided for developers, translators and release managers. - - -\row - \o{2,1} \l{modelview.html}{\bold{ModelView}} - \o{2,1} \l{thread-basics.html}{\bold {Threads}} - \row - \o \image treeview_sml.png ModelView - \o - This tutorial gives an introduction to ModelView programming using the Qt cross-platform framework - - \o \image threads-examples.png Threads - \o - A short tutorial about thread concepts in general and basic Qt classes to handle threads. - - \row - \o{2,1} \l{QML Tutorial}{\bold QML Tutorial} - \o{2,1} \l{QML Advanced Tutorial}{\bold SameGame} - \row - \o{2,1} - This tutorial provides a very basic introduction to QML. - \o \image qml-samegame-demo-small.png Samegame - \o - This tutorial walks through creating a complete application with QML, - in this case a simple game. It is recommended that you complete the basic QML - tutorial first. - - \row - \o{2,1} \l{QTestLib Tutorial}{\bold QTestLib} - \o{2,1} \l{qmake Tutorial}{\bold qmake} - \row - \o{2,1} - This tutorial gives a short introduction to how to use some of the - features of Qt's unit-testing framework, QTestLib. It is divided into - four chapters. - - \o{2,1} - This tutorial teaches you how to use \c qmake. We recommend that - you read the \l{qmake Manual}{qmake user guide} after completing - this tutorial. - - \endtable + For demonstrations on how to use different Qt technologies, visit the + \l{Qt Examples} page. + + \section1 Qt Creator Tutorial + Qt Creator is the development environment for Qt. + \list + \o \l{external: Qt Creator Manual}{Qt Creator Manual} - The manual contains + information on how to achieve development tasks + These are excerpts from the manual: + \list + \o \l{external: Creating Qt Projects in Creator}{Creating Qt Projects in Creator} + \o \l{external: Developing Qt Quick Applications with Creator}{Developing Qt Quick Applications with Creator} + \o \l{external: Building and Running Applications in Creator}{Building and Running Applications in Creator} + \o \l{external: Debugging Applications in Creator}{Debugging Applications in Creator} + \o \l{external: Publishing Applications to Ovi Store}{Publishing Applications to Ovi Store} + \endlist + \endlist + + \section1 Qt Essentials + The basic concepts and technologies in Qt are introduced in these essential + tutorials. + \list + \o \l{Getting Started Programming with Qt}{Qt Text Editor} - A simple + tutorial detailing the creation of a basic Qt application + Introduces the use of slots and signals, file operations, and widgets. + \o \l{Address Book Tutorial}{Address Book} - A beginner's guide to + widgets, container classes, and layouts. This tutorial is also available + with + \l{Tutoriel "Carnet d'adresses"}{French version}. + \image addressbook-tutorial.png AddressBook + \o \l{modelview.html}{ModelView} - This tutorial gives an introduction to + ModelView programming using the Qt cross-platform framework + \o\l{thread-basics.html}{Threads} - A short tutorial about thread concepts + in general and basic Qt classes to handle threads + \endlist + + \section1 Qt Quick Essentials + Qt Quick and QML features are covered in several tutorials, ranging from + easy introductions to advanced tutorials that mix QML with C++ and + JavaScript. + \list + \o \l{QML Tutorial}{Hello World} - A very simple QML example that + demonstrates the basic QML features + \o \l{Getting Started Programming with QML}{QML Text Editor} - An + intermediate QML tutorial that covers many QML features such as states, + plugins, and C++ development + \o \l{QML Advanced Tutorial}{SameGame} - A walkthrough of creating a + simple game using QML for the interface and JavaScript for the game + logic + \image qml-samegame-demo-small.png Samegame + \endlist + + \section1 QtWebKit + \list + \o \l{QtWebKit Guide} - An introductory guide to the features of QtWebKit + and HTML5. + \list + \o \l{QtWebKit Guide - Level 3 CSS}{CSS Chapter} - Covers what is + possible with CSS3 and QtWebKit. + \o \l{Canvas Graphics}{HTML5 Canvas Chapter} - Covers the basics of + integrating the element into web applications. + \o \l{QtWebKit Guide - Client Storage}{Client Storage Chapter} - + Describes the basics of storing information on the client side. + \endlist + \endlist + + \section1 Qt Utilities + \list + \o \l{QTestLib Tutorial}{QTestLib} - This tutorial gives a short + introduction to how to use some of the features of Qt's unit-testing + framework, QTestLib. It is divided into four chapters. + \o \l{qmake Tutorial}{qmake} - This tutorial teaches you how to use \c + qmake. We recommend that you read the \l{qmake Manual}{qmake user guide} + after completing this tutorial. + \o \l{Qt Linguist Manual: Programmers#Tutorials}{Qt Linguist} - A guided + tour through the translations process, explaining the tools provided for + developers, translators and release managers. + \image linguist-examples.png QtLinguist + \endlist + + \section1 Online Learning Materials + These online materials provide further tutorials and developer + presentations. + + \note The videos presented in these sites are not supported by the + Qt Creator browser and must be viewed in a web browser. + + \list + \o \l{Qt eLearning} - The Qt eLearning team provides training and Qt + certification. Many of their learning content are hosted online. + \list + \o \l{Qt eLearning Training Materials} - Additional training material + are available as videos, downloadable code, and PDF files. + \o \l{Qt Developer Days 2010} - The presentation slides and videos from + Qt Developer Days are available for viewing. + \endlist + \endlist */ diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc index 90caf06..69bb038 100644 --- a/doc/src/index.qdoc +++ b/doc/src/index.qdoc @@ -73,14 +73,15 @@ Develop with Qt \enddiv \list - \o \l{Getting Started Guides}{Getting Started with Qt} \o \l{Develop with Qt}{Steps to Programming Qt Applications} \o \l{qt-creator-configure-target}{Configure Qt and Creator for Platforms} \o \l{qt-technologies}{Qt Features and Technologies} \o \l{qt-utilities}{Utilities and Testing} \o \l{qt-deployment}{Deploying and Publishing Applications to Ovi Store} \endlist - + \list + \o \l{Getting Started Guides}{Qt and Qt Quick Programming Guides} + \endlist \enddiv \div {class="sectionlist normallist"} \div {class="heading"} diff --git a/doc/src/qt-webpages.qdoc b/doc/src/qt-webpages.qdoc index d0a5416..9097a38 100644 --- a/doc/src/qt-webpages.qdoc +++ b/doc/src/qt-webpages.qdoc @@ -301,3 +301,20 @@ \externalpage http://qt.nokia.com/developer/learning/online/training/training-day-at-developer-days-2009/ \title Training Day at Qt Developer Days 2009 */ +/*! + \externalpage http://doc.qt.nokia.com/qtmobility/all-examples.html + \title external: Qt Mobility Examples +*/ +/*! + \externalpage http://qt.nokia.com/developer/learning/online/training + \title Qt eLearning +*/ +/*! + \externalpage http://qt.nokia.com/developer/learning/online/training + \title Qt eLearning Training Materials +*/ +/*! + \externalpage http://qt.nokia.com/developer/learning/online/talks/developerdays2010 + \title Qt Developer Days 2010 +*/ + -- cgit v0.12 From 921896ab2b5f2ad6be547fbac532914c8f35c80b Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Mon, 28 Mar 2011 10:07:09 +0200 Subject: qdoc: Added a way to exclude directories from receiving default metadata But it is ifdefed out because I think we won't use it. --- tools/qdoc3/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/qdoc3/main.cpp b/tools/qdoc3/main.cpp index 7eb8067..52715a3 100644 --- a/tools/qdoc3/main.cpp +++ b/tools/qdoc3/main.cpp @@ -235,6 +235,26 @@ static void processQdocconfFile(const QString &fileName) QStringList indexFiles = config.getStringList(CONFIG_INDEXES); tree->readIndexes(indexFiles); +#if 0 + /* + I think we won't beusing this... + + Read the list of DITA excluded directories. + */ + QSet ditaExcludedDirs; + QStringList ditaExcludedDirsList = config.getStringList("dita.metadata.excludedirs"); + foreach (const QString &t, ditaExcludedDirsList) + ditaExcludedDirs.insert(QDir::fromNativeSeparators(t)); + + if (!ditaExcludedDirs.isEmpty()) { + QSet::iterator i = ditaExcludedDirs.begin(); + while (i != ditaExcludedDirs.end()) { + qDebug() << "DITA EXCLUDED DIR:" << (*i); + ++i; + } + } +#endif + /* Read the list of excluded directories. */ -- cgit v0.12 From d89b8fb714e2d2e592b221cf2832eb4c188e2029 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Mon, 28 Mar 2011 15:13:23 +0200 Subject: qdoc: Updates to the qdoc manual. --- tools/qdoc3/doc/qdoc-manual.qdoc | 91 +++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/tools/qdoc3/doc/qdoc-manual.qdoc b/tools/qdoc3/doc/qdoc-manual.qdoc index 712dcea..0fbd4b7 100644 --- a/tools/qdoc3/doc/qdoc-manual.qdoc +++ b/tools/qdoc3/doc/qdoc-manual.qdoc @@ -141,13 +141,16 @@ \c {/current/dir$ ../../bin/qdoc3 ./config.qdocconf} \endquotation - \c{config.qdocconf} is your \l{The QDoc Configuration File} {QDoc - configuration file}. The configuration file is where tell QDoc - where to find the source files from which it will extract the QDoc - comments it will use to generate the documentation. It is also - where you tell QDoc what kind of output to generate (HTML, DITA - XML,...), and where to put the generated output. The configuration - file also contains other information for QDoc. + In the command line above, \c{config.qdocconf} is a \l{The QDoc + Configuration File} {QDoc configuration file}. The configuration + file is where you tell QDoc where to find the source files that + contain the QDoc comments that will become the documentation. It + is also where you tell QDoc what kind of output to generate (HTML, + DITA XML,...), and where to put the generated output. The + configuration file also contains other information for QDoc. + + See \l{The QDoc Configuration File} for a instructions on how ro + build a Qdoc configuration file. \section1 Command Types @@ -6740,59 +6743,41 @@ \title The QDoc Configuration File - Before running QDoc to to extract and format your QDOC comments, - you must create a QDoc configuration file to tell QDoc where to find - them. + Before running QDoc, you must create a QDoc configuration file to + tell QDoc where to find the source files that contain the QDoc + comments. The pathname to your configuration file is passed to + QDoc on the command line: - \list - \o \l {Supporting Derived Projects} - \o \l {Compatibility Issues} - \endlist - - When running QDoc to generate the documentation, you must specify - a configuration file on the command line: + \quotation + \c {/current/dir$ ../../bin/qdoc3 ./config.qdocconf} + \endquotation \section1 General Description - The configuration file is a list of entries of entries of the form - \e {"variable = value"}. Using the configuration variables, you - can define where QDoc should find the various source files, images - and examples, where to put generated documentation etc. The + The configuration file is a list of entries of the form \e + {"variable = value"}. Using the configuration variables, you can + define where QDoc should find the various source files, images and + examples, where to put generated documentation etc. The configuration file can also contain directives like \c include. For an example, see the \l minimum.qdocconf file. - In addition, you can use some particular configuration variables - to make QDoc support derived projects, i.e make the projects, for - example Qt Solutions, contain links to the online Qt - documentation. These variables are documented in the \l - {Supporting Derived projects} section. In this section you can - also find out how to use these variables to support your derived - projects. - - If some of the variable keys have the same values, they can be set - at the same time. - - \code - {header, source}dirs = kernel - \endcode - - is equivalent to - - \code - headerdirs = kernel - sourcedirs = kernel - \endcode - - A variable's value can be set using either '=' or '+='. The - difference is that '=' overrides any previously set value, while - '+=' only adds the value to the previously set ones. - - In general, some of the variables accepts a list of strings as - their value, while others only accept a single string. If you - provide a variable of the latter type with several strings they - will simply be concatenated. The quotes around the value string - are optional. But applying them allows you to use special - characters like '=' and ' \" ' within the string. + You can also use configuration variables to get QDoc to support + \l{Supporting Derived Projects} {derived projects}, i.e QDoc can + generate links in your project's documentation to elements in the + Qt online documentation. See the \l {Supporting Derived projects} + section. + + The value of a configuration variable can be set using either '=' + or '+='. The difference is that '=' overrides the previous value, + while '+=' adds a new value to the current one. + + Some configuration variables accept a list of strings as their + value, e.g. + \l {22-qdoc-configuration-generalvariables.html#sourcedirs-variable} + {\c{sourcedirs}}, while others accept only a single string. Double + quotes around a value string are optional, but including them allows + you to use special characters like '=' and ' \" ' within the valuem + string, e.g.: \code HTML.postheader = "Home" -- cgit v0.12 From 16b75d6faea5cbf4be16476ae0e53ffbc01d58bd Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Mon, 28 Mar 2011 15:43:16 +0200 Subject: Added a link to the Debugging Techniques article. --- doc/src/mainpage.qdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/mainpage.qdoc b/doc/src/mainpage.qdoc index cafd927..f7f0486 100644 --- a/doc/src/mainpage.qdoc +++ b/doc/src/mainpage.qdoc @@ -171,6 +171,7 @@ Testing and debugging are part of the development process and Qt offers the developer multiple methods of testing their code. \list \o \l{external: Debugging Applications in Creator}{Debugging Applications in Creator} - various debugging options in Creator +\o \l{Debugging Techniques} - essential techniques for debugging Qt code \o \l{external: Qt Simulator Manual}{Simulator} - testing mobile applications by simulating a mobile environment \o \l{QML Viewer} - an executable that is able to run QML files \o \l{QTestLib Manual}{QTestLib} - a unit testing framework built into Qt -- cgit v0.12