From 90e009e9e273a4fea5166007e4c2b0638c6588cd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 7 Jun 2010 11:41:10 +0200 Subject: Fix QTransform::map(const QPainterPath &) not working with paths that have only one element Replaced the isEmpty() check for the shortcut in map() with elementCount() == 0 Task-number: QTBUG-11264 Reviewed-by: Samuel --- src/gui/painting/qtransform.cpp | 2 +- tests/auto/qtransform/tst_qtransform.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 423cce9..47b7758 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1626,7 +1626,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat QPainterPath QTransform::map(const QPainterPath &path) const { TransformationType t = inline_type(); - if (t == TxNone || path.isEmpty()) + if (t == TxNone || path.elementCount() == 0) return path; if (t >= TxProject) diff --git a/tests/auto/qtransform/tst_qtransform.cpp b/tests/auto/qtransform/tst_qtransform.cpp index a3ded8e..c784b3a 100644 --- a/tests/auto/qtransform/tst_qtransform.cpp +++ b/tests/auto/qtransform/tst_qtransform.cpp @@ -85,6 +85,7 @@ private slots: void inverted(); void projectivePathMapping(); void mapInt(); + void mapPathWithPoint(); private: void mapping_data(); @@ -793,6 +794,13 @@ void tst_QTransform::mapInt() QCOMPARE(y, 10); } +void tst_QTransform::mapPathWithPoint() +{ + QPainterPath p(QPointF(10, 10)); + p = QTransform::fromTranslate(10, 10).map(p); + QCOMPARE(p.currentPosition(), QPointF(20, 20)); +} + QTEST_APPLESS_MAIN(tst_QTransform) -- cgit v0.12 From f409128642c976bde0a7d4f32ed1db96a2af637b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Riku=20Palom=C3=A4ki?= Date: Mon, 7 Jun 2010 12:18:23 +0200 Subject: Splitted attrib_list generation into buildSpec from QGLContext::tryVisual. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 609 Reviewed-by: Samuel Rødal --- src/opengl/qgl_x11.cpp | 281 +++++++++++++++++++++++++------------------------ 1 file changed, 144 insertions(+), 137 deletions(-) diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index d203646..a6b0fae 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -401,6 +401,148 @@ bool QGLFormat::hasOpenGLOverlays() return trans_colors.size() > 0; } +static bool buildSpec(int* spec, const QGLFormat& f, QPaintDevice* paintDevice, + int bufDepth, bool onlyFBConfig = false) +{ + int i = 0; + spec[i++] = GLX_LEVEL; + spec[i++] = f.plane(); + const QX11Info *xinfo = qt_x11Info(paintDevice); + bool useFBConfig = onlyFBConfig; + +#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX) + /* + HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. + Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. + */ + QWidget* widget = 0; + if (paintDevice->devType() == QInternal::Widget) + widget = static_cast(paintDevice); + + // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual + if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender) + useFBConfig = true; +#endif + +#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) + static bool useTranspExt = false; + static bool useTranspExtChecked = false; + if (f.plane() && !useTranspExtChecked && paintDevice) { + QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); + useTranspExt = extensions.match("GLX_EXT_visual_info"); + //# (A bit simplistic; that could theoretically be a substring) + if (useTranspExt) { + QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); + useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround + if (useTranspExt) { + // bug workaround - some systems (eg. FireGL) refuses to return an overlay + // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if + // the implementation supports transparent overlays + int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, + f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, + XNone }; + XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec); + if (!vinf) { + useTranspExt = false; + } + } + } + + useTranspExtChecked = true; + } + if (f.plane() && useTranspExt && !useFBConfig) { + // Required to avoid non-transparent overlay visual(!) on some systems + spec[i++] = GLX_TRANSPARENT_TYPE_EXT; + spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; + } +#endif + +#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) + // GLX_RENDER_TYPE is only in glx >=1.3 + if (useFBConfig) { + spec[i++] = GLX_RENDER_TYPE; + spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + } +#endif + + if (f.doubleBuffer()) + spec[i++] = GLX_DOUBLEBUFFER; + if (useFBConfig) + spec[i++] = True; + if (f.depth()) { + spec[i++] = GLX_DEPTH_SIZE; + spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); + } + if (f.stereo()) { + spec[i++] = GLX_STEREO; + if (useFBConfig) + spec[i++] = True; + } + if (f.stencil()) { + spec[i++] = GLX_STENCIL_SIZE; + spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); + } + if (f.rgba()) { + if (!useFBConfig) + spec[i++] = GLX_RGBA; + spec[i++] = GLX_RED_SIZE; + spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); + spec[i++] = GLX_GREEN_SIZE; + spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); + spec[i++] = GLX_BLUE_SIZE; + spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); + if (f.alpha()) { + spec[i++] = GLX_ALPHA_SIZE; + spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); + } + if (f.accum()) { + spec[i++] = GLX_ACCUM_RED_SIZE; + spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); + spec[i++] = GLX_ACCUM_GREEN_SIZE; + spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); + spec[i++] = GLX_ACCUM_BLUE_SIZE; + spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); + if (f.alpha()) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; + spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); + } + } + } else { + spec[i++] = GLX_BUFFER_SIZE; + spec[i++] = bufDepth; + } + + if (f.sampleBuffers()) { + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = f.samples() == -1 ? 4 : f.samples(); + } + +#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) + if (useFBConfig) { + spec[i++] = GLX_DRAWABLE_TYPE; + switch(paintDevice->devType()) { + case QInternal::Pixmap: + spec[i++] = GLX_PIXMAP_BIT; + break; + case QInternal::Pbuffer: + spec[i++] = GLX_PBUFFER_BIT; + break; + default: + qWarning("QGLContext: Unknown paint device type %d", paintDevice->devType()); + // Fall-through & assume it's a window + case QInternal::Widget: + spec[i++] = GLX_WINDOW_BIT; + break; + }; + } +#endif + + spec[i] = XNone; + return useFBConfig; +} + /***************************************************************************** QGLContext UNIX/GLX-specific code *****************************************************************************/ @@ -606,143 +748,8 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) { Q_D(QGLContext); int spec[45]; - int i = 0; - spec[i++] = GLX_LEVEL; - spec[i++] = f.plane(); const QX11Info *xinfo = qt_x11Info(d->paintDevice); - bool useFBConfig = false; - -#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX) - /* - HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. - Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. - */ - QWidget* widget = 0; - if (d->paintDevice->devType() == QInternal::Widget) - widget = static_cast(d->paintDevice); - - // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual - if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender) - useFBConfig = true; -#endif - -#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) - static bool useTranspExt = false; - static bool useTranspExtChecked = false; - if (f.plane() && !useTranspExtChecked && d->paintDevice) { - QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); - useTranspExt = extensions.match("GLX_EXT_visual_info"); - //# (A bit simplistic; that could theoretically be a substring) - if (useTranspExt) { - QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); - useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround - if (useTranspExt) { - // bug workaround - some systems (eg. FireGL) refuses to return an overlay - // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if - // the implementation supports transparent overlays - int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, - f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, - XNone }; - XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec); - if (!vinf) { - useTranspExt = false; - } - } - } - - useTranspExtChecked = true; - } - if (f.plane() && useTranspExt && !useFBConfig) { - // Required to avoid non-transparent overlay visual(!) on some systems - spec[i++] = GLX_TRANSPARENT_TYPE_EXT; - spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; - } -#endif - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - // GLX_RENDER_TYPE is only in glx >=1.3 - if (useFBConfig) { - spec[i++] = GLX_RENDER_TYPE; - spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - } -#endif - - if (f.doubleBuffer()) - spec[i++] = GLX_DOUBLEBUFFER; - if (useFBConfig) - spec[i++] = True; - if (f.depth()) { - spec[i++] = GLX_DEPTH_SIZE; - spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); - } - if (f.stereo()) { - spec[i++] = GLX_STEREO; - if (useFBConfig) - spec[i++] = True; - } - if (f.stencil()) { - spec[i++] = GLX_STENCIL_SIZE; - spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); - } - if (f.rgba()) { - if (!useFBConfig) - spec[i++] = GLX_RGBA; - spec[i++] = GLX_RED_SIZE; - spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); - spec[i++] = GLX_GREEN_SIZE; - spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); - spec[i++] = GLX_BLUE_SIZE; - spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ALPHA_SIZE; - spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); - } - if (f.accum()) { - spec[i++] = GLX_ACCUM_RED_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_GREEN_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - spec[i++] = GLX_ACCUM_BLUE_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - if (f.alpha()) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; - spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); - } - } - } else { - spec[i++] = GLX_BUFFER_SIZE; - spec[i++] = bufDepth; - } - - if (f.sampleBuffers()) { - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = f.samples() == -1 ? 4 : f.samples(); - } - -#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) - if (useFBConfig) { - spec[i++] = GLX_DRAWABLE_TYPE; - switch(d->paintDevice->devType()) { - case QInternal::Pixmap: - spec[i++] = GLX_PIXMAP_BIT; - break; - case QInternal::Pbuffer: - spec[i++] = GLX_PBUFFER_BIT; - break; - default: - qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType()); - // Fall-through & assume it's a window - case QInternal::Widget: - spec[i++] = GLX_WINDOW_BIT; - break; - }; - } -#endif - - spec[i] = XNone; - + bool useFBConfig = buildSpec(spec, f, d->paintDevice, bufDepth, false); XVisualInfo* chosenVisualInfo = 0; @@ -755,7 +762,7 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) if (!configs) break; // fallback to trying glXChooseVisual - for (i = 0; i < configCount; ++i) { + for (int i = 0; i < configCount; ++i) { XVisualInfo* vi; vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]); if (!vi) -- cgit v0.12 From d6c1894772ffd0c1ef2c4fd2c7469328dbbf9fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Riku=20Palom=C3=A4ki?= Date: Mon, 7 Jun 2010 12:18:24 +0200 Subject: Use the new OpenGL 3.* context/profile if asked with X11/GLX. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 609 Reviewed-by: Samuel Rødal --- src/opengl/qgl_x11.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index a6b0fae..9c1f537 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -115,6 +115,20 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd); #define GLX_FRONT_LEFT_EXT 0x20DE #endif +#ifndef GLX_ARB_create_context +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#endif + +#ifndef GLX_ARB_create_context_profile +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#endif + /* The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext() and GLX (not Windows). If the application can't find any sharable @@ -635,21 +649,70 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) shareContext = 0; } + const int major = d->reqFormat.majorVersion(); + const int minor = d->reqFormat.minorVersion(); + const int profile = d->reqFormat.profile() == QGLFormat::CompatibilityProfile + ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB + : GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + d->cx = 0; - if (shareContext) { + + if ((major == 3 && minor >= 2) || major > 3) { + QGLTemporaryContext *tmpContext = 0; + if (!QGLContext::currentContext()) + tmpContext = new QGLTemporaryContext; + + int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major, + GLX_CONTEXT_MINOR_VERSION_ARB, minor, + GLX_CONTEXT_PROFILE_MASK_ARB, profile, + 0 }; + + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = + (PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB"); + + if (glXCreateContextAttribs) { + int spec[45]; + glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BUFFER_SIZE, &res); + buildSpec(spec, format(), d->paintDevice, res, true); + + GLXFBConfig *configs; + int configCount = 0; + configs = glXChooseFBConfig(disp, xinfo->screen(), spec, &configCount); + + if (configs && configCount > 0) { + d->cx = glXCreateContextAttribs(disp, configs[0], + shareContext ? (GLXContext)shareContext->d_func()->cx : 0, direct, attributes); + if (!d->cx && shareContext) { + shareContext = 0; + d->cx = glXCreateContextAttribs(disp, configs[0], 0, direct, attributes); + } + d->screen = ((XVisualInfo*)d->vi)->screen; + } + XFree(configs); + } else { + qWarning("QGLContext::chooseContext(): OpenGL %d.%d is not supported", major, minor); + } + + if (tmpContext) + delete tmpContext; + } + if (!d->cx && shareContext) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, (GLXContext)shareContext->d_func()->cx, direct); d->screen = ((XVisualInfo*)d->vi)->screen; - if (d->cx) { - QGLContext *share = const_cast(shareContext); - d->sharing = true; - share->d_func()->sharing = true; - } } if (!d->cx) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct); d->screen = ((XVisualInfo*)d->vi)->screen; + shareContext = 0; + } + + if (shareContext && d->cx) { + QGLContext *share = const_cast(shareContext); + d->sharing = true; + share->d_func()->sharing = true; } + if (!d->cx) return false; d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx)); -- cgit v0.12 From 679611c26c5b7ecf63b4ed490803073a96ce9d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 7 Jun 2010 12:16:41 +0200 Subject: Protected call to glXChooseFBConfig with appropriate defines. Reviewed-by: Trond --- src/opengl/qgl_x11.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 9c1f537..8194c588 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -657,6 +657,11 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->cx = 0; +#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) + /* + HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions. + Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented. + */ if ((major == 3 && minor >= 2) || major > 3) { QGLTemporaryContext *tmpContext = 0; if (!QGLContext::currentContext()) @@ -696,6 +701,12 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) if (tmpContext) delete tmpContext; } +#else + Q_UNUSED(major); + Q_UNUSED(minor); + Q_UNUSED(profile); +#endif + if (!d->cx && shareContext) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, (GLXContext)shareContext->d_func()->cx, direct); -- cgit v0.12 From 95fcfccf3c6d9d102fa1c5481e6be52a21749af6 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 7 Jun 2010 16:51:18 +0200 Subject: Doc: Added details of a system proxy limitation on Windows. Reviewed-by: Markus Goetz Task-number: QTBUG-10106 --- src/network/kernel/qnetworkproxy.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index ada9381..bc5a025 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -1138,6 +1138,20 @@ void QNetworkProxyQuery::setUrl(const QUrl &url) multiple connections, such as QNetworkAccessManager. When set on such object, the factory will be queried for sockets created by that framework only. + + \section1 System Proxies + + You can configure a factory to use the system proxy's settings. + Call the setUseSystemConfiguration() function with true to enable + this behavior, or false to disable it. + + Similarly, you can use a factory to make queries directly to the + system proxy by calling its systemProxyForQuery() function. + + \warning Depending on the configuration of the user's system, the + use of system proxy features on certain platforms may be subject + to limitations. The systemProxyForQuery() documentation contains a + list of these limitations for those platforms that are affected. */ /*! @@ -1159,17 +1173,20 @@ QNetworkProxyFactory::~QNetworkProxyFactory() /*! + \since 4.6 + Enables the use of the platform-specific proxy settings, and only those. See systemProxyForQuery() for more information. Internally, this method (when called with \a enable set to true) sets an application-wide proxy factory. For this reason, this method - is mutually exclusive with setApplicationProxyFactory: calling - setApplicationProxyFactory overrides the use of the system-wide proxy, - and calling setUseSystemConfiguration overrides any + is mutually exclusive with setApplicationProxyFactory(): calling + setApplicationProxyFactory() overrides the use of the system-wide proxy, + and calling setUseSystemConfiguration() overrides any application proxy or proxy factory that was previously set. - \since 4.6 + \note See the systemProxyForQuery() documentation for a list of + limitations related to the use of system proxies. */ void QNetworkProxyFactory::setUseSystemConfiguration(bool enable) { @@ -1264,8 +1281,13 @@ void QNetworkProxyFactory::setApplicationProxyFactory(QNetworkProxyFactory *fact function. Future versions of Qt may lift some of the limitations listed here. - On MacOS X, this function will ignore the Proxy Auto Configuration + \list + \o On MacOS X, this function will ignore the Proxy Auto Configuration settings, since it cannot execute the associated ECMAScript code. + + \o On Windows platforms, this function may take several seconds to + execute depending on the configuration of the user's system. + \endlist */ /*! -- cgit v0.12 From bbf78c9b422c4c7eda7e7fce067578c75d3bc9b3 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Mon, 7 Jun 2010 17:57:56 +0200 Subject: Allow to build Qt in static with mingw Some functions were marked with Q_DECL_IMPORT where they should just be Q_CORE_EXPORT. The reason is that this macro is expanded to nothing in case of static builds whereas Q_DECL_IMPORT isn't (it is a dllimport). That leads the linker to try to import it and it shouldn't. Task-number: QTBUG-10791 Reviewed-by: gabi --- src/declarative/qml/parser/qdeclarativejslexer.cpp | 2 +- src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qwhatsthis.cpp | 2 +- src/script/api/qscriptengine.cpp | 4 +--- src/script/parser/qscriptlexer.cpp | 2 +- src/xmlpatterns/data/qdecimal_p.h | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 975ad4c..fcaaece 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -57,7 +57,7 @@ #include QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern double qstrtod(const char *s00, char const **se, bool *ok); +Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); QT_END_NAMESPACE QT_QML_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index c9a3e8b..02d732b 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -146,7 +146,7 @@ static void initResources() QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern void qt_call_post_routines(); +Q_CORE_EXPORT void qt_call_post_routines(); int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index 6181b62..ff4641e 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -143,7 +143,7 @@ QT_BEGIN_NAMESPACE \sa QToolTip */ -Q_DECL_IMPORT extern void qDeleteInEventHandler(QObject *o); +Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o); class QWhatsThat : public QWidget { diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 86915bb..f02ea52 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1525,7 +1525,7 @@ void QScriptEnginePrivate::detachAllRegisteredScriptStrings() #ifndef QT_NO_REGEXP -Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); +Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp ®exp) { @@ -2020,8 +2020,6 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, #ifndef QT_NO_REGEXP -Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); - /*! Creates a QtScript object of class RegExp with the given \a regexp. diff --git a/src/script/parser/qscriptlexer.cpp b/src/script/parser/qscriptlexer.cpp index ca64776..3ddc3aa 100644 --- a/src/script/parser/qscriptlexer.cpp +++ b/src/script/parser/qscriptlexer.cpp @@ -31,7 +31,7 @@ QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern double qstrtod(const char *s00, char const **se, bool *ok); +Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); #define shiftWindowsLineBreak() \ do { \ diff --git a/src/xmlpatterns/data/qdecimal_p.h b/src/xmlpatterns/data/qdecimal_p.h index d17b647..2a5e0b3 100644 --- a/src/xmlpatterns/data/qdecimal_p.h +++ b/src/xmlpatterns/data/qdecimal_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE /** * Defined in QtCore's qlocale.cpp. */ -Q_DECL_IMPORT extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp); +Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp); namespace QPatternist { -- cgit v0.12 From d0e209747a31c3e06f82e831fc3695986e12e9cd Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Tue, 8 Jun 2010 12:07:04 +0200 Subject: prefer QElapsedTimer over QTime Merge-request: 678 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qeventloop.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 628afa7..c19f718 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -43,7 +43,7 @@ #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" -#include "qdatetime.h" +#include "qelapsedtimer.h" #include "qobject_p.h" #include @@ -247,7 +247,7 @@ void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime) if (!d->threadData->eventDispatcher) return; - QTime start; + QElapsedTimer start; start.start(); if (flags & DeferredDeletion) QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); -- cgit v0.12 From a0dc2b8344e2a24d78d5648bfb0f9f76bca37ca9 Mon Sep 17 00:00:00 2001 From: Gordon Schumacher Date: Tue, 8 Jun 2010 13:37:30 +0200 Subject: QVarLenghtArray: Add typedefs for stl compatibility. Merge-request: 599 Reviewed-by: Olivier Goffart --- src/corelib/tools/qvarlengtharray.h | 7 +++++ src/corelib/tools/qvarlengtharray.qdoc | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index bfede94..4a6bb4b 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -127,6 +127,13 @@ public: inline T *data() { return ptr; } inline const T *data() const { return ptr; } inline const T * constData() const { return ptr; } + typedef int size_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef qptrdiff difference_type; private: friend class QPodList; diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index 38901e5..ef2dc58 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -302,3 +302,52 @@ \a defaultValue. */ +/*! + \typedef QVarLengthArray::size_type + \since 4.7 + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::value_type + \since 4.7 + + Typedef for T. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::difference_type + \since 4.7 + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::pointer + \since 4.7 + + Typedef for T *. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::const_pointer + \since 4.7 + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::reference + \since 4.7 + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::const_reference + \since 4.7 + + Typedef for const T &. Provided for STL compatibility. +*/ + -- cgit v0.12 From a1f7df67056c24b8b23393401953859f6e59417e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 2 Jun 2010 11:07:48 +0200 Subject: small optimisation Don't use fromLocal8Bit() when comparing an ascii string to a QString, use QLatin1String. --- src/declarative/qml/qdeclarativeimport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index c658a31..a2e3831 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -823,7 +823,7 @@ void QDeclarativeImportDatabase::addPluginPath(const QString& path) qDebug() << "QDeclarativeImportDatabase::addPluginPath" << path; QUrl url = QUrl(path); - if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file")) { QDir dir = QDir(path); filePluginPath.prepend(dir.canonicalPath()); } else { @@ -842,7 +842,7 @@ void QDeclarativeImportDatabase::addImportPath(const QString& path) QUrl url = QUrl(path); QString cPath; - if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file")) { QDir dir = QDir(path); cPath = dir.canonicalPath(); } else { -- cgit v0.12 From 17427887a2847acc74c61424e812aca0fea23226 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:03:52 +0200 Subject: Fix QString::isRightToLeft() to conform with Unicode Bidi algorithm Rules P2 and P3 demand us to ignore the LRE/LRO/RLE/RLO characters for determining the paragraph direction. Task-Number: Part of QT-3292 --- src/corelib/tools/qstring.cpp | 20 +++++++++++--------- src/corelib/tools/qstring.h | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 1172a7b..1d5fab3 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -6916,20 +6916,23 @@ void QString::updateProperties() const p++; } - p = d->data; - d->righttoleft = false; + d->righttoleft = isRightToLeft(); + d->clean = true; +} + +bool QString::isRightToLeft() const +{ + ushort *p = d->data; + const ushort * const end = p + d->size; + bool righttoleft = false; while (p < end) { switch(QChar::direction(*p)) { case QChar::DirL: - case QChar::DirLRO: - case QChar::DirLRE: goto end; case QChar::DirR: case QChar::DirAL: - case QChar::DirRLO: - case QChar::DirRLE: - d->righttoleft = true; + righttoleft = true; goto end; default: break; @@ -6937,8 +6940,7 @@ void QString::updateProperties() const ++p; } end: - d->clean = true; - return; + return righttoleft; } /*! \fn bool QString::isSimpleText() const diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a1c4e77..e52f59f 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -590,7 +590,7 @@ public: #endif bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; } - bool isRightToLeft() const { if (!d->clean) updateProperties(); return d->righttoleft; } + bool isRightToLeft() const; QString(int size, Qt::Initialization); -- cgit v0.12 From 0b06274858cab9cedace8e684d16664e49d5f814 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:10:08 +0200 Subject: Introduce LayoutDirection Qt::LayoutDirectionAuto Extend the enum to contains a value that can be used to hint that we would like to determine the text direction from the content. Reviewed-by: Simon Hausmann --- src/corelib/global/qnamespace.h | 3 ++- src/corelib/global/qnamespace.qdoc | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index a9c56f6..a12e121 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1561,7 +1561,8 @@ public: enum LayoutDirection { LeftToRight, - RightToLeft + RightToLeft, + LayoutDirectionAuto }; enum AnchorPoint { diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 7eae3a5..abbc03e 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2572,15 +2572,23 @@ /*! \enum Qt::LayoutDirection - Specifies the direction of Qt's layouts: + Specifies the direction of Qt's layouts and text handling. \value LeftToRight Left-to-right layout. \value RightToLeft Right-to-left layout. + \value LayoutDirectionAuto Automatic layout. Right-to-left layouts are necessary for certain languages, notably Arabic and Hebrew. - \sa QApplication::setLayoutDirection(), QWidget::setLayoutDirection() + LayoutDirectionAuto serves two purposes. When used in conjunction with widgets and layouts, it + will imply to use the layout direction set on the parent widget or QApplication. This + has the same effect as QWidget::unsetLayoutDirection(). + + When LayoutDirectoinAuto is used in conjunction with text layouting, it will imply that the text + directionality is determined from the content of the string to be layouted. + + \sa QApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft() */ /*! -- cgit v0.12 From 312c028d44a80f5d6029eb166a0de731f8452525 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:11:50 +0200 Subject: Handle setting the layoutDirection to Qt::LayoutDirectionAuto Setting it to LayoutAuto will be ignored on an application level (only LeftToRight or RightToLeft are valid). On a widget level is does the same as calling unsetLayoutDirection(). Reviewed-by: Simon Hausmann --- src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qwidget.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 02d732b..52767b8 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3544,7 +3544,7 @@ int QApplication::startDragDistance() void QApplication::setLayoutDirection(Qt::LayoutDirection direction) { - if (layout_direction == direction) + if (layout_direction == direction || direction == Qt::LayoutDirectionAuto) return; layout_direction = direction; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 895c85d..ab84a54 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4828,6 +4828,11 @@ void QWidget::setLayoutDirection(Qt::LayoutDirection direction) { Q_D(QWidget); + if (direction == Qt::LayoutDirectionAuto) { + unsetLayoutDirection(); + return; + } + setAttribute(Qt::WA_SetLayoutDirection); d->setLayoutDirection_helper(direction); } -- cgit v0.12 From 6287977849ff5cab64a944fb0590d306a79f3637 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:15:56 +0200 Subject: The default text direction for QTextOption is Qt::LayoutDirectionAuto The change is binary compatible, even though the changed bitfield is being accessed inline. The reason is that we extend by a bit that has previously been initialized to 0. bitordering will ensure that old code reads Qt::LayoutAuto as Qt::LeftToRight. Task-number: Part of QT-3292 Reviewed-by: Simon Hausmann --- src/gui/text/qtextoption.cpp | 2 +- src/gui/text/qtextoption.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index c1e254c..3b02ebe 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -65,7 +65,7 @@ QTextOption::QTextOption() tab(-1), d(0) { - direction = QApplication::layoutDirection(); + direction = Qt::LayoutDirectionAuto; } /*! diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h index 1381ed1..fa8c6f2 100644 --- a/src/gui/text/qtextoption.h +++ b/src/gui/text/qtextoption.h @@ -134,8 +134,8 @@ private: uint align : 8; uint wordWrap : 4; uint design : 1; - uint direction : 1; - uint unused : 19; + uint direction : 2; + uint unused : 18; uint f; qreal tab; QTextOptionPrivate *d; -- cgit v0.12 From 1533e7251d1dc4318b87ec799f0367f5fca0b092 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:20:23 +0200 Subject: Correct BiDi behavior of QLineEdit * LayoutDirectionChange event doesn't affect the text anymore. * Default text direction is determined from string * Qt::Key_Direction_L/R forces the layout direction Task-number: Part of Qt-3292 Reviewed-by: Simon Hausmann --- src/gui/widgets/qlinecontrol_p.h | 8 ++++++-- src/gui/widgets/qlineedit.cpp | 5 +---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 5da1831..b419adf 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -78,7 +78,7 @@ class Q_GUI_EXPORT QLineControl : public QObject public: QLineControl(const QString &txt = QString()) - : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LeftToRight), + : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LayoutDirectionAuto), m_hideCursor(false), m_separator(0), m_readOnly(0), m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), @@ -272,7 +272,11 @@ public: QChar passwordCharacter() const { return m_passwordCharacter; } void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); } - Qt::LayoutDirection layoutDirection() const { return m_layoutDirection; } + Qt::LayoutDirection layoutDirection() const { + if (m_layoutDirection == Qt::LayoutDirectionAuto) + return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + return m_layoutDirection; + } void setLayoutDirection(Qt::LayoutDirection direction) { if (direction != m_layoutDirection) { diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index c1c4abf..1bffde1 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1860,7 +1860,7 @@ void QLineEdit::paintEvent(QPaintEvent *) p.setClipRect(r); QFontMetrics fm = fontMetrics(); - Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment)); + Qt::Alignment va = QStyle::visualAlignment(d->control->layoutDirection(), QFlag(d->alignment)); switch (va & Qt::AlignVertical_Mask) { case Qt::AlignBottom: d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin; @@ -2161,9 +2161,6 @@ void QLineEdit::changeEvent(QEvent *ev) } update(); break; - case QEvent::LayoutDirectionChange: - d->control->setLayoutDirection(layoutDirection()); - break; default: break; } -- cgit v0.12 From 906a68a59c242744568afb12aba1ccc474bf6217 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:40:05 +0200 Subject: LayoutDirectionAuto is the default layout direction for QPainter Don't retrieve the layout direction from QWidget or QApplication anymore. Respect if somebody explicitly sets the direction with setLayoutDirection(). Task-number: Part of QT-3292 Reviewed-by: Simon Hausmann --- src/gui/painting/qpainter.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 97f754d..e8c4599 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1564,7 +1564,6 @@ void QPainter::initFrom(const QWidget *widget) d->engine->setDirty(QPaintEngine::DirtyBrush); d->engine->setDirty(QPaintEngine::DirtyFont); } - d->state->layoutDirection = widget->layoutDirection(); } @@ -1874,7 +1873,7 @@ bool QPainter::begin(QPaintDevice *pd) QWidget *widget = static_cast(d->original_device); initFrom(widget); } else { - d->state->layoutDirection = QApplication::layoutDirection(); + d->state->layoutDirection = Qt::LayoutDirectionAuto; // make sure we have a font compatible with the paintdevice d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device()); } @@ -8056,7 +8055,10 @@ start_lengthVariant: Sets the layout direction used by the painter when drawing text, to the specified \a direction. - \sa layoutDirection(), drawText(), {QPainter#Settings}{Settings} + The default is Qt::LayoutDirectionAuto, which will implicitly determine the + direction from the text drawn. + + \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings} */ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) { @@ -8068,12 +8070,12 @@ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) /*! Returns the layout direction used by the painter when drawing text. - \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} + \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} */ Qt::LayoutDirection QPainter::layoutDirection() const { Q_D(const QPainter); - return d->state ? d->state->layoutDirection : Qt::LeftToRight; + return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto; } QPainterState::QPainterState(const QPainterState *s) -- cgit v0.12 From 7358af18674f6dbd9abf67f6e02809f43e2cfc3e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 21:45:25 +0200 Subject: Make sure LayoutDirectionAuto is the default text direction QTextFormat::intProperty requires a small change to ensure we return the right value for layoutDirection. No need to change QTextFormat::property, as an invalid QVariant will be returned if the layoutDirection is not explicitly set. Reviewed-by: Simon Hausmann --- src/gui/text/qtextformat.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 140cf43..46db253 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -900,11 +900,14 @@ bool QTextFormat::boolProperty(int propertyId) const */ int QTextFormat::intProperty(int propertyId) const { + // required, since the default layout direction has to be LayoutDirectionAuto, which is not integer 0 + int def = (propertyId == QTextFormat::LayoutDirection) ? int(Qt::LayoutDirectionAuto) : 0; + if (!d) - return 0; + return def; const QVariant prop = d->property(propertyId); if (prop.userType() != QVariant::Int) - return 0; + return def; return prop.toInt(); } -- cgit v0.12 From fee7f7d67f780b798a63994a1125f9ca3ade1bd3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 22:05:44 +0200 Subject: Add QTextBlock::textDirection() The method returns the resolved text direction for the block. It implements P1-P3 of the Unicode bidi algorithm. Task-number: Part of Qt-3292 Reviewed-by: Simon Hausmann --- src/gui/text/qtextobject.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ src/gui/text/qtextobject.h | 2 ++ 2 files changed, 45 insertions(+) diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 088eb98..f386871 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1140,6 +1140,49 @@ int QTextBlock::charFormatIndex() const } /*! + \since 4.7 + + Returns the resolved text direction. + + If the block has no explicit direction set, it will resolve the + direction from the blocks content. Returns either Qt::LeftToRight + or Qt::RightToLeft. + + \sa QTextBlock::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection +*/ +Qt::LayoutDirection QTextBlock::textDirection() const +{ + Qt::LayoutDirection dir = blockFormat().layoutDirection(); + if (dir != Qt::LayoutDirectionAuto) + return dir; + + const QString buffer = p->buffer(); + + const int pos = position(); + QTextDocumentPrivate::FragmentIterator it = p->find(pos); + QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char + for (; it != end; ++it) { + const QTextFragmentData * const frag = it.value(); + const QChar *p = buffer.constData() + frag->stringPosition; + const QChar * const end = p + frag->size_array[0]; + while (p < end) { + switch(QChar::direction(p->unicode())) + { + case QChar::DirL: + return Qt::LeftToRight; + case QChar::DirR: + case QChar::DirAL: + return Qt::RightToLeft; + default: + break; + } + ++p; + } + } + return Qt::LeftToRight; +} + +/*! Returns the block's contents as plain text. \sa length() charFormat() blockFormat() diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 67f67d8..a573a26 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -221,6 +221,8 @@ public: QTextCharFormat charFormat() const; int charFormatIndex() const; + Qt::LayoutDirection textDirection() const; + QString text() const; const QTextDocument *document() const; -- cgit v0.12 From 7b0f00e8c8a4ec541dba510debcf786c7edb7fae Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 22:11:57 +0200 Subject: Use the textDirection() of blocks correctly. Task-number: Part of QT-3292 Reviewed-by: Simon Hausmann --- src/gui/text/qtextcursor.cpp | 2 +- src/gui/text/qtextdocument.cpp | 9 +++------ src/gui/text/qtextdocumentlayout.cpp | 8 ++------ src/gui/text/qtextlist.cpp | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index d6ac3aa..23849bc 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -362,7 +362,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor QTextBlock blockIt = block(); if (op >= QTextCursor::Left && op <= QTextCursor::WordRight - && blockIt.blockFormat().layoutDirection() == Qt::RightToLeft) { + && blockIt.textDirection() == Qt::RightToLeft) { if (op == QTextCursor::Left) op = QTextCursor::NextCharacter; else if (op == QTextCursor::Right) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c7a9756..48aee8f 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2496,13 +2496,10 @@ void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block) QTextBlockFormat format = block.blockFormat(); emitAlignment(format.alignment()); - Qt::LayoutDirection dir = format.layoutDirection(); - if (dir == Qt::LeftToRight) { - // assume default to not bloat the html too much - // html += QLatin1String(" dir='ltr'"); - } else { + // assume default to not bloat the html too much + // html += QLatin1String(" dir='ltr'"); + if (block.textDirection() == Qt::RightToLeft) html += QLatin1String(" dir='rtl'"); - } QLatin1String style(" style=\""); html += style; diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index eeb66ce..ff14490 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1369,9 +1369,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p QTextLine firstLine = layout->lineAt(0); Q_ASSERT(firstLine.isValid()); QPointF pos = (offset + layout->position()).toPoint(); - Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); - if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) - dir = blockFormat.layoutDirection(); + Qt::LayoutDirection dir = bl.textDirection(); { QRectF textRect = firstLine.naturalTextRect(); pos += textRect.topLeft().toPoint(); @@ -2530,9 +2528,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi //QTextFrameData *fd = data(layoutStruct->frame); - Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); - if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) - dir = blockFormat.layoutDirection(); + Qt::LayoutDirection dir = bl.textDirection(); QFixed extraMargin; if (docPrivate->defaultTextOption.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) { diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index 2986ee7..a0ff520 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -262,7 +262,7 @@ QString QTextList::itemText(const QTextBlock &blockIt) const default: Q_ASSERT(false); } - if (blockFormat.layoutDirection() == Qt::RightToLeft) + if (blockIt.textDirection() == Qt::RightToLeft) return result.prepend(QLatin1Char('.')); return result + QLatin1Char('.'); } -- cgit v0.12 From 2ae3d17883c0b24f7f4a5a1ea763105a2c8a7342 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 22:12:56 +0200 Subject: correctly initialize the bidi level in the text engine If the text options doesn't specify the layout direction, determine it from the content. Reviewed-by: Simon Hausmann --- src/gui/text/qtextengine.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 3486264..191508c 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1404,7 +1404,20 @@ void QTextEngine::itemize() const #else bool ignore = ignoreBidi; #endif - if (!ignore && option.textDirection() == Qt::LeftToRight) { + + bool rtl = false; + switch (option.textDirection()) { + case Qt::LeftToRight: + break; + case Qt::RightToLeft: + rtl = true; + break; + case Qt::LayoutDirectionAuto: + rtl = layoutData->string.isRightToLeft(); + break; + } + + if (!ignore && !rtl) { ignore = true; const QChar *start = layoutData->string.unicode(); const QChar * const end = start + length; @@ -1420,7 +1433,7 @@ void QTextEngine::itemize() const QVarLengthArray scriptAnalysis(length); QScriptAnalysis *analysis = scriptAnalysis.data(); - QBidiControl control(option.textDirection() == Qt::RightToLeft); + QBidiControl control(rtl); if (ignore) { memset(analysis, 0, length*sizeof(QScriptAnalysis)); -- cgit v0.12 From b69e592b2b8fb3eae75c112e491e3ed90fc0248a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 23:21:59 +0200 Subject: For an empty line edit the cursor position is depending on input language Ensure the cursor is on the right if the keyboard layout is for a right to left language. Task-number: Part of Qt-3292 Reviewed-by: Simon Hausmann --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 1 - src/gui/widgets/qlinecontrol_p.h | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 1202101..8d320f4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1356,7 +1356,6 @@ void QDeclarativeTextInputPrivate::init() Q_Q(QDeclarativeTextInput); control->setCursorWidth(1); control->setPasswordCharacter(QLatin1Char('*')); - control->setLayoutDirection(Qt::LeftToRight); q->setSmooth(smooth); q->setAcceptedMouseButtons(Qt::LeftButton); q->setFlag(QGraphicsItem::ItemHasNoContents, false); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index b419adf..7068f62 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -273,8 +273,11 @@ public: void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); } Qt::LayoutDirection layoutDirection() const { - if (m_layoutDirection == Qt::LayoutDirectionAuto) + if (m_layoutDirection == Qt::LayoutDirectionAuto) { + if (m_text.isEmpty()) + return QApplication::keyboardInputDirection(); return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + } return m_layoutDirection; } void setLayoutDirection(Qt::LayoutDirection direction) -- cgit v0.12 From 726607baf707318de6f685573553d22df4966f61 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 23:23:42 +0200 Subject: consistent handling of directionality in QTextLayout Make sure we use the same method to determine RTL/LTR for the layout everywhere. Task-number: Part of QT-3292 Reviewed-by: Simon Hausmann --- src/gui/text/qtextengine.cpp | 31 +++++++++++++++++++------------ src/gui/text/qtextengine_p.h | 1 + src/gui/text/qtextlayout.cpp | 6 +++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 191508c..ac1fffd 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1405,17 +1405,7 @@ void QTextEngine::itemize() const bool ignore = ignoreBidi; #endif - bool rtl = false; - switch (option.textDirection()) { - case Qt::LeftToRight: - break; - case Qt::RightToLeft: - rtl = true; - break; - case Qt::LayoutDirectionAuto: - rtl = layoutData->string.isRightToLeft(); - break; - } + bool rtl = isRightToLeft(); if (!ignore && !rtl) { ignore = true; @@ -1528,6 +1518,23 @@ void QTextEngine::itemize() const resolveAdditionalFormats(); } +bool QTextEngine::isRightToLeft() const +{ + switch (option.textDirection()) { + case Qt::LeftToRight: + return false; + case Qt::RightToLeft: + return true; + default: + break; + } + // this places the cursor in the right position depending on the keyboard layout + if (layoutData->string.isEmpty()) + return QApplication::keyboardInputDirection() == Qt::RightToLeft; + return layoutData->string.isRightToLeft(); +} + + int QTextEngine::findItem(int strPos) const { itemize(); @@ -2524,7 +2531,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const QList tabArray = option.tabs(); if (!tabArray.isEmpty()) { - if (option.textDirection() == Qt::RightToLeft) { // rebase the tabArray positions. + if (isRightToLeft()) { // rebase the tabArray positions. QList newTabs; QList::Iterator iter = tabArray.begin(); while(iter != tabArray.end()) { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 00b1392..908a0ec 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -458,6 +458,7 @@ public: void validate() const; void itemize() const; + bool isRightToLeft() const; static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder); const HB_CharAttributes *attributes() const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f5e252c..ddf9411 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -69,7 +69,7 @@ static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line if (!line.hasTrailingSpaces || (eng->option.flags() & QTextOption::IncludeTrailingSpaces) || !(eng->option.alignment() & Qt::AlignRight) - || (eng->option.textDirection() != Qt::RightToLeft)) + || !eng->isRightToLeft()) return QFixed(); int pos = line.length; @@ -86,7 +86,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) // if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned. if (!line.justified && line.width != QFIXED_MAX) { int align = eng->option.alignment(); - if (align & Qt::AlignJustify && eng->option.textDirection() == Qt::RightToLeft) + if (align & Qt::AlignJustify && eng->isRightToLeft()) align = Qt::AlignRight; if (align & Qt::AlignRight) x = line.width - (line.textAdvance + leadingSpaceWidth(eng, line)); @@ -1337,7 +1337,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition int itm = d->findItem(cursorPosition - 1); QFixed base = sl.base(); QFixed descent = sl.descent; - bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft); + bool rightToLeft = d->isRightToLeft(); if (itm >= 0) { const QScriptItem &si = d->layoutData->items.at(itm); if (si.ascent > 0) -- cgit v0.12 From 424735f91dbf5847640aca4011a309dbef7b1e31 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 9 Jun 2010 23:00:20 +0200 Subject: Add a isWrittenRightToLeft() method to QLocale. This helps us keeping the code in the key mappers that detect keyboard changes simple and is useful for other cases as well. Task-number: Part of QT-3292 Reviewed-by: Simon Hausmann --- src/corelib/tools/qlocale.cpp | 19 +++++++++++++++++++ src/corelib/tools/qlocale.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index c000dc8..8f50f2e 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3478,6 +3478,25 @@ QLocale::MeasurementSystem QLocale::measurementSystem() const } /*! + \since 4.7 + + Returns true if the language is written right to left. +*/ +bool QLocale::isWrittenRightToLeft() const +{ + Language lang = language(); + if (lang == QLocale::Arabic || + lang == QLocale::Hebrew || + lang == QLocale::Persian || + lang == QLocale::Urdu || + lang == QLocale::Syriac) + return true; + + return false; +} + + +/*! \since 4.5 Returns the localized name of the "AM" suffix for times specified using diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index f2fd892..f8b5c55 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -666,6 +666,8 @@ public: MeasurementSystem measurementSystem() const; + bool isWrittenRightToLeft() const; + inline bool operator==(const QLocale &other) const; inline bool operator!=(const QLocale &other) const; -- cgit v0.12 From da603c7c80ea14df18790ae77f5de82880307650 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 5 Jun 2010 23:15:16 +0200 Subject: Fixed some bugs in detection of keyboard directionality The mapping table on X11 had a few bugs. Implemented rudimentary support on QWS and fixed a tiny issue on Mac. Reviewed-by: Simon Hausmann --- src/gui/inputmethod/qximinputcontext_x11.cpp | 14 +++----------- src/gui/kernel/qkeymapper_mac.cpp | 18 +----------------- src/gui/kernel/qkeymapper_qws.cpp | 2 +- src/gui/kernel/qkeymapper_x11.cpp | 21 ++++++--------------- src/gui/kernel/qkeymapper_x11_p.cpp | 14 +++++++------- 5 files changed, 18 insertions(+), 51 deletions(-) diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp index d048b36..88f8daf 100644 --- a/src/gui/inputmethod/qximinputcontext_x11.cpp +++ b/src/gui/inputmethod/qximinputcontext_x11.cpp @@ -346,10 +346,7 @@ static XFontSet getFontSet(const QFont &f) extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp #ifndef QT_NO_XKB -extern void q_getLocaleAndDirection(QLocale *locale, - Qt::LayoutDirection *direction, - const QByteArray &layoutName, - const QByteArray &variantName); +extern QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName); #endif QXIMInputContext::QXIMInputContext() @@ -407,17 +404,12 @@ QXIMInputContext::QXIMInputContext() QList layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(','); QList variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(','); for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) { - QLocale keyboardInputLocale; - Qt::LayoutDirection keyboardInputDirection; QByteArray variantName = variantNames.at(i); const int dashPos = variantName.indexOf("-"); if (dashPos >= 0) variantName.truncate(dashPos); - q_getLocaleAndDirection(&keyboardInputLocale, - &keyboardInputDirection, - layoutNames.at(i), - variantName); - if (keyboardInputDirection == Qt::RightToLeft) + QLocale keyboardInputLocale = q_getKeyboardLocale(layoutNames.at(i), variantName); + if (keyboardInputLocale.isWrittenRightToLeft()) qt_use_rtl_extensions = true; } } diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index a7145d4..885f5ba 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -672,23 +672,7 @@ QKeyMapperPrivate::updateKeyboard() #endif if (iso639Code) { keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); - QString monday = keyboardInputLocale.dayName(1); - bool rtl = false; - for (int i = 0; i < monday.length(); ++i) { - switch (monday.at(i).direction()) { - default: - break; - case QChar::DirR: - case QChar::DirAL: - case QChar::DirRLE: - case QChar::DirRLO: - rtl = true; - break; - } - if (rtl) - break; - } - keyboardInputDirection = rtl ? Qt::RightToLeft : Qt::LeftToRight; + keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; } else { keyboardInputLocale = QLocale::c(); keyboardInputDirection = Qt::LeftToRight; diff --git a/src/gui/kernel/qkeymapper_qws.cpp b/src/gui/kernel/qkeymapper_qws.cpp index 5b6b1c4..0e9f35a 100644 --- a/src/gui/kernel/qkeymapper_qws.cpp +++ b/src/gui/kernel/qkeymapper_qws.cpp @@ -52,7 +52,7 @@ QT_USE_NAMESPACE QKeyMapperPrivate::QKeyMapperPrivate() { keyboardInputLocale = QLocale::system(); - keyboardInputDirection = Qt::RightToLeft; + keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; } QKeyMapperPrivate::~QKeyMapperPrivate() diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index 807959c..f0d548c 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -80,22 +80,15 @@ QT_BEGIN_NAMESPACE (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF)) #endif -void q_getLocaleAndDirection(QLocale *locale, - Qt::LayoutDirection *direction, - const QByteArray &layoutName, - const QByteArray &variantName) +QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName) { int i = 0; while (xkbLayoutData[i].layout != 0) { - if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) { - *locale = QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country); - *direction = xkbLayoutData[i].direction; - return; - } + if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) + return QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country); ++i; } - *locale = QLocale::c(); - *direction = Qt::LeftToRight; + return QLocale::c(); } #endif // QT_NO_XKB @@ -523,10 +516,8 @@ void QKeyMapperPrivate::clearMappings() // if (keyboardLayoutName.isEmpty()) // qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ? - q_getLocaleAndDirection(&keyboardInputLocale, - &keyboardInputDirection, - layoutName, - variantName); + keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName); + keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; #if 0 qDebug() << "keyboard input locale =" diff --git a/src/gui/kernel/qkeymapper_x11_p.cpp b/src/gui/kernel/qkeymapper_x11_p.cpp index 20fcc86..6308973 100644 --- a/src/gui/kernel/qkeymapper_x11_p.cpp +++ b/src/gui/kernel/qkeymapper_x11_p.cpp @@ -271,13 +271,13 @@ static struct { // name = is:nodeadkeys, description = Iceland { "is", "nodeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland }, // name = il, description = Israel - { "il", "", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:lyx, description = Israel - { "il", "lyx", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "lyx", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:si1452, description = Israel - { "il", "si1452", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "si1452", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:phonetic, description = Israel - { "il", "phonetic", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "phonetic", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = it, description = Italy { "it", "", Qt::LeftToRight, QLocale::Italian, QLocale::Italy }, // name = it:nodeadkeys, description = Italy @@ -419,11 +419,11 @@ static struct { // name = ch:fr_sundeadkeys, description = Switzerland { "ch", "fr_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland }, // name = sy, description = Syria - { "sy", "", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = sy:syc, description = Syria - { "sy", "syc", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "syc", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = sy:syc_phonetic, description = Syria - { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = tj, description = Tajikistan { "tj", "", Qt::LeftToRight, QLocale::Tajik, QLocale::Tajikistan }, // name = lk, description = Sri Lanka -- cgit v0.12 From 1abf2d6dfafc71f73746b7e69e11e0c8152edb4a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 10 Jun 2010 00:05:07 +0200 Subject: Rename QLocale::isWrittenRightToLeft() to textDirection() This is more in line with the rest of Qt. Reviewed-by: Simon Hausmann --- src/corelib/tools/qlocale.cpp | 8 ++++---- src/corelib/tools/qlocale.h | 2 +- src/gui/inputmethod/qximinputcontext_x11.cpp | 2 +- src/gui/kernel/qkeymapper_mac.cpp | 2 +- src/gui/kernel/qkeymapper_qws.cpp | 2 +- src/gui/kernel/qkeymapper_x11.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 8f50f2e..a51ee81 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3480,9 +3480,9 @@ QLocale::MeasurementSystem QLocale::measurementSystem() const /*! \since 4.7 - Returns true if the language is written right to left. + Returns the text direction of the language. */ -bool QLocale::isWrittenRightToLeft() const +Qt::LayoutDirection QLocale::textDirection() const { Language lang = language(); if (lang == QLocale::Arabic || @@ -3490,9 +3490,9 @@ bool QLocale::isWrittenRightToLeft() const lang == QLocale::Persian || lang == QLocale::Urdu || lang == QLocale::Syriac) - return true; + return Qt::RightToLeft; - return false; + return Qt::LeftToRight; } diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index f8b5c55..8b424bb 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -666,7 +666,7 @@ public: MeasurementSystem measurementSystem() const; - bool isWrittenRightToLeft() const; + Qt::LayoutDirection textDirection() const; inline bool operator==(const QLocale &other) const; inline bool operator!=(const QLocale &other) const; diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp index 88f8daf..ed5aa23 100644 --- a/src/gui/inputmethod/qximinputcontext_x11.cpp +++ b/src/gui/inputmethod/qximinputcontext_x11.cpp @@ -409,7 +409,7 @@ QXIMInputContext::QXIMInputContext() if (dashPos >= 0) variantName.truncate(dashPos); QLocale keyboardInputLocale = q_getKeyboardLocale(layoutNames.at(i), variantName); - if (keyboardInputLocale.isWrittenRightToLeft()) + if (keyboardInputLocale.textDirection() == Qt::RightToLeft) qt_use_rtl_extensions = true; } } diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index 885f5ba..873b8f9 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -672,7 +672,7 @@ QKeyMapperPrivate::updateKeyboard() #endif if (iso639Code) { keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); - keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + keyboardInputDirection = keyboardInputLocale.textDirection(); } else { keyboardInputLocale = QLocale::c(); keyboardInputDirection = Qt::LeftToRight; diff --git a/src/gui/kernel/qkeymapper_qws.cpp b/src/gui/kernel/qkeymapper_qws.cpp index 0e9f35a..63bb46b 100644 --- a/src/gui/kernel/qkeymapper_qws.cpp +++ b/src/gui/kernel/qkeymapper_qws.cpp @@ -52,7 +52,7 @@ QT_USE_NAMESPACE QKeyMapperPrivate::QKeyMapperPrivate() { keyboardInputLocale = QLocale::system(); - keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + keyboardInputDirection = keyboardInputLocale.textDirection(); } QKeyMapperPrivate::~QKeyMapperPrivate() diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index f0d548c..825edbc 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -517,7 +517,7 @@ void QKeyMapperPrivate::clearMappings() // qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ? keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName); - keyboardInputDirection = keyboardInputLocale.isWrittenRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + keyboardInputDirection = keyboardInputLocale.textDirection(); #if 0 qDebug() << "keyboard input locale =" -- cgit v0.12 From 39e11b3f49fdc01155575f6d909efd92e435d5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 7 Jun 2010 17:23:44 +0200 Subject: Optimized 90-, 180-, and 270- rotated blits in raster paint engine. Blitting a 90-degree rotated RGB16 image now takes 40 % of the time it used to on the N900. Task-number: QT-3057 Reviewed-by: Kim --- src/gui/painting/qpaintengine_raster.cpp | 105 +++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 48974e8..08e14fb 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -68,6 +68,7 @@ // #include #include #include +#include "qmemrotate_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -2521,6 +2522,58 @@ QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t) return QRectF(r.topLeft() * t, r.bottomRight() * t); } +namespace { + enum RotationType { + Rotation90, + Rotation180, + Rotation270, + NoRotation + }; + + inline RotationType qRotationType(const QTransform &transform) + { + QTransform::TransformationType type = transform.type(); + + if (type > QTransform::TxRotate) + return NoRotation; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1)) + && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22())) + return Rotation90; + + if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12()) + && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1))) + return Rotation180; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1)) + && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22())) + return Rotation270; + + return NoRotation; + } + + template void memRotate(RotationType type, const T *srcBase, int w, int h, int sbpl, T *dstBase, int dbpl) + { + switch (type) { + case Rotation90: + qt_memrotate90(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation180: + qt_memrotate180(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation270: + qt_memrotate270(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case NoRotation: + break; + } + } + + inline bool isPixelAligned(const QRectF &rect) { + return QRectF(rect.toRect()) == rect; + } +} + /*! \reimp */ @@ -2582,6 +2635,58 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe const QClipData *clip = d->clip(); + if (s->matrix.type() > QTransform::TxTranslate + && !stretch_sr + && (!clip || clip->hasRectClip) + && s->intOpacity == 256 + && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver + || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source) + && d->rasterBuffer->format == img.format() + && (d->rasterBuffer->format == QImage::Format_RGB16 + || d->rasterBuffer->format == QImage::Format_RGB32 + || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied + && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))) + { + RotationType rotationType = qRotationType(s->matrix); + + if (rotationType != NoRotation && img.rect().contains(sr.toAlignedRect())) { + QRectF transformedTargetRect = s->matrix.mapRect(r); + + if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) + || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr))) + { + QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect); + if (clippedTransformedTargetRect.isNull()) + return; + + QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect)); + + QRect clippedSourceRect + = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(), + clippedTargetRect.width(), clippedTargetRect.height()).toRect(); + + uint dbpl = d->rasterBuffer->bytesPerLine(); + uint sbpl = img.bytesPerLine(); + + uchar *dst = d->rasterBuffer->buffer(); + uint bpp = img.depth() >> 3; + + const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp; + uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp; + + uint cw = clippedSourceRect.width(); + uint ch = clippedSourceRect.height(); + + if (d->rasterBuffer->format == QImage::Format_RGB16) + memRotate(rotationType, (quint16 *)srcBase, cw, ch, sbpl, (quint16 *)dstBase, dbpl); + else + memRotate(rotationType, (quint32 *)srcBase, cw, ch, sbpl, (quint32 *)dstBase, dbpl); + + return; + } + } + } + if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { if (s->flags.fast_images) { -- cgit v0.12 From 7101ae5a0e90d97acf86a444c4d51ca45e7863fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 4 Jun 2010 12:12:01 +0200 Subject: QWidget::childAt for masked child widgets doesn't work properly Problem was that we didn't take the children's effective mask into account when checking whether a point was inside or not. This commit is also an optimization since we no longer check the point against the widget's rect twice. Furthermore, unnecessary QRegion operations are completely avoided in the common case. Auto tests included. Task-number: QTBUG-7150 Reviewed-by: paul --- src/gui/kernel/qwidget.cpp | 75 +++++++++++++++++------------ src/gui/kernel/qwidget_p.h | 9 ++++ tests/auto/qwidget/tst_qwidget.cpp | 97 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 31 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index ab84a54..492954a 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -67,6 +67,7 @@ # include "qt_mac_p.h" # include "qt_cocoa_helpers_mac_p.h" # include "qmainwindow.h" +# include "qtoolbar.h" #endif #if defined(Q_WS_QWS) # include "qwsdisplay_qws.h" @@ -9716,46 +9717,58 @@ QWidget *QWidget::childAt(const QPoint &p) const QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const { - Q_Q(const QWidget); + if (children.isEmpty()) + return 0; + #ifdef Q_WS_MAC + Q_Q(const QWidget); + // Unified tool bars on the Mac require special handling since they live outside + // QMainWindow's geometry(). See commit: 35667fd45ada49269a5987c235fdedfc43e92bb8 bool includeFrame = q->isWindow() && qobject_cast(q) && static_cast(q)->unifiedTitleAndToolBarOnMac(); + if (includeFrame) + return childAtRecursiveHelper(p, ignoreChildrenInDestructor, includeFrame); #endif - if ( -#ifdef Q_WS_MAC - !includeFrame && -#endif - !q->rect().contains(p)) + if (!pointInsideRectAndMask(p)) return 0; + return childAtRecursiveHelper(p, ignoreChildrenInDestructor); +} - for (int i = children.size(); i > 0 ;) { - --i; - QWidget *w = qobject_cast(children.at(i)); - if (w && !w->isWindow() && !w->isHidden() - && (w->geometry().contains(p) -#ifdef Q_WS_MAC - || (includeFrame && w->geometry().contains(qt_mac_nativeMapFromParent(w, p))) +QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor, bool includeFrame) const +{ +#ifndef Q_WS_MAC + Q_UNUSED(includeFrame); #endif - )) { - if (ignoreChildrenInDestructor && w->data->in_destructor) - continue; - if (w->testAttribute(Qt::WA_TransparentForMouseEvents)) - continue; - QPoint childPoint = w->mapFromParent(p); -#ifdef Q_WS_MAC - if (includeFrame && !w->geometry().contains(p)) - childPoint = qt_mac_nativeMapFromParent(w, p); -#endif - if (QWidget *t = w->d_func()->childAt_helper(childPoint, ignoreChildrenInDestructor)) - return t; - // if WMouseNoMask is set the widget mask is ignored, if - // the widget has no mask then the WMouseNoMask flag has no - // effect - if (w->testAttribute(Qt::WA_MouseNoMask) || w->mask().contains(childPoint) - || w->mask().isEmpty()) - return w; + for (int i = children.size() - 1; i >= 0; --i) { + QWidget *child = qobject_cast(children.at(i)); + if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents) + || (ignoreChildrenInDestructor && child->data->in_destructor)) { + continue; } + + // Map the point 'p' from parent coordinates to child coordinates. + QPoint childPoint = p; +#ifdef Q_WS_MAC + // 'includeFrame' is true if the child's parent is a top-level QMainWindow with an unified tool bar. + // An unified tool bar on the Mac lives outside QMainWindow's geometry(), so a normal + // QWidget::mapFromParent won't do the trick. + if (includeFrame && qobject_cast(child)) + childPoint = qt_mac_nativeMapFromParent(child, p); + else +#endif + childPoint -= child->data->crect.topLeft(); + + // Check if the point hits the child. + if (!child->d_func()->pointInsideRectAndMask(childPoint)) + continue; + + // Do the same for the child's descendants. + if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor)) + return w; + + // We have found our target; namely the child at position 'p'. + return child; } return 0; } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 49a2dc8..4247c3a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -542,7 +542,9 @@ public: bool setMinimumSize_helper(int &minw, int &minh); bool setMaximumSize_helper(int &maxw, int &maxh); void setConstraints_sys(); + bool pointInsideRectAndMask(const QPoint &) const; QWidget *childAt_helper(const QPoint &, bool) const; + QWidget *childAtRecursiveHelper(const QPoint &p, bool, bool includeFrame = false) const; void updateGeometry_helper(bool forceUpdate); void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const; @@ -968,6 +970,13 @@ inline void QWidgetPrivate::setSharedPainter(QPainter *painter) x->sharedPainter = painter; } +inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const +{ + Q_Q(const QWidget); + return q->rect().contains(p) && (!extra || !extra->hasMask || q->testAttribute(Qt::WA_MouseNoMask) + || extra->mask.contains(p)); +} + inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const { Q_Q(const QWidget); diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index a1fc607..d76bbfa 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -404,6 +404,10 @@ private slots: void taskQTBUG_7532_tabOrderWithFocusProxy(); void movedAndResizedAttributes(); + void childAt(); +#ifdef Q_WS_MAC + void childAt_unifiedToolBar(); +#endif private: bool ensureScreenSize(int width, int height); @@ -10347,5 +10351,98 @@ void tst_QWidget::movedAndResizedAttributes() #endif } +void tst_QWidget::childAt() +{ + QWidget parent(0, Qt::FramelessWindowHint); + parent.resize(200, 200); + + QWidget *child = new QWidget(&parent); + child->setPalette(Qt::red); + child->setAutoFillBackground(true); + child->setGeometry(20, 20, 160, 160); + + QWidget *grandChild = new QWidget(child); + grandChild->setPalette(Qt::blue); + grandChild->setAutoFillBackground(true); + grandChild->setGeometry(-20, -20, 220, 220); + + QVERIFY(!parent.childAt(19, 19)); + QVERIFY(!parent.childAt(180, 180)); + QCOMPARE(parent.childAt(20, 20), grandChild); + QCOMPARE(parent.childAt(179, 179), grandChild); + + grandChild->setAttribute(Qt::WA_TransparentForMouseEvents); + QCOMPARE(parent.childAt(20, 20), child); + QCOMPARE(parent.childAt(179, 179), child); + grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false); + + child->setMask(QRect(50, 50, 60, 60)); + + QVERIFY(!parent.childAt(69, 69)); + QVERIFY(!parent.childAt(130, 130)); + QCOMPARE(parent.childAt(70, 70), grandChild); + QCOMPARE(parent.childAt(129, 129), grandChild); + + child->setAttribute(Qt::WA_MouseNoMask); + QCOMPARE(parent.childAt(69, 69), grandChild); + QCOMPARE(parent.childAt(130, 130), grandChild); + child->setAttribute(Qt::WA_MouseNoMask, false); + + grandChild->setAttribute(Qt::WA_TransparentForMouseEvents); + QCOMPARE(parent.childAt(70, 70), child); + QCOMPARE(parent.childAt(129, 129), child); + grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false); + + grandChild->setMask(QRect(80, 80, 40, 40)); + + QCOMPARE(parent.childAt(79, 79), child); + QCOMPARE(parent.childAt(120, 120), child); + QCOMPARE(parent.childAt(80, 80), grandChild); + QCOMPARE(parent.childAt(119, 119), grandChild); + + grandChild->setAttribute(Qt::WA_MouseNoMask); + + QCOMPARE(parent.childAt(79, 79), grandChild); + QCOMPARE(parent.childAt(120, 120), grandChild); +} + +#ifdef Q_WS_MAC +void tst_QWidget::childAt_unifiedToolBar() +{ + QLabel *label = new QLabel(QLatin1String("foo")); + QToolBar *toolBar = new QToolBar; + toolBar->addWidget(new QLabel("dummy")); + toolBar->addWidget(label); + + QMainWindow mainWindow; + mainWindow.addToolBar(toolBar); + mainWindow.show(); + + // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates). + QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint()); + QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint()); + + QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast(toolBar)); + QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(label)); + + // Enable unified tool bars. + mainWindow.setUnifiedTitleAndToolBarOnMac(true); + QTest::qWait(50); + + // The tool bar is now in the "non-client" area of QMainWindow, i.e. + // outside the mainWindow's rect(), and since mapTo et al. doesn't work + // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8), + // we use mapToGlobal/mapFromGlobal to re-calculate the corners. + QPoint oldToolBarTopLeft = toolBarTopLeft; + toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint())); + QVERIFY(toolBarTopLeft != oldToolBarTopLeft); + QVERIFY(toolBarTopLeft.y() < 0); + labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint())); + + QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast(toolBar)); + QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(label)); +} +#endif + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" -- cgit v0.12 From fbb3aca27682bfe81c17866f518eae23b3158aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 11 Jun 2010 10:29:06 +0200 Subject: Compile fix. The PFNGLXCREATECONTEXTATTRIBSARBPROC typedef isn't defined on all GLX 1.3 systems, so we use our own. Reviewed-by: Trond --- src/opengl/qgl_x11.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 3e71a48..da072c7 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -672,8 +672,12 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) GLX_CONTEXT_PROFILE_MASK_ARB, profile, 0 }; - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = - (PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB"); + typedef GLXContext ( * Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) + (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + + + Q_PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = + (Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB"); if (glXCreateContextAttribs) { int spec[45]; -- cgit v0.12 From 045732d43f38dadc6019e3ca53e547e4bcb31190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 11 Jun 2010 10:52:43 +0200 Subject: Fixed an on-exit application crash for GL apps using EGL. Task-number: QT-3498 Reviewed-by: Samuel --- src/opengl/qgl_egl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 44e8ae9..4a89b26 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -190,7 +190,7 @@ void QGLContext::makeCurrent() if (!d->workaroundsCached) { d->workaroundsCached = true; const char *renderer = reinterpret_cast(glGetString(GL_RENDERER)); - if (strstr(renderer, "SGX") || strstr(renderer, "MBX")) { + if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) { // PowerVR MBX/SGX chips needs to clear all buffers when starting to render // a new frame, otherwise there will be a performance penalty to pay for // each frame. -- cgit v0.12 From 3ff9474b8e3812f629869bc349ffb0a7f70c93a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 11 Jun 2010 12:25:29 +0200 Subject: Fix another potential strstr() crash for EGL based GL apps. Task-number: releated to QT-3498 Reviewed-by: Samuel --- src/opengl/qgl_egl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 4a89b26..0a19531 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -200,7 +200,8 @@ void QGLContext::makeCurrent() // bug which prevents glCopyTexSubImage2D() to work with a POT // or GL_ALPHA texture bound to an FBO. The only way to // identify that driver is to check the EGL version number for it. - if (strstr(eglQueryString(d->eglContext->display(), EGL_VERSION), "1.3")) + const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION); + if (egl_version && strstr(egl_version, "1.3")) d->workaround_brokenFBOReadBack = true; } } -- cgit v0.12 From 9a16161889c7f6c15c4d5679148a28fe51f95abb Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 9 Jun 2010 10:04:50 +0200 Subject: QMetaType: do not crash when registering builtin stream operator It is not required to register builtin operator, but old code might do so if a type was not builtin before. This is the case of QVariant which became builtin only in Qt 4.7 Task-number: QTBUG-11316 Reviewed-by: Gabriel --- src/corelib/kernel/qmetatype.cpp | 2 ++ tests/auto/qmetatype/tst_qmetatype.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index ce9ed58..6ebaaa3 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -378,6 +378,8 @@ void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveO void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp, LoadOperator loadOp) { + if (idx < User) + return; //builtin types should not be registered; QVector *ct = customTypes(); if (!ct) return; diff --git a/tests/auto/qmetatype/tst_qmetatype.cpp b/tests/auto/qmetatype/tst_qmetatype.cpp index f4e122f..8558e06 100644 --- a/tests/auto/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/qmetatype/tst_qmetatype.cpp @@ -77,6 +77,7 @@ private slots: void isRegistered_data(); void isRegistered(); void unregisterType(); + void QTBUG11316_registerStreamBuiltin(); }; @@ -318,5 +319,12 @@ void tst_QMetaType::unregisterType() QCOMPARE(QMetaType::isRegistered(typeId), false); } +void tst_QMetaType::QTBUG11316_registerStreamBuiltin() +{ + //should not crash; + qRegisterMetaTypeStreamOperators("QString"); + qRegisterMetaTypeStreamOperators("QVariant"); +} + QTEST_MAIN(tst_QMetaType) #include "tst_qmetatype.moc" -- cgit v0.12 From cde3f39cb75ba69185cca8176ea7126f8441f042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 11 Jun 2010 14:47:21 +0200 Subject: Fixed an on-exit crash for apps using GL. If a QGLWidget is left on the heap when the QApplication destructor is called, it will leave the QGLWidget in a broken state. The widget itself is released and set to a non-created state, which the associated QGLContext doesn't get notified about. With this patch the QGLWidget knows when QWidget::destroy() is called and can act acordingly. Task-number: QT-3498, QTBUG-10995 Reviewed-by: Paul --- src/gui/kernel/qwidget_mac.mm | 9 +++++---- src/gui/kernel/qwidget_p.h | 5 +++++ src/gui/kernel/qwidget_qws.cpp | 2 +- src/gui/kernel/qwidget_s60.cpp | 1 + src/gui/kernel/qwidget_win.cpp | 1 + src/gui/kernel/qwidget_x11.cpp | 1 + src/opengl/qgl.cpp | 2 ++ src/opengl/qgl_p.h | 4 ++++ src/opengl/qgl_x11.cpp | 2 +- 9 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1928599..280712a 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2688,6 +2688,7 @@ QWidget::macCGHandle() const void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); @@ -3994,10 +3995,10 @@ static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRe (oldRect.isValid() == false || newRect.isValid() == false) || // the position update is a part of a drag-and-drop operation - QDragManager::self()->object || - - // we are on Panther (no HIViewSetNeedsDisplayInRect) - QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 + QDragManager::self()->object || + + // we are on Panther (no HIViewSetNeedsDisplayInRect) + QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 ){ HIViewSetFrame(view, &bounds); return; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 4247c3a..587d7fb 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -551,6 +551,11 @@ public: void setLayoutItemMargins(int left, int top, int right, int bottom); void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); + // aboutToDestroy() is called just before the contents of + // QWidget::destroy() is executed. It's used to signal QWidget + // sub-classes that their internals are about to be released. + virtual void aboutToDestroy() {} + QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index b827e8b..3145136 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -256,7 +256,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destro void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); - + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 86b858d..68f9470 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1177,6 +1177,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(geometry()); d->deactivateWidgetCleanup(); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index a7e66bf..9c65aa0 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -544,6 +544,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 43f510c..e01489f 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -1023,6 +1023,7 @@ bool QWidgetPrivate::isBackgroundInherited() const void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 5c5d3d1..b4c85ac 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -3674,8 +3674,10 @@ QGLWidget::~QGLWidget() bool doRelease = (glcx && glcx->windowCreated()); #endif delete d->glcx; + d->glcx = 0; #if defined(Q_WGL) delete d->olcx; + d->olcx = 0; #endif #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) if (doRelease) diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 16c225f..1727a41 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -177,6 +177,10 @@ public: void initContext(QGLContext *context, const QGLWidget* shareWidget); bool renderCxPm(QPixmap *pixmap); void cleanupColormaps(); + void aboutToDestroy() { + if (glcx) + glcx->reset(); + } QGLContext *glcx; QGLWidgetGLPaintDevice glDevice; diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index da072c7..bfb232d 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -928,7 +928,7 @@ void QGLContext::makeCurrent() } else if (d->paintDevice->devType() == QInternal::Pbuffer) { ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx); } else if (d->paintDevice->devType() == QInternal::Widget) { - ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx); + ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->internalWinId(), (GLXContext)d->cx); } if (!ok) qWarning("QGLContext::makeCurrent(): Failed."); -- cgit v0.12