From ba65e2741c47912a800132b90f7dbaf2551b04c4 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Wed, 6 Jul 2011 17:08:41 +0200 Subject: Fix raster subpixel positioning in Lion In Lion, the x position returned by CTFontGetBoundingRectsForGlyphs can be fractional, we need to round().truncate() it as we did in QTextureGlyphCache to save the baseLineX. Reviewed-by: Eskil --- src/gui/text/qfontengine_coretext.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm index 07711a3..afeb0a0 100644 --- a/src/gui/text/qfontengine_coretext.mm +++ b/src/gui/text/qfontengine_coretext.mm @@ -750,7 +750,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetFont(ctx, cgFont); - qreal pos_x = -br.x.toReal() + subPixelPosition.toReal() + margin; + qreal pos_x = -br.x.round().truncate() + subPixelPosition.toReal() + margin; qreal pos_y = im.height() + br.y.toReal() - margin; CGContextSetTextPosition(ctx, pos_x, pos_y); -- cgit v0.12 From bd476c6e4b238290a92cfd4693c709e9010b282b Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 7 Jul 2011 13:08:10 +0200 Subject: Revert 344a4dcfe and part of 93bce787 Due to subpixel grid change, these changes are no longer needed. Reviewed-by: Eskil --- src/gui/painting/qtextureglyphcache.cpp | 4 +--- src/gui/text/qfontengine_coretext.mm | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index fdba9c9..abd0ed1 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -367,9 +367,7 @@ void QImageTextureGlyphCache::createTextureData(int width, int height) int QImageTextureGlyphCache::glyphMargin() const { -#if (defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)) - return 1; -#elif defined(Q_WS_X11) +#if (defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)) || defined(Q_WS_X11) return 0; #else return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0; diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm index afeb0a0..6a9201d 100644 --- a/src/gui/text/qfontengine_coretext.mm +++ b/src/gui/text/qfontengine_coretext.mm @@ -718,8 +718,9 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool aa) { + Q_UNUSED(margin); const glyph_metrics_t br = boundingBox(glyph); - QImage im(qRound(br.width) + margin * 2, qRound(br.height) + margin * 2, QImage::Format_RGB32); + QImage im(qRound(br.width) + 2, qRound(br.height) + 2, QImage::Format_RGB32); im.fill(0); CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); @@ -750,8 +751,8 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetFont(ctx, cgFont); - qreal pos_x = -br.x.round().truncate() + subPixelPosition.toReal() + margin; - qreal pos_y = im.height() + br.y.toReal() - margin; + qreal pos_x = -br.x.round().truncate() + subPixelPosition.toReal(); + qreal pos_y = im.height() + br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; -- cgit v0.12 From 459dc4a3bf0dc0ac54fc558379fdf551949dd1c6 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 7 Jul 2011 14:53:09 +0200 Subject: Fix editable combobox style on Mac Reviewed-by: Jens Bache-Wiig --- src/gui/styles/qmacstyle_mac.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 40c28f6..74e3440 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1195,15 +1195,15 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe QRect ret = outerBounds; switch (bdi.kind){ case kThemeComboBox: - ret.adjust(5, 8, -21, -4); + ret.adjust(5, 8, -22, -4); break; case kThemeComboBoxSmall: - ret.adjust(4, 5, -18, 0); - ret.setHeight(16); + ret.adjust(4, 6, -20, 0); + ret.setHeight(14); break; case kThemeComboBoxMini: - ret.adjust(4, 5, -16, 0); - ret.setHeight(13); + ret.adjust(4, 5, -18, -1); + ret.setHeight(12); break; case kThemePopupButton: ret.adjust(10, 3, -23, -3); -- cgit v0.12 From 8b66982ec7b4b5d2071931c288973dce73dc9875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 8 Jul 2011 09:56:00 +0200 Subject: Use more numerically robust algorithm to compute QBezier::pointAt(). QBezier::pointAt() could potentially return values outside the bezier's bounds, even when the bezier was a straight horizontal line. For example, with y = 0.5, it would produce y=0.5 or y=0.49999999999999 for different values of t, which when rounded cause jittering in a QML PathView. Task-number: QTBUG-17007 Task-number: QTBUG-18133 Reviewed-by: Kim --- src/gui/painting/qbezier_p.h | 36 ++++++++++++++-------------- tests/auto/qpainterpath/tst_qpainterpath.cpp | 21 ++++++++++++++++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h index 399dd89..f1f7eb1 100644 --- a/src/gui/painting/qbezier_p.h +++ b/src/gui/painting/qbezier_p.h @@ -162,27 +162,27 @@ inline void QBezier::coefficients(qreal t, qreal &a, qreal &b, qreal &c, qreal & inline QPointF QBezier::pointAt(qreal t) const { -#if 1 - qreal a, b, c, d; - coefficients(t, a, b, c, d); - return QPointF(a*x1 + b*x2 + c*x3 + d*x4, a*y1 + b*y2 + c*y3 + d*y4); -#else // numerically more stable: + qreal x, y; + qreal m_t = 1. - t; - qreal a = x1*m_t + x2*t; - qreal b = x2*m_t + x3*t; - qreal c = x3*m_t + x4*t; - a = a*m_t + b*t; - b = b*m_t + c*t; - qreal x = a*m_t + b*t; - qreal a = y1*m_t + y2*t; - qreal b = y2*m_t + y3*t; - qreal c = y3*m_t + y4*t; - a = a*m_t + b*t; - b = b*m_t + c*t; - qreal y = a*m_t + b*t; + { + qreal a = x1*m_t + x2*t; + qreal b = x2*m_t + x3*t; + qreal c = x3*m_t + x4*t; + a = a*m_t + b*t; + b = b*m_t + c*t; + x = a*m_t + b*t; + } + { + qreal a = y1*m_t + y2*t; + qreal b = y2*m_t + y3*t; + qreal c = y3*m_t + y4*t; + a = a*m_t + b*t; + b = b*m_t + c*t; + y = a*m_t + b*t; + } return QPointF(x, y); -#endif } inline QPointF QBezier::normalVector(qreal t) const diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp index 3941a11..33315ad 100644 --- a/tests/auto/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp @@ -114,6 +114,8 @@ private slots: void connectPathMoveTo(); void translate(); + + void lineWithinBounds(); }; // Testing get/set functions @@ -1306,6 +1308,25 @@ void tst_QPainterPath::translate() QCOMPARE(complexPath.translated(-offset), untranslatedComplexPath); } + +void tst_QPainterPath::lineWithinBounds() +{ + const int iteration_count = 3; + volatile const qreal yVal = 0.5; + QPointF a(0.0, yVal); + QPointF b(1000.0, yVal); + QPointF c(2000.0, yVal); + QPointF d(3000.0, yVal); + QPainterPath path; + path.moveTo(QPointF(0, yVal)); + path.cubicTo(QPointF(1000.0, yVal), QPointF(2000.0, yVal), QPointF(3000.0, yVal)); + for(int i=0; i<=iteration_count; i++) { + qreal actual = path.pointAtPercent(qreal(i) / iteration_count).y(); + QVERIFY(actual == yVal); // don't use QCOMPARE, don't want fuzzy comparison + } +} + + QTEST_APPLESS_MAIN(tst_QPainterPath) #include "tst_qpainterpath.moc" -- cgit v0.12 From c5f3ea858679d07d753e29af87f04efadd7683e9 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 8 Jul 2011 13:39:36 +0200 Subject: Use truncate only for subpixel boundingBox x position Since Lion, Core Text starts to return fractional values for x origin in the glyph bounding box. To get correct alignment we need to make it integer, it seems that round will cut certain pixels (x = 0.6 will be round to 1, then that glyph will be moved too much to the left in image glyph cache). Reverting 4297b85a appears to work fine on previous version of Mac OS X as well. This change will not affect Windows (DirectWrite) and FreeType font engines since they both return integer values for that. Reviewed-by: Eskil --- src/gui/painting/qtextureglyphcache.cpp | 2 +- src/gui/text/qfontengine_coretext.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index abd0ed1..3973abd 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -198,7 +198,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const Coord c = { 0, 0, // will be filled in later glyph_width, glyph_height, // texture coords - metrics.x.round().truncate(), + metrics.x.truncate(), -metrics.y.truncate() }; // baseline for horizontal scripts listItemCoordinates.insert(key, c); diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm index 6a9201d..64d4a24 100644 --- a/src/gui/text/qfontengine_coretext.mm +++ b/src/gui/text/qfontengine_coretext.mm @@ -751,7 +751,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetFont(ctx, cgFont); - qreal pos_x = -br.x.round().truncate() + subPixelPosition.toReal(); + qreal pos_x = -br.x.truncate() + subPixelPosition.toReal(); qreal pos_y = im.height() + br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); -- cgit v0.12 From b05a513e1427dacc4c3de1b6d507616764248b96 Mon Sep 17 00:00:00 2001 From: Tomi Vihria Date: Mon, 11 Jul 2011 13:06:21 +0300 Subject: Backporting fix for QTBUG-18716 Provide internal API to avoid automatic translation of input widget There will be cases when client will want to disable splitview automatic view translation, so that keyboard is just brought on top of the application and no other actions happen. There will be no new public Qt GUI API to cover the cases (the public API will come from QML Components), but the implementation is done with new private API. Task-number: QTBUG-20171 Reviewed-by: Honglei Zhang --- src/gui/inputmethod/qcoefepinputcontext_p.h | 1 + src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 10 ++++++++-- src/gui/kernel/qt_s60_p.h | 2 ++ src/s60installs/bwins/QtGuiu.def | 1 + src/s60installs/eabi/QtGuiu.def | 1 + 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 9fd2703..9857015 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -170,6 +170,7 @@ private: }; Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable); +Q_GUI_EXPORT void qt_s60_setPartialScreenAutomaticTranslation(bool enable); QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 567f83b..c3d293b 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -95,6 +95,11 @@ Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable) ic->update(); } +Q_GUI_EXPORT void qt_s60_setPartialScreenAutomaticTranslation(bool enable) +{ + S60->partial_keyboardAutoTranslation = enable; +} + QCoeFepInputContext::QCoeFepInputContext(QObject *parent) : QInputContext(parent), m_fepState(q_check_ptr(new CAknEdwinState)), // CBase derived object needs check on new @@ -612,12 +617,13 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) widget->resize(widget->width(), splitViewRect.height() - windowTop); } - if (gv->scene()) { + if (gv->scene() && S60->partial_keyboardAutoTranslation) { const QRectF microFocusRect = gv->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF(); gv->ensureVisible(microFocusRect); } } else { - translateInputWidget(); + if (S60->partial_keyboardAutoTranslation) + translateInputWidget(); } if (alwaysResize) diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index fccb44d..35cea5f 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -153,6 +153,7 @@ public: int menuBeingConstructed : 1; int orientationSet : 1; int partial_keyboard : 1; + int partial_keyboardAutoTranslation : 1; int partialKeyboardOpen : 1; int handleStatusPaneResizeNotifications : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type @@ -343,6 +344,7 @@ inline QS60Data::QS60Data() menuBeingConstructed(0), orientationSet(0), partial_keyboard(0), + partial_keyboardAutoTranslation(1), partialKeyboardOpen(0), handleStatusPaneResizeNotifications(1), s60ApplicationFactory(0) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 9b70ee8..e9e58c8 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -13113,4 +13113,5 @@ EXPORTS ?hasBCM2727@QSymbianGraphicsSystemEx@@SA_NXZ @ 13112 NONAME ; bool QSymbianGraphicsSystemEx::hasBCM2727(void) ?constImageRef@QVolatileImage@@QBEABVQImage@@XZ @ 13113 NONAME ; class QImage const & QVolatileImage::constImageRef(void) const ?toVolatileImage@QPixmapData@@UBE?AVQVolatileImage@@XZ @ 13114 NONAME ; class QVolatileImage QPixmapData::toVolatileImage(void) const + ?qt_s60_setPartialScreenAutomaticTranslation@@YAX_N@Z @ 13115 NONAME ; void qt_s60_setPartialScreenAutomaticTranslation(bool) diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 0f9442d..939398b 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12197,4 +12197,5 @@ EXPORTS _ZTV24QSymbianGraphicsSystemEx @ 12196 NONAME _ZNK11QPixmapData15toVolatileImageEv @ 12197 NONAME _ZNK14QVolatileImage13constImageRefEv @ 12198 NONAME + _Z43qt_s60_setPartialScreenAutomaticTranslationb @ 12199 NONAME -- cgit v0.12 From 0ffd5e2dcd9a181fad1e053d8067cbd61d4d3799 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Mon, 11 Jul 2011 12:25:53 +0200 Subject: Removed files with 3rd party copyright notices. HTML files not necessary for the HTML Info example. Reviewed-by: David Boddie --- examples/xml/htmlinfo/apache_org.html | 281 ------ examples/xml/htmlinfo/htmlinfo.html | 51 + examples/xml/htmlinfo/nokia_com.html | 215 ---- examples/xml/htmlinfo/resources.qrc | 6 +- examples/xml/htmlinfo/simpleexample.html | 30 +- examples/xml/htmlinfo/trolltech_com.html | 955 ------------------ examples/xml/htmlinfo/w3c_org.html | 507 ---------- examples/xml/htmlinfo/youtube_com.html | 1585 ------------------------------ 8 files changed, 81 insertions(+), 3549 deletions(-) delete mode 100644 examples/xml/htmlinfo/apache_org.html create mode 100644 examples/xml/htmlinfo/htmlinfo.html delete mode 100644 examples/xml/htmlinfo/nokia_com.html delete mode 100644 examples/xml/htmlinfo/trolltech_com.html delete mode 100644 examples/xml/htmlinfo/w3c_org.html delete mode 100644 examples/xml/htmlinfo/youtube_com.html diff --git a/examples/xml/htmlinfo/apache_org.html b/examples/xml/htmlinfo/apache_org.html deleted file mode 100644 index 9e5e4d3..0000000 --- a/examples/xml/htmlinfo/apache_org.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - Welcome! - The Apache Software Foundation - - - -
-
-
-
- -
-
-
-
-
-

- Latest News -

-
- -
-
-
- -
-

If you would like to keep up with news and announcements from the -foundation and all its projects, you can subscribe to the -Apache -Announcements List.

- -

- Free Video Streams from ApacheCon Europe 2008 -

-
-ApacheCon Europe 2008 -

-ApacheCon Europe 2008 held in Amsterdam was a great success, and attracted higher -than ever attendance figures, with about 500 registered attendees. This -figure represents an increase of more than 40% over the previous year, -demonstrating the rapidly growing interest in Apache and Open Source software -amongst European businesses. - -If you have not been able to attend ApacheCon Europe, you can still watch -videos of all keynotes and select talks online. Keynote sessions -and the opening plenary are available free of charge:

- -

The talks of the following select ApacheCon Europe tracks are -available for just 49 Euro: -System Administration, -Web Security, -Web Services and Web 2.0. -

-
-
- -

- ApacheCon US 2008 in New Orleans! -

-
-

- ApacheCon US 2008 will be held 3 November through 7 November in - New Orleans, Louisiana. - The Call for Papers has already closed and the program and further - information will be made available soon on the ApacheCon US 2008 - Web site www.us.apachecon.com. - If you would like to receive information about ApacheCon US 2008, please - subscribe to - the ApacheCon announcement mailing list. -

-
-
- -

- Notice regarding open letter to Sun Microsystems -

-
-

- The Apache Software Foundation has written an open letter - to Sun Microsystems regarding our inabillity to acquire an acceptable license for the test kit - for Java SE needed by Apache Harmony. For futher information - please see the FAQ and direct all questions to Apache's VP - for JCP issues, geirm at apache dot org, or our regular press inquiry address, press at apache dot org. -

-
-
-
- - -
-
- - - diff --git a/examples/xml/htmlinfo/htmlinfo.html b/examples/xml/htmlinfo/htmlinfo.html new file mode 100644 index 0000000..33e296a --- /dev/null +++ b/examples/xml/htmlinfo/htmlinfo.html @@ -0,0 +1,51 @@ + + + + + HTML Info Example. + + + + The XML HTML Info example provides a simple command line utility that + scans the current directory for HTML files and prints statistics about + them to standard out. + + \note Standard out is redirected on some platforms. On Symbian using Open + C \c stdout is by default directed to the console window, but this window + may not always be visible. To redirect to a file instead, locate the \c + c:\\system\\data\\config.ini file (on either the emulator or the device) + and change \c STDOUT to point to \c MEDIA4. This will redirect the console + to \c c:\\system\\data\\out.txt. + + The files are parsed using a QXmlStreamReader object. If the file does + not contain a well-formed XML document, a description of the error is + printed to the standard error console. + + diff --git a/examples/xml/htmlinfo/nokia_com.html b/examples/xml/htmlinfo/nokia_com.html deleted file mode 100644 index 46d4c95..0000000 --- a/examples/xml/htmlinfo/nokia_com.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - Nokia - Nokia on the Web - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
-
- Nokia - Connecting people - -
- -
- - -
-

Welcome to Nokia

-
-

Where would you like to go?

- -
- -
- - - -
- - -
- - - - - - - - - - - - - -
- - - - - diff --git a/examples/xml/htmlinfo/resources.qrc b/examples/xml/htmlinfo/resources.qrc index a8cf88d..86d8416 100644 --- a/examples/xml/htmlinfo/resources.qrc +++ b/examples/xml/htmlinfo/resources.qrc @@ -1,11 +1,7 @@ - apache_org.html - nokia_com.html simpleexample.html - trolltech_com.html - w3c_org.html - youtube_com.html + htmlinfo.html diff --git a/examples/xml/htmlinfo/simpleexample.html b/examples/xml/htmlinfo/simpleexample.html index 83a55cf..28aaa6b 100644 --- a/examples/xml/htmlinfo/simpleexample.html +++ b/examples/xml/htmlinfo/simpleexample.html @@ -1,7 +1,35 @@ + - Qt is cute! Frans is too! + Qt is cute!

A paragraph.

diff --git a/examples/xml/htmlinfo/trolltech_com.html b/examples/xml/htmlinfo/trolltech_com.html deleted file mode 100644 index 180eb74..0000000 --- a/examples/xml/htmlinfo/trolltech_com.html +++ /dev/null @@ -1,955 +0,0 @@ - - - - - - - - - - - Code Less. Create More. Deploy Everywhere. - — - Trolltech - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- Skip to content. - - Skip to navigation - -
- - - - -
- - -
-

- Trolltech -

- -
- -
-
- - -
Sections
-
-
- -
-
- -
-
- -
Personal tools
- - -
- -
-
- - You -are here: - Home - - -
-
-
- -
- - - - - - - - - - - - - - - - - - - - - -
- - -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -

Trolltech provides cross-platform software solutions for:

- - - - - - - - - - - - - - - - - - -
- - - - - Software Development Managers - - - - - - - - - - Embedded Developers - - - - -
- - - - - Consumer Electronics Vendors - - - - - - - - - - Mobile Application Developers - - - - -
- - - - - Cross-Platform Developers - - - - - - - - - - Open Source Developers - - - - -
- -
- -
- - - - - Code Less. Create More. Deploy Everywhere. - - - -
- - - -
-
-

Download Qt Button: Grey BG

-

Qt

-

Qt is a cross-platform application framework.  It includes:

- -

 

-

Learn More Buy Now

-

 

-

 

-

 

-
-
-
-

Qtopia Learn More button 90px

-

Qtopia

-

Qtopia is an application platform and UI for Linux-based mobile, consumer electronics and embedded devices. Qtopia offers:

-
  • Rich toolkit and intuitive API
  • Fully customizable user interface
  • Highly efficient development framework
-

 

-

Customer Devices Buy Now

-
-
- - - - - - - - - - - - -
- -
- - -
- -
-

Quick Links

- - - - - - - - - - - - - - -
- - -
-

Nokia Acquisition

- - - - - - - - -
- - -
-

News

- - - - -

- - Trolltech Releases Qt Jambi 4.3.5 - - - - (Jun 03) - - - - - - - - -

-

- - Trolltech releases Qt 4.3.5 - - - - (May 28) - - - - - - - - -

-

- - Award From Qt Developers Recognizes Best Open Source Development Tools - - - - (May 14) - - - - - - - - -

-

- - Trolltech Delivered Revenues of NOK 55.6 Million - - - - (May 08) - - - - - - - - -

- - - - - -
- - -
-

Events

- -
-

 

-
- - -

- - Qt Open Enrollment Training Class - - - - - - (Jun 09 - Jun 13) - - - - - -

-

- - Israel Qt User Group - - - - - - (Jun 16) - - - - - -

-

- - Webinar: Building Tomorrow’s Virtual Driver Control Center - - - - - - (Jun 24) - - - - - -

- - - - - - - -
- -
- - -
- - -
- - - - - -
- - - - Powered by Plone CMS, the Open Source Content Management System - - - - -

- This site conforms to the following standards: -

- - - -
- -
- - - - - - - diff --git a/examples/xml/htmlinfo/w3c_org.html b/examples/xml/htmlinfo/w3c_org.html deleted file mode 100644 index 0fcce48..0000000 --- a/examples/xml/htmlinfo/w3c_org.html +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - - - - -World Wide Web Consortium - Web Standards - - - - - - - - - - - - - - - - -

The World Wide Web Consortium (W3C)

- -

Leading the Web to Its Full Potential...

- - - -

The World Wide Web Consortium (W3C) develops interoperable -technologies (specifications, guidelines, software, and tools) to lead -the Web to its full potential. W3C is a forum for information, -commerce, communication, and collective understanding. On this page, -you'll find W3C news, links to W3C technologies and ways to get involved. New visitors can find help in -Finding Your Way at -W3C. We encourage organizations to learn more about W3C and about -W3C Membership.

- - - -
-

News

- - - -

New eGovernment Activity to Help Improve Government through Better Use of the Web

-

Crowd scene

-

2008-06-03: W3C launches today a new forum for governments, citizens, researchers, and other stakeholders to investigate how best to use Web technology for good governance and citizen participation. "Open Standards, and in particular Semantic Web Standards, can help lower the cost of government, make it easier for independent agencies to work together, and increase flexibility in the face of change," said Tim Berners-Lee, W3C Director. W3C invites participation in the new eGovernment Interest Group, which is open to the public. The group will identify best practices and guidelines in this area, document where current technology does not adequately address stakeholder needs, and suggest improvements via the standards process. Read the W3C eGovernment FAQ and press release, and learn more about the W3C eGovernment Activity. (Permalink)

- -

Two Group Notes Published About Semantic Web and Life Sciences

2008-06-05: The Semantic Web Health Care and Life Sciences Interest Group has published two Group Notes: A Prototype Knowledge Base for the Life Sciences and Experiences with the conversion of SenseLab databases to RDF/OWL. The former describes a prototype of a biomedical knowledge base that integrates 15 distinct data sources using currently available Semantic Web technologies including RDF and OWL. The Note outlines which resources were integrated, how the knowledge base was constructed using free and open source triple store technology, how it can be queried using SPARQL, and what resources and inferences are involved in answering complex queries. While the utility of the knowledge base is illustrated by identifying a set of genes involved in Alzheimer's Disease, the approach described here can be applied to any use case that integrates data from multiple domains. The second document describe the experience of converting SenseLab databases into OWL, an important step towards realizing the benefits of Semantic Web in integrative neuroscience research. Learn more about the Semantic Web Activity. (Permalink)

- -

Offline Web Applications Published as W3C Note

2008-06-03: The HTML Working Group has published the Offline Web Applications Group Note. HTML 5 contains several features that address the challenge of building Web applications that work while offline. This document highlights these features (SQL, offline application caching APIs as well as online/offline events, status, and the localStorage API) from HTML 5 and provides brief tutorials on how these features might be used to create Web applications that work offline. Learn more about the HTML Activity. (Permalink)

- -

W3C Advisory Committee Elects Advisory Board

2008-06-02: The W3C Advisory Committee has filled six open seats on the W3C Advisory Board. Created in 1998, the Advisory Board provides guidance to the Team on issues of strategy, management, legal matters, process, and conflict resolution. Beginning 1 July, the nine Advisory Board participants are Jean-François Abramatic (ILOG), Ann Bassetti (The Boeing Company), Jim Bell (HP), Don Deutsch (Oracle), Eduardo Gutentag (Sun Microsystems), Steve Holbrook (IBM), Ken Laskey (MITRE), Ora Lassila (Nokia), and Arun Ranganathan (Mozilla Foundation). Steve Zilles continues as interim Advisory Board Chair. Read more about the Advisory Board. (Permalink)

- -

W3C Talks in June

2008-06-02: Browse W3C presentations and events also available as an RSS channel. (Permalink)

- -

W3C Launches Group to Help Bridge the Digital Divide

Phone bikes2008-05-27: As part of the growing set of W3C initiatives related to social development, W3C invites participation in the new Mobile Web for Development (MW4D) interest Group, chartered to explore the potential of mobile technology to help bridge the digital divide. "We need to solve important challenges, such as lack of standards in end-user devices, network constraints, service cost, issues of literacy, and an understanding of the real information needs of rural communities," said Ken Banks, kiwanja.net, who Chairs the group. "To do so requires an multidisciplinary approach, a step we take through the creation of this new group." Read more in the press release. This launch is part of W3C's Mobile Web Initiative (MWI), which aims to identify and resolve challenges and issues of accessing the Web when on the move. This work takes place under the auspices of the European Union's 7th Research Framework Programme (FP7), part of the Digital World Forum project. (Photo credit: Stéphane Boyera. Permalink)

- -

Last Call: XHTML Access Module

2008-05-26: The XHTML 2 Working Group has published the Last Call Working Draft of XHTML Access Module. This document is intended to help make XHTML-family markup languages more effective at supporting the needs of the accessibility community. It does so by providing a generic mechanism for defining the relationship between document components and well-known accessibility taxonomies. Comments are welcome through 16 June. Learn more about the HTML Activity. (Permalink)

- -

W3C Invites Implementations of CSS Namespaces Module (Candidate Recommendation)

2008-05-23: The Cascading Style Sheets (CSS) Working Group has published the Candidate Recommendation of CSS Namespaces Module. This CSS Namespaces module defines the syntax for using namespaces in CSS. It defines the @namespace rule for declaring the default namespace and binding namespaces to namespace prefixes, and it also defines a syntax that other specifications can adopt for using those prefixes in namespace-qualified names. Learn more about the Style Activity. (Permalink)

- -

Progress Events 1.0

2008-05-22: The Web API Working Group has published a Working Draft of Progress Events 1.0.This document describes event types that can be used for monitoring the progress of an operation. It is primarily intended for contexts such as data transfer operations specified by XMLHTTPRequest, or Media Access Events. Learn more about the Rich Web Client Activity. (Permalink)

- -

XML Security Working Group to Take Next Steps on XML Signature, Encryption

2008-05-21: W3C is pleased to announce the creation of the XML Security Working Group, whose mission is to evaluate and act on recommendations from the September 2007 Workshop on XML Signature and XML Encryption regarding next steps for XML Security specifications. The group's deliverables include new work on XML Signature Syntax and Processing and XML Encryption Syntax and Processing, as well as maintenance of related specifications. Frederick Hirsch (Nokia) will Chair the group, with Thomas Roessler (W3C) as Team Contact. Learn more about the W3C Security Activity. (Permalink)

- -

Last Call: Cascading Style Sheets (CSS) Snapshot 2007

2008-05-16: The Cascading Style Sheets (CSS) Working Group has published the Last Call Working Draft of Cascading Style Sheets (CSS) Snapshot 2007. This document collects together into one definition all the specifications that together form the current state of Cascading Style Sheets (CSS). The primary audience is CSS implementors, not CSS authors, as this definition includes modules by specification stability, not Web browser adoption rate. Comments are welcome through 09 June. Learn more about the Style Activity. (Permalink)

- -

W3C Invites Implementations of XQuery and XPath Full Text 1.0 (Candidate Recommendation); Requirements and Use Cases Drafts Available

2008-05-16: The W3C XML Query Working Group and the W3C XSL Working Group jointly published today a Candidate Recommendation of XQuery and XPath Full Text 1.0. This document defines the syntax and formal semantics of XQuery and XPath Full Text 1.0 which is a language that extends XQuery 1.0 [XQuery 1.0: An XML Query Language] and XPath 2.0 [XML Path Language (XPath) 2.0] with full-text search capabilities. Implementors are encouraged to run the groups' test suite and report their results. The Groups also published Working Drafts of XQuery and XPath Full Text 1.0 Requirements and Use Cases. Learn more about the XML Activity. (Permalink)

- -

State Chart XML (SCXML) Working Draft Published

2008-05-16: The Voice Browser Working Group has published an updated Working Draft of State Chart XML (SCXML): State Machine Notation for Control Abstraction. SCXML is an execution environment based on UML Harel State Tables and CCXML. The main differences from the previous draft are (1) the modularization of the language, (2) the introduction of profiles and (3) a revision of the algorithm for document interpretation; the document as a whole has changed significantly and the group welcomes review. Learn more about the Voice Browser Activity. (Permalink)

- -

"Web Accessibility for Older Users: A Literature Review"; Comments Welcome on First Public Draft

2008-05-14: The Web Accessibility Initiative (WAI) Education and Outreach Working Group Working Group (EOWG) has published Web Accessibility for Older Users: A Literature Review as a First Public Working Draft. The document includes reviews and analysis of guidelines and articles covering the requirements of people with Web accessibility needs related to ageing. This literature review will inform WAI efforts to promote accessibility solutions for older Web users and potentially to develop profiles or extensions to WAI guidelines. The literature review is a deliverable of the WAI-AGE Project (Ageing Education and Harmonisation). See the call for review and participation for an introduction to the project and an invitation to contribute to the literature review and other WAI-AGE work; and about the Web Accessibility Initiative. (Permalink)

- -

Last Call: CURIE Syntax 1.0

2008-05-08: The XHTML2 Working Group has published the Last Call Working Draft of CURIE Syntax 1.0, which outlines a syntax for expressing URIs in a generic, abbreviated syntax ("Compact URI"). The specification targets language designers who need a mechanism to permit the use of extensible value collections. Any language designer considering the use of QNames in attribute values should consider instead using CURIEs, since CURIEs are designed for this purpose, while QNames are not. Comments are welcome through 10 June. Learn more about the HTML Activity. (Permalink)

- - - -

Past News

-
- - -
- -

W3C would like to thank the Supporters who have contributed -financially or through a donation of goods to W3C.

- -

Read about the layout and send comments -about this page. Syndicate -this page with RSS 1.0, an -RDF vocabulary used for site summaries.

- -
-Webmaster · Last modified: - $Date: 2008/06/05 17:06:19 $ - |
-Valid XHTML 1.0! | Valid CSS! | Level Double-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0 - | -
- - - - diff --git a/examples/xml/htmlinfo/youtube_com.html b/examples/xml/htmlinfo/youtube_com.html deleted file mode 100644 index 1de65a3..0000000 --- a/examples/xml/htmlinfo/youtube_com.html +++ /dev/null @@ -1,1585 +0,0 @@ - - - - - - - - - YouTube - Broadcast Yourself. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- -
- - - -
- -
- -
-
Loading...
-
- -
-
-
- - - - - - -
-
-
- -
- -
-
Promoted Videos
-
-
-
-
-
-
-
- - -
- beggars -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
- - -
- Jr0canest -
-
-
-
-
-
-
-
- - - -
-
-
-
- - - - - - - - -
-
- - - - -
- -
video
- -
- - -
- - - - Michael Greiner who is a neighbor and good friend of mine asked me to upload several Marim - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 3,853
- -
- - -
- - 4.84814814815 - - - -
- - - -
01:46
-
- -
-
- More in Entertainment -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - Check out the book "Sharp Teeth" on Amazon:
http://www.amazon.com/Sharp-Teeth-Toby-Barlow -
- - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 67,438
- -
- - -
- - 4.39928057554 - - - -
- - - -
01:33
-
- -
-
- More in Film & Animation -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - This video is for Mrs. Aderman's 1st Period Environmental Science Class.

We are Mose Gi -
- - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 122,748
- -
- - -
- - 4.44329896907 - - - -
- - - -
04:02
-
- -
-
- More in Education -
-
- -
- - - -
- - - - - - -
- -
video
- -
-
-
- JCJC -
-
- JCJC -
-
- -
- - - - His name is Okotanpe.
His mail addless is fuseloopa@hotmail.com

The name of this son -
- - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 532,447
- -
- - -
- - 4.83995523223 - - - -
- - - -
05:26
-
- -
-
- More in Entertainment -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - I'm not a particularly political person, by which I mean I'd sooner just not get involved - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 136,222
- -
- - -
- - 4.65044814341 - - - -
- - - -
03:55
-
- -
-
- More in Music -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - for the taking. - - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 509,825
- -
- - -
- - 3.91057134971 - - - -
- - - -
05:15
-
- -
-
- More in Science & Technology -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - Want a chance to sing with Aimee Mann live? Go to http://www.youtube.com/group/aimeemannco - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 283,776
- -
- - -
- - 3.79036827195 - - - -
- - - -
02:22
-
- -
-
- More in Music -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - This is the first interactive video on YouTube!
Have fun and enjoy the show
you can see -
- - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 3,155,063
- -
- - -
- - 3.41263230956 - - - -
- - - -
01:10
-
- -
-
- More in People & Blogs -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - making the biggest drawing in the world - - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 971,773
- -
- - -
- - 4.54770783066 - - - -
- - - -
04:04
-
- -
-
- More in Film & Animation -
-
- -
- - - -
- - - - - - -
- -
video
- -
-
-
- Checkmate -
-
- Checkmate -
-
- -
- - - - The Internets Celebrities Dallas Penn and Rafi Kam go in for an investigative report on Ch - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 412,830
- -
- - -
- - 4.52936962751 - - - -
- - - -
09:45
-
- -
-
- More in News & Politics -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - Stories from the men and women of the miltary, stationed in the Al Anbar Province. Right f - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 367,189
- -
- - -
- - 4.2188365651 - - - -
- - - -
10:35
-
- -
-
- More in News & Politics -
-
- -
- - - -
- - - - - - -
- -
video
- -
- - -
- - - - Video from TornadoVideos.net Live Stream Unit 3 of several tornadoes from close range.. In - - - - (more) - - - - -
-
- -
- - -
- -
-
-
- -
- Views: 797,370
- -
- - -
- - 4.28912552436 - - - -
- - - -
07:10
-
- -
-
- More in News & Politics -
-
- -
- - - -
- - -
-
- -
- - -
-
- - - - - - - - - - - -
- - - - - - - -
- - - - -
- -
-
-
- -
- Login -
-
-
- -
- - - - - - - - - - - - - -
-
- -
-
- -
- -
-
- - -
- - - - - - - - - - - - - - -
- -
- - - - - - - - - - - - - - -
- -
-
-
What's New
- -
-
-
- Video Annotations
Add interactive commentary and links to your videos -
-
- -
-
-
- New Address Book
Organizing your YouTube friends and contacts just got a lot simpler -
-
- -
-
-
- Updated Inbox
Manage your messages and invites with ease -
-
- - -
-
-
- YouTube Mobile
Watch and upload YouTube videos on your mobile device. -
-
- -
- Hear Ye, Hear Ye: Calling all Reporters
- Today we announce the launch of a new type of YouTube account: the Reporter. Reporter channels are just like the other YouTube channel types, but are specifically intended for citizens and profess... - -

-
-
- - -
- - - - - - - - - - - - - - -
- - -
- -
- - - -
- - - - -
- - - - - - - \ No newline at end of file -- cgit v0.12 From 1f90ae36cff8acf581d1624bf011fe3a55c623c0 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 8 Jul 2011 17:40:43 +0200 Subject: Fix crash when app font is added Loading app fonts will clear the application font cache, but QFontPrivate::engineWithScript will try to load the font again, in Mac the font engine used here must be the one used for shaping, because subsequent sub font engines may be added to it during the shaping process (QCoreTextFontEngineMulti::stringToCMap). That is why we need to fetch the font engine directly from QTextEngine's fontEngine cache instead of QFontCache. Task-number: QTBUG-20250 Reviewed-by: Eskil --- src/gui/text/qtextengine.cpp | 35 +++++++++++++++++++++-------------- src/gui/text/qtextengine_p.h | 4 +++- src/gui/text/qtextlayout.cpp | 8 ++++---- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8ddf3eb..c900918 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -3051,6 +3051,22 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo : justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format), num_chars(0), chars(0), logClusters(0), f(0), fontEngine(0) { + f = font; + fontEngine = f->d->engineForScript(si.analysis.script); + Q_ASSERT(fontEngine); + + initWithScriptItem(si); +} + +QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe, const QTextCharFormat &format) + : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format), + num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) +{ +} + +// Fix up flags and underlineStyle with given info +void QTextItemInt::initWithScriptItem(const QScriptItem &si) +{ // explicitly initialize flags so that initFontAttributes can be called // multiple times on the same TextItem flags = 0; @@ -3058,13 +3074,10 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo flags |= QTextItem::RightToLeft; ascent = si.ascent; descent = si.descent; - f = font; - fontEngine = f->d->engineForScript(si.analysis.script); - Q_ASSERT(fontEngine); - if (format.hasProperty(QTextFormat::TextUnderlineStyle)) { - underlineStyle = format.underlineStyle(); - } else if (format.boolProperty(QTextFormat::FontUnderline) + if (charFormat.hasProperty(QTextFormat::TextUnderlineStyle)) { + underlineStyle = charFormat.underlineStyle(); + } else if (charFormat.boolProperty(QTextFormat::FontUnderline) || f->d->underline) { underlineStyle = QTextCharFormat::SingleUnderline; } @@ -3073,18 +3086,12 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo if (underlineStyle == QTextCharFormat::SingleUnderline) flags |= QTextItem::Underline; - if (f->d->overline || format.fontOverline()) + if (f->d->overline || charFormat.fontOverline()) flags |= QTextItem::Overline; - if (f->d->strikeOut || format.fontStrikeOut()) + if (f->d->strikeOut || charFormat.fontStrikeOut()) flags |= QTextItem::StrikeOut; } -QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe) - : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), - num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) -{ -} - QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const { QTextItemInt ti = *this; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 055974a..b1bd0c3 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -312,11 +312,13 @@ public: logClusters(0), f(0), fontEngine(0) {} QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); - QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe); + QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe, + const QTextCharFormat &format = QTextCharFormat()); /// copy the structure items, adjusting the glyphs arrays to the right subarrays. /// the width of the returned QTextItemInt is not adjusted, for speed reasons QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const; + void initWithScriptItem(const QScriptItem &si); QFixed descent; QFixed ascent; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index c1bc846..2d5b453 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2381,13 +2381,13 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR unsigned short *logClusters = eng->logClusters(&si); QGlyphLayout glyphs = eng->shapedGlyphs(&si); - QTextItemInt gf(si, &f, format); - gf.glyphs = glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart); - gf.chars = eng->layoutData->string.unicode() + iterator.itemStart; + QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart), + &f, eng->layoutData->string.unicode() + iterator.itemStart, + iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format); gf.logClusters = logClusters + iterator.itemStart - si.position; - gf.num_chars = iterator.itemEnd - iterator.itemStart; gf.width = iterator.itemWidth; gf.justified = line.justified; + gf.initWithScriptItem(si); Q_ASSERT(gf.fontEngine); -- cgit v0.12 From 0b996f435fb0da42e4f563986ef8214d542398f4 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Fri, 8 Jul 2011 17:40:43 +0200 Subject: Fix crash when app font is added Loading app fonts will clear the application font cache, but QFontPrivate::engineWithScript will try to load the font again, in Mac the font engine used here must be the one used for shaping, because subsequent sub font engines may be added to it during the shaping process (QCoreTextFontEngineMulti::stringToCMap). That is why we need to fetch the font engine directly from QTextEngine's fontEngine cache instead of QFontCache. Task-number: QTBUG-20250 Reviewed-by: Eskil (cherry picked from commit 1f90ae36cff8acf581d1624bf011fe3a55c623c0) --- src/gui/text/qtextengine.cpp | 35 +++++++++++++++++++++-------------- src/gui/text/qtextengine_p.h | 4 +++- src/gui/text/qtextlayout.cpp | 8 ++++---- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 9271f34..8374c62 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2778,6 +2778,22 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo : justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format), num_chars(0), chars(0), logClusters(0), f(0), fontEngine(0) { + f = font; + fontEngine = f->d->engineForScript(si.analysis.script); + Q_ASSERT(fontEngine); + + initWithScriptItem(si); +} + +QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe, const QTextCharFormat &format) + : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format), + num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) +{ +} + +// Fix up flags and underlineStyle with given info +void QTextItemInt::initWithScriptItem(const QScriptItem &si) +{ // explicitly initialize flags so that initFontAttributes can be called // multiple times on the same TextItem flags = 0; @@ -2785,13 +2801,10 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo flags |= QTextItem::RightToLeft; ascent = si.ascent; descent = si.descent; - f = font; - fontEngine = f->d->engineForScript(si.analysis.script); - Q_ASSERT(fontEngine); - if (format.hasProperty(QTextFormat::TextUnderlineStyle)) { - underlineStyle = format.underlineStyle(); - } else if (format.boolProperty(QTextFormat::FontUnderline) + if (charFormat.hasProperty(QTextFormat::TextUnderlineStyle)) { + underlineStyle = charFormat.underlineStyle(); + } else if (charFormat.boolProperty(QTextFormat::FontUnderline) || f->d->underline) { underlineStyle = QTextCharFormat::SingleUnderline; } @@ -2800,18 +2813,12 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo if (underlineStyle == QTextCharFormat::SingleUnderline) flags |= QTextItem::Underline; - if (f->d->overline || format.fontOverline()) + if (f->d->overline || charFormat.fontOverline()) flags |= QTextItem::Overline; - if (f->d->strikeOut || format.fontStrikeOut()) + if (f->d->strikeOut || charFormat.fontStrikeOut()) flags |= QTextItem::StrikeOut; } -QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe) - : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), - num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe) -{ -} - QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const { QTextItemInt ti = *this; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 09610ff..86551a4 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -311,11 +311,13 @@ public: logClusters(0), f(0), fontEngine(0) {} QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat()); - QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe); + QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe, + const QTextCharFormat &format = QTextCharFormat()); /// copy the structure items, adjusting the glyphs arrays to the right subarrays. /// the width of the returned QTextItemInt is not adjusted, for speed reasons QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const; + void initWithScriptItem(const QScriptItem &si); QFixed descent; QFixed ascent; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 0fbf838..86c6f48 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2319,13 +2319,13 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR unsigned short *logClusters = eng->logClusters(&si); QGlyphLayout glyphs = eng->shapedGlyphs(&si); - QTextItemInt gf(si, &f, format); - gf.glyphs = glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart); - gf.chars = eng->layoutData->string.unicode() + iterator.itemStart; + QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart), + &f, eng->layoutData->string.unicode() + iterator.itemStart, + iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format); gf.logClusters = logClusters + iterator.itemStart - si.position; - gf.num_chars = iterator.itemEnd - iterator.itemStart; gf.width = iterator.itemWidth; gf.justified = line.justified; + gf.initWithScriptItem(si); Q_ASSERT(gf.fontEngine); -- cgit v0.12 From 64dc31c660fd23ec77c51f406ba473a6ca0b3c13 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 11 Jul 2011 14:07:34 +0200 Subject: Fix compiler warning in qtextdocument.cpp Missing QLatin1String() wrapper to ensure codec of text. Reviewed-by: Jiang Jiang --- src/gui/text/qtextdocument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 0abafb8..143dc1a 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2710,7 +2710,7 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) html += QLatin1Char('>'); if (block.begin().atEnd()) - html += "
"; + html += QLatin1String("
"); QTextBlock::Iterator it = block.begin(); if (fragmentMarkers && !it.atEnd() && block == doc->begin()) -- cgit v0.12 From c4b5e186c7718f0a03d6ed529f546e7debfbcf86 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 9 Jul 2010 11:33:56 +1000 Subject: Optimize text layout. When laying out text, a significant amount of time was being spent querying for the font engine. This patch: * changes the layout to only query for the engine when a new script item is encountered. * adds an internal cache of the previous result to QTextEngine::fontEngine(). This catches the important case of multiline text with few font engine changes. With these changes layout costs are now approximately 60% of what they were previously, as measured by the text layout benchmarks. Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 0c56bef89b6e3fe4c9fb32eb8b51a6ea316a89fa) --- src/gui/text/qtextengine.cpp | 65 +++++++++++++++++++++++++++++++------------- src/gui/text/qtextengine_p.h | 17 ++++++++++++ src/gui/text/qtextlayout.cpp | 14 ++++++---- 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 8374c62..03717dc 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1392,6 +1392,7 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + feCache.reset(); } void QTextEngine::clearLineData() @@ -1783,6 +1784,13 @@ QFont QTextEngine::font(const QScriptItem &si) const return font; } +QTextEngine::FontEngineCache::FontEngineCache() +{ + reset(); +} + +//we cache the previous results of this function, as calling it numerous times with the same effective +//input is common (and hard to cache at a higher level) QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const { QFontEngine *engine = 0; @@ -1791,28 +1799,47 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix QFont font = fnt; if (hasFormats()) { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + feCache.prevScaledFontEngine = scaledEngine; + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); } } else { - engine = font.d->engineForScript(script); + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } if (si.analysis.flags == QScriptAnalysis::SmallCaps) { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 86551a4..c920c7b 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -558,6 +558,23 @@ public: mutable QScriptLineArray lines; + struct FontEngineCache { + FontEngineCache(); + mutable QFontEngine *prevFontEngine; + mutable QFontEngine *prevScaledFontEngine; + mutable int prevScript; + mutable int prevPosition; + mutable int prevLength; + inline void reset() { + prevFontEngine = 0; + prevScaledFontEngine = 0; + prevScript = -1; + prevPosition = -1; + prevLength = -1; + } + }; + mutable FontEngineCache feCache; + QString text; QFont fnt; QTextBlock block; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 86c6f48..183bcea 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -386,6 +386,7 @@ QTextLayout::~QTextLayout() void QTextLayout::setFont(const QFont &font) { d->fnt = font; + d->feCache.reset(); } /*! @@ -518,6 +519,7 @@ void QTextLayout::setAdditionalFormats(const QList &formatList) } if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); + d->feCache.reset(); } /*! @@ -1867,14 +1869,14 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); lbh.glyphs = eng->shapedGlyphs(¤t); + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } } const QScriptItem ¤t = eng->layoutData->items[item]; - QFontEngine *fontEngine = eng->fontEngine(current); - if (lbh.fontEngine != fontEngine) { - lbh.fontEngine = fontEngine; - lbh.minimumRightBearing = qMin(QFixed(), - QFixed::fromReal(fontEngine->minRightBearing())); - } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, -- cgit v0.12 From 5f2b6dd2a50275bc05ae5d7e9dd8902d6d49d9df Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Tue, 22 Feb 2011 15:49:34 +0100 Subject: Keep reference count for cached font engines in QTextEngine So that if these font engines are deallocated elsewhere (by QFontCache for instance), we can still access them in QTextEngine. Task-number: QTBUG-17603 Reviewed-by: Eskil (cherry picked from commit 6e23fb69e441871829765ff512e90fed17b6798d) --- src/gui/text/qtextengine.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 03717dc..6322245 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1385,6 +1385,15 @@ void QTextEngine::shape(int item) const } } +static inline void releaseCachedFontEngine(QFontEngine *fontEngine) +{ + if (fontEngine) { + fontEngine->ref.deref(); + if (fontEngine->cache_count == 0 && fontEngine->ref == 0) + delete fontEngine; + } +} + void QTextEngine::invalidate() { freeMemory(); @@ -1392,6 +1401,9 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + + releaseCachedFontEngine(feCache.prevFontEngine); + releaseCachedFontEngine(feCache.prevScaledFontEngine); feCache.reset(); } @@ -1824,7 +1836,9 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix scaledEngine = font.d->engineForScript(script); } feCache.prevFontEngine = engine; + engine->ref.ref(); feCache.prevScaledFontEngine = scaledEngine; + scaledEngine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = si.position; feCache.prevLength = length(&si); @@ -1835,6 +1849,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix else { engine = font.d->engineForScript(script); feCache.prevFontEngine = engine; + engine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = -1; feCache.prevLength = -1; -- cgit v0.12 From ade1378a4fc479d7ff3de3eb636c222c195a9082 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Wed, 23 Feb 2011 12:07:10 +0100 Subject: Check engine existence before increasing reference count Reviewed-by: TrustMe (cherry picked from commit 244620438700464a862ceab7c881974a5b1d1fea) --- src/gui/text/qtextengine.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 6322245..648f5c0 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1836,9 +1836,11 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix scaledEngine = font.d->engineForScript(script); } feCache.prevFontEngine = engine; - engine->ref.ref(); + if (engine) + engine->ref.ref(); feCache.prevScaledFontEngine = scaledEngine; - scaledEngine->ref.ref(); + if (scaledEngine) + scaledEngine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = si.position; feCache.prevLength = length(&si); @@ -1849,7 +1851,8 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix else { engine = font.d->engineForScript(script); feCache.prevFontEngine = engine; - engine->ref.ref(); + if (engine) + engine->ref.ref(); feCache.prevScript = script; feCache.prevPosition = -1; feCache.prevLength = -1; -- cgit v0.12 From 1a10d15593b37ea6956d2eecac60381f2c956074 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Tue, 12 Jul 2011 15:15:15 +0200 Subject: Remove broken link to Symbian.org documentation. --- doc/src/deployment/deployment.qdoc | 11 ----------- doc/src/external-resources.qdoc | 5 ----- 2 files changed, 16 deletions(-) diff --git a/doc/src/deployment/deployment.qdoc b/doc/src/deployment/deployment.qdoc index 74a34ee..d9b169c 100644 --- a/doc/src/deployment/deployment.qdoc +++ b/doc/src/deployment/deployment.qdoc @@ -1555,15 +1555,4 @@ For more information about creating a \c .sis file and installing it to device see also \l {The Symbian platform - Introduction to Qt#Installing your own applications}{here}. - - \section1 Further Reading - - This document aims to cover the common case for developers who want to - deploy Qt applications on devices using the Smart Installer. It does not - aim to cover every possible way of installing applications, Qt and other - dependencies on a device. - - A wider selection of deployment methods is described in the - \l{Deploying a Qt Application article} on the Symbian Foundation - Developer Wiki. */ diff --git a/doc/src/external-resources.qdoc b/doc/src/external-resources.qdoc index 04d7ccb..50e5a21 100644 --- a/doc/src/external-resources.qdoc +++ b/doc/src/external-resources.qdoc @@ -425,11 +425,6 @@ */ /*! - \externalpage http://developer.symbian.org/wiki/index.php/Deploying_a_Qt_Application - \title Deploying a Qt Application article -*/ - -/*! \externalpage http://www.ecma-international.org/publications/standards/Ecma-262.htm \title ECMAScript Language Specification */ -- cgit v0.12 From 2118a8df91263dcadd1ca0067caed84d1c749977 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Tue, 12 Jul 2011 11:33:31 +0200 Subject: Compensate for different rounding rule in CG engine After we switched to fractional metrics, Core Graphics engine always put text at floored vertical postion, while underlines will be rounded after 0.75. Ceiling the underline position will make sure it will always leave the underline pixels given. Task-number: QTBUG-19959 Reviewed-by: Eskil --- src/gui/painting/qpainter.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 604c1ab..754b16e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6335,10 +6335,16 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QLineF line(pos.x(), pos.y(), pos.x() + width, pos.y()); - const qreal underlineOffset = fe->underlinePosition().toReal(); + qreal underlineOffset = fe->underlinePosition().toReal(); + qreal y = pos.y(); + // compensate for different rounding rule in Core Graphics paint engine, + // ideally code like this should be moved to respective engines. + if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics) { + y = qCeil(y); + } // deliberately ceil the offset to avoid the underline coming too close to // the text above it. - const qreal underlinePos = pos.y() + qCeil(underlineOffset); + const qreal underlinePos = y + qCeil(underlineOffset); if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle)); -- cgit v0.12 From c0772f44fb1d53608ff629fc622103698c6d0ee5 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 13 Jul 2011 15:06:43 +0200 Subject: Fix potential crash when clicking in a text edit Since the attributes() call might resize the layout and therefore delete the previous data, the logClusters pointer might be dangling at this point. We need to reget it to make sure it's valid. Task-number: QTBUG-20310 Reviewed-by: Jiang Jiang --- src/gui/text/qtextengine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 648f5c0..6c13eae 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2789,6 +2789,7 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end, } const HB_CharAttributes *attrs = attributes(); + logClusters = this->logClusters(si); clusterLength = getClusterLength(logClusters, attrs, 0, end, glyph_pos, &clusterStart); if (clusterLength) { -- cgit v0.12 From e797ba558dddd45522b5a317316e497e9efc44a8 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 27 Jun 2011 16:28:50 +0200 Subject: Add IAccessible2 table2 implementation. Implement the IAccessible table2 interface for itemviews. This is simpler than what we have in complexwidgets. For now it is only used on Linux. Reviewed-by: Gabi --- src/gui/accessible/qaccessible.cpp | 5 + src/gui/accessible/qaccessible.h | 10 +- src/gui/accessible/qaccessible2.h | 112 +++ src/gui/accessible/qaccessible_unix.cpp | 11 + src/gui/itemviews/qabstractitemview.cpp | 95 +- src/gui/itemviews/qabstractitemview.h | 1 + src/gui/itemviews/qabstractitemview_p.h | 1 + src/gui/itemviews/qlistview.cpp | 12 + src/gui/itemviews/qtableview.cpp | 17 + src/gui/itemviews/qtableview_p.h | 5 + src/gui/itemviews/qtreeview.cpp | 52 +- src/gui/itemviews/qtreeview.h | 3 + src/gui/itemviews/qtreeview_p.h | 6 +- src/plugins/accessible/widgets/itemviews.cpp | 1029 ++++++++++++++++++++++ src/plugins/accessible/widgets/itemviews.h | 319 +++++++ src/plugins/accessible/widgets/main.cpp | 22 +- src/plugins/accessible/widgets/widgets.pro | 22 +- tests/auto/qaccessibility/tst_qaccessibility.cpp | 308 +++++++ 18 files changed, 2001 insertions(+), 29 deletions(-) create mode 100644 src/plugins/accessible/widgets/itemviews.cpp create mode 100644 src/plugins/accessible/widgets/itemviews.h diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 337bb99..10e5785 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1048,6 +1048,11 @@ const QAccessibleInterface *other, int otherChild) const */ /*! + \fn QAccessibleTable2Interface *QAccessibleInterface::table2Interface() + \internal +*/ + +/*! \fn QAccessibleActionInterface *QAccessibleInterface::actionInterface() \internal */ diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index fc03e1c..16869bb 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -151,6 +151,7 @@ public: ReadOnly = 0x00000040, HotTracked = 0x00000080, DefaultButton = 0x00000100, + // #### Qt5 Expandable Expanded = 0x00000200, Collapsed = 0x00000400, Busy = 0x00000800, @@ -178,6 +179,8 @@ public: HasPopup = 0x40000000, Modal = 0x80000000, + // #### Qt5 ManagesDescendants + // #### Qt5 remove HasInvokeExtension HasInvokeExtension = 0x10000000 // internal }; Q_DECLARE_FLAGS(State, StateFlag) @@ -348,7 +351,8 @@ namespace QAccessible2 ValueInterface, TableInterface, ActionInterface, - ImageInterface + ImageInterface, + Table2Interface }; } @@ -359,6 +363,7 @@ class QAccessibleValueInterface; class QAccessibleTableInterface; class QAccessibleActionInterface; class QAccessibleImageInterface; +class QAccessibleTable2Interface; class Q_GUI_EXPORT QAccessibleInterface : public QAccessible { @@ -422,6 +427,9 @@ public: inline QAccessibleImageInterface *imageInterface() { return reinterpret_cast(cast_helper(QAccessible2::ImageInterface)); } + inline QAccessibleTable2Interface *table2Interface() + { return reinterpret_cast(cast_helper(QAccessible2::Table2Interface)); } + private: QAccessible2Interface *cast_helper(QAccessible2::InterfaceType); }; diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index 5cb0323..106b69e 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -52,6 +52,8 @@ QT_MODULE(Gui) #ifndef QT_NO_ACCESSIBILITY +class QModelIndex; + namespace QAccessible2 { enum CoordinateType @@ -68,6 +70,24 @@ namespace QAccessible2 LineBoundary, NoBoundary }; + + enum TableModelChangeType { + TableModelChangeInsert, + TableModelChangeDelete, + TableModelChangeUpdate + }; + + struct TableModelChange { + int firstColumn; + int firstRow; + int lastColumn; + int lastRow; + TableModelChangeType type; + + TableModelChange() + : firstColumn(0), firstRow(0), lastColumn(0), lastRow(0), type(TableModelChangeUpdate) + {} + }; } class Q_GUI_EXPORT QAccessible2Interface @@ -83,6 +103,7 @@ inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleTableCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; } inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; } +inline QAccessible2Interface *qAccessibleTable2CastHelper() { return 0; } #define Q_ACCESSIBLE_OBJECT \ public: \ @@ -101,6 +122,8 @@ inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; } return qAccessibleActionCastHelper(); \ case QAccessible2::ImageInterface: \ return qAccessibleImageCastHelper(); \ + case QAccessible2::Table2Interface: \ + return qAccessibleTable2CastHelper(); \ } \ return 0; \ } \ @@ -214,6 +237,95 @@ public: int *columnSpan, bool *isSelected) = 0; }; +class Q_GUI_EXPORT QAccessibleTable2CellInterface: public QAccessibleInterface +{ +public: + // Returns the number of columns occupied by this cell accessible. + virtual int columnExtent() const = 0; + + // Returns the column headers as an array of cell accessibles. + virtual QList columnHeaderCells() const = 0; + + // Translates this cell accessible into the corresponding column index. + virtual int columnIndex() const = 0; + // Returns the number of rows occupied by this cell accessible. + virtual int rowExtent() const = 0; + // Returns the row headers as an array of cell accessibles. + virtual QList rowHeaderCells() const = 0; + // Translates this cell accessible into the corresponding row index. + virtual int rowIndex() const = 0; + // Returns a boolean value indicating whether this cell is selected. + virtual bool isSelected() const = 0; + + // Gets the row and column indexes and extents of this cell accessible and whether or not it is selected. + virtual void rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const = 0; + // Returns a reference to the accessbile of the containing table. + virtual QAccessibleTable2Interface* table() const = 0; + + // #### Qt5 this should not be here but part of the state + virtual bool isExpandable() const = 0; +}; + +class Q_GUI_EXPORT QAccessibleTable2Interface: public QAccessible2Interface +{ +public: + inline QAccessible2Interface *qAccessibleTable2CastHelper() { return this; } + + // Returns the cell at the specified row and column in the table. + virtual QAccessibleTable2CellInterface *cellAt (int row, int column) const = 0; + // Returns the caption for the table. + virtual QAccessibleInterface *caption() const = 0; + // Returns the description text of the specified column in the table. + virtual QString columnDescription(int column) const = 0; + // Returns the total number of columns in table. + virtual int columnCount() const = 0; + // Returns the total number of rows in table. + virtual int rowCount() const = 0; + // Returns the total number of selected cells. + virtual int selectedCellCount() const = 0; + // Returns the total number of selected columns. + virtual int selectedColumnCount() const = 0; + // Returns the total number of selected rows. + virtual int selectedRowCount() const = 0; + // Returns the description text of the specified row in the table. + virtual QString rowDescription(int row) const = 0; + // Returns a list of accessibles currently selected. + virtual QList selectedCells() const = 0; + // Returns a list of column indexes currently selected (0 based). + virtual QList selectedColumns() const = 0; + // Returns a list of row indexes currently selected (0 based). + virtual QList selectedRows() const = 0; + // Returns the summary description of the table. + virtual QAccessibleInterface *summary() const = 0; + // Returns a boolean value indicating whether the specified column is completely selected. + virtual bool isColumnSelected(int column) const = 0; + // Returns a boolean value indicating whether the specified row is completely selected. + virtual bool isRowSelected(int row) const = 0; + // Selects a row and unselects all previously selected rows. + virtual bool selectRow(int row) = 0; + // Selects a column and unselects all previously selected columns. + virtual bool selectColumn(int column) = 0; + // Unselects one row, leaving other selected rows selected (if any). + virtual bool unselectRow(int row) = 0; + // Unselects one column, leaving other selected columns selected (if any). + virtual bool unselectColumn(int column) = 0; + // Returns the type and extents describing how a table changed. + virtual QAccessible2::TableModelChange modelChange() const = 0; + +protected: + // These functions are called when the model changes. + virtual void modelReset() = 0; + virtual void rowsInserted(const QModelIndex &parent, int first, int last) = 0; + virtual void rowsRemoved(const QModelIndex &parent, int first, int last) = 0; + virtual void columnsInserted(const QModelIndex &parent, int first, int last) = 0; + virtual void columnsRemoved(const QModelIndex &parent, int first, int last) = 0; + virtual void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) = 0; + virtual void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column) = 0; + +friend class QAbstractItemView; +friend class QAbstractItemViewPrivate; +}; + class Q_GUI_EXPORT QAccessibleActionInterface : public QAccessible2Interface { public: diff --git a/src/gui/accessible/qaccessible_unix.cpp b/src/gui/accessible/qaccessible_unix.cpp index a6b7ec3..19fbe78 100644 --- a/src/gui/accessible/qaccessible_unix.cpp +++ b/src/gui/accessible/qaccessible_unix.cpp @@ -103,6 +103,17 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) if (!iface) return; + // updates for List/Table/Tree should send child + if (who) { + QAccessibleInterface *child; + iface->navigate(QAccessible::Child, who, &child); + if (child) { + delete iface; + iface = child; + who = 0; + } + } + for (int i = 0; i < bridges()->count(); ++i) bridges()->at(i)->notifyAccessibilityUpdate(reason, iface, who); delete iface; diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index f53705b..ded4d63 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -60,6 +60,7 @@ #include #ifndef QT_NO_ACCESSIBILITY #include +#include #endif #include @@ -645,6 +646,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); + disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(_q_rowsInserted(QModelIndex,int,int))); disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), @@ -675,6 +678,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) this, SLOT(_q_headerDataChanged())); connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int))); + connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(_q_rowsInserted(QModelIndex,int,int))); connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), @@ -1058,6 +1063,14 @@ void QAbstractItemView::reset() setRootIndex(QModelIndex()); if (d->selectionModel) d->selectionModel->reset(); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(this)->table2Interface()->modelReset(); + QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged); + } +#endif +#endif } /*! @@ -2805,7 +2818,7 @@ void QAbstractItemView::editorDestroyed(QObject *editor) */ void QAbstractItemView::setHorizontalStepsPerItem(int steps) { - Q_UNUSED(steps); + Q_UNUSED(steps) // do nothing } @@ -2834,7 +2847,7 @@ int QAbstractItemView::horizontalStepsPerItem() const */ void QAbstractItemView::setVerticalStepsPerItem(int steps) { - Q_UNUSED(steps); + Q_UNUSED(steps) // do nothing } @@ -3267,12 +3280,24 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star rows are those under the given \a parent from \a start to \a end inclusive. */ -void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &, int, int) +void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int start, int end) { + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) + Q_Q(QAbstractItemView); if (q->isVisible()) q->updateEditorGeometries(); q->setState(QAbstractItemView::NoState); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(q)->table2Interface()->rowsRemoved(index, start, end); + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } /*! @@ -3335,27 +3360,72 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par rows are those under the given \a parent from \a start to \a end inclusive. */ -void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &, int, int) +void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int start, int end) { + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) + Q_Q(QAbstractItemView); if (q->isVisible()) q->updateEditorGeometries(); q->setState(QAbstractItemView::NoState); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(q)->table2Interface()->columnsRemoved(index, start, end); + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } + /*! \internal This slot is called when rows have been inserted. */ -void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &, int, int) +void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int start, int end) { + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) + Q_Q(QAbstractItemView); - if (q->isVisible()) - q->updateEditorGeometries(); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(q)->table2Interface()->rowsInserted(index, start, end); + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } +/*! + \internal + This slot is called when columns have been inserted. +*/ +void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int start, int end) +{ + Q_UNUSED(index) + Q_UNUSED(start) + Q_UNUSED(end) + + Q_Q(QAbstractItemView); + if (q->isVisible()) + q->updateEditorGeometries(); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(q)->table2Interface()->columnsInserted(index, start, end); + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif +} /*! \internal @@ -3373,7 +3443,16 @@ void QAbstractItemViewPrivate::_q_modelDestroyed() */ void QAbstractItemViewPrivate::_q_layoutChanged() { + Q_Q(QAbstractItemView); doDelayedItemsLayout(); +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::queryAccessibleInterface(q)->table2Interface()->modelReset(); + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } /*! @@ -3698,7 +3777,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemView::selectionCommand(const QM QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::multiSelectionCommand( const QModelIndex &index, const QEvent *event) const { - Q_UNUSED(index); + Q_UNUSED(index) if (event) { switch (event->type()) { diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h index cb7b78d..1d0c36e 100644 --- a/src/gui/itemviews/qabstractitemview.h +++ b/src/gui/itemviews/qabstractitemview.h @@ -355,6 +355,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_columnsRemoved(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_columnsInserted(const QModelIndex&, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged()) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 3ba7227..04babde 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -108,6 +108,7 @@ public: void init(); virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end); + virtual void _q_rowsInserted(const QModelIndex &parent, int start, int end); virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end); virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end); diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index a234fde..a0955d2 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -3168,7 +3168,11 @@ void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr if (QAccessible::isActive()) { if (current.isValid()) { int entry = visualIndex(current) + 1; +#ifdef Q_WS_X11 + QAccessible::updateAccessibility(this, entry, QAccessible::Focus); +#else QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus); +#endif } } #endif @@ -3187,12 +3191,20 @@ void QListView::selectionChanged(const QItemSelection &selected, QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { int entry = visualIndex(sel) + 1; +#ifdef Q_WS_X11 + QAccessible::updateAccessibility(this, entry, QAccessible::Selection); +#else QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection); +#endif } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { int entry = visualIndex(desel) + 1; +#ifdef Q_WS_X11 + QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove); +#else QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove); +#endif } } #endif diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 617409f..6f532eb 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -3164,10 +3164,16 @@ void QTableView::currentChanged(const QModelIndex ¤t, const QModelIndex &p #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { if (current.isValid()) { +#ifdef Q_WS_X11 + Q_D(QTableView); + int entry = d->accessibleTable2Index(current); + QAccessible::updateAccessibility(this, entry, QAccessible::Focus); +#else int entry = visualIndex(current) + 1; if (horizontalHeader()) ++entry; QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus); +#endif } } #endif @@ -3180,22 +3186,33 @@ void QTableView::currentChanged(const QModelIndex ¤t, const QModelIndex &p void QTableView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { + Q_D(QTableView); #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { +#ifdef Q_WS_X11 + int entry = d->accessibleTable2Index(sel); + QAccessible::updateAccessibility(this, entry, QAccessible::Selection); +#else int entry = visualIndex(sel); if (horizontalHeader()) ++entry; QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection); +#endif } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { +#ifdef Q_WS_X11 + int entry = d->accessibleTable2Index(sel); + QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove); +#else int entry = visualIndex(sel); if (horizontalHeader()) ++entry; QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove); +#endif } } #endif diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h index f973acf..dce0ed0 100644 --- a/src/gui/itemviews/qtableview_p.h +++ b/src/gui/itemviews/qtableview_p.h @@ -167,6 +167,11 @@ public: return horizontalHeader->logicalIndex(visualCol); } + inline int accessibleTable2Index(const QModelIndex &index) const { + return (index.row() + (horizontalHeader ? 1 : 0)) * (index.model()->columnCount() + (verticalHeader ? 1 : 0)) + + index.column() + (verticalHeader ? 1 : 0) + 1; + } + int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const; int sectionSpanSize(const QHeaderView *header, int logical, int span) const; bool spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const; diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 6a992db..9228ac8 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -54,6 +54,7 @@ #include #ifndef QT_NO_ACCESSIBILITY #include +#include #endif #include @@ -2883,20 +2884,36 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem) { + Q_Q(QTreeView); viewItems.insert(pos, count, viewItem); QTreeViewItem *items = viewItems.data(); for (int i = pos + count; i < viewItems.count(); i++) if (items[i].parentItem >= pos) items[i].parentItem += count; +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } void QTreeViewPrivate::removeViewItems(int pos, int count) { + Q_Q(QTreeView); viewItems.remove(pos, count); QTreeViewItem *items = viewItems.data(); for (int i = pos; i < viewItems.count(); i++) if (items[i].parentItem >= pos) items[i].parentItem -= count; +#ifndef QT_NO_ACCESSIBILITY +#ifdef Q_WS_X11 + if (QAccessible::isActive()) { + QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged); + } +#endif +#endif } #if 0 @@ -3687,14 +3704,6 @@ void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order) */ void QTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { -#ifndef QT_NO_ACCESSIBILITY - if (QAccessible::isActive()) { - int entry = visualIndex(current) + 1; - if (header()) - ++entry; - QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus); - } -#endif QAbstractItemView::currentChanged(current, previous); if (allColumnsShowFocus()) { @@ -3711,6 +3720,19 @@ void QTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr viewport()->update(currentRect); } } +#ifndef QT_NO_ACCESSIBILITY + if (QAccessible::isActive() && current.isValid()) { +#ifdef Q_WS_X11 + int entry = (visualIndex(current) + (header()?1:0))*current.model()->columnCount()+current.column() + 1; + QAccessible::updateAccessibility(this, entry, QAccessible::Focus); +#else + int entry = visualIndex(current) + 1; + if (header()) + ++entry; + QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus); +#endif + } +#endif } /*! @@ -3719,26 +3741,38 @@ void QTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr void QTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { + QAbstractItemView::selectionChanged(selected, deselected); #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { +#ifdef Q_WS_X11 + int entry = (visualIndex(sel) + (header()?1:0))*sel.model()->columnCount()+sel.column() + 1; + Q_ASSERT(entry > 0); + QAccessible::updateAccessibility(this, entry, QAccessible::Selection); +#else int entry = visualIndex(sel) + 1; if (header()) ++entry; QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection); +#endif } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { +#ifdef Q_WS_X11 + int entry = (visualIndex(desel) + (header()?1:0))*desel.model()->columnCount()+desel.column() + 1; + Q_ASSERT(entry > 0); + QAccessible::updateAccessibility(this, entry, QAccessible::SelectionRemove); +#else int entry = visualIndex(desel) + 1; if (header()) ++entry; QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove); +#endif } } #endif - QAbstractItemView::selectionChanged(selected, deselected); } int QTreeView::visualIndex(const QModelIndex &index) const diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h index 26c7315..b77da4e 100644 --- a/src/gui/itemviews/qtreeview.h +++ b/src/gui/itemviews/qtreeview.h @@ -219,6 +219,9 @@ protected: private: friend class QAccessibleItemView; + friend class QAccessibleTable2; + friend class QAccessibleTree; + friend class QAccessibleTable2Cell; int visualIndex(const QModelIndex &index) const; Q_DECLARE_PRIVATE(QTreeView) diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index b6d8458..a9dc452 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -78,7 +78,7 @@ struct QTreeViewItem Q_DECLARE_TYPEINFO(QTreeViewItem, Q_MOVABLE_TYPE); -class QTreeViewPrivate : public QAbstractItemViewPrivate +class Q_GUI_EXPORT QTreeViewPrivate : public QAbstractItemViewPrivate { Q_DECLARE_PUBLIC(QTreeView) public: @@ -223,6 +223,10 @@ public: inline void invalidateHeightCache(int item) const { viewItems[item].height = 0; } + inline int accessibleTable2Index(const QModelIndex &index) const { + return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column() + 1; + } + // used for spanning rows QVector spanningIndexes; diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp new file mode 100644 index 0000000..d7432e9 --- /dev/null +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -0,0 +1,1029 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "itemviews.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_ACCESSIBILITY + +QT_BEGIN_NAMESPACE + +QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); + +#ifndef QT_NO_ITEMVIEWS +/* +Implementation of the IAccessible2 table2 interface. Much simpler than +the other table interfaces since there is only the main table and cells: + +TABLE/LIST/TREE + |- HEADER CELL + |- CELL + |- CELL + ... +*/ + +int QAccessibleTable2::logicalIndex(const QModelIndex &index) const +{ + if (!index.isValid()) + return -1; + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + // row * number columns + column + 1 for one based counting + return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader) + 1; +} + +QAccessibleInterface *QAccessibleTable2::childFromLogical(int logicalIndex) const +{ + logicalIndex--; // one based counting ftw + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + + int columns = view->model()->columnCount() + vHeader; + + int row = logicalIndex / columns; + int column = logicalIndex % columns; + + if (vHeader) { + if (column == 0) { + if (row == 0) { + return new QAccessibleTable2CornerButton(view); + } + return new QAccessibleTable2HeaderCell(view, row-1, Qt::Vertical); + } + --column; + } + if (hHeader) { + if (row == 0) { + return new QAccessibleTable2HeaderCell(view, column, Qt::Horizontal); + } + --row; + } + return new QAccessibleTable2Cell(view, view->model()->index(row, column), cellRole()); +} + +QAccessibleTable2::QAccessibleTable2(QWidget *w) + : QAccessibleObjectEx(w) +{ + view = qobject_cast(w); + Q_ASSERT(view); + + if (qobject_cast(view)) { + m_role = QAccessible::Table; + } else if (qobject_cast(view)) { + m_role = QAccessible::Tree; + } else if (qobject_cast(view)) { + m_role = QAccessible::List; + } else { + // is this our best guess? + m_role = QAccessible::Table; + } +} + +QAccessibleTable2::~QAccessibleTable2() +{ +} + +QHeaderView *QAccessibleTable2::horizontalHeader() const +{ + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->horizontalHeader(); +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + return header; +} + +QHeaderView *QAccessibleTable2::verticalHeader() const +{ + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->verticalHeader(); +#endif + } + return header; +} + +void QAccessibleTable2::modelReset() +{} + +void QAccessibleTable2::rowsInserted(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = first; + lastChange.lastRow = last; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeInsert; +} + +void QAccessibleTable2::rowsRemoved(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = first; + lastChange.lastRow = last; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeDelete; +} + +void QAccessibleTable2::columnsInserted(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = first; + lastChange.lastColumn = last; + lastChange.type = QAccessible2::TableModelChangeInsert; +} + +void QAccessibleTable2::columnsRemoved(const QModelIndex &, int first, int last) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = first; + lastChange.lastColumn = last; + lastChange.type = QAccessible2::TableModelChangeDelete; +} + +void QAccessibleTable2::rowsMoved( const QModelIndex &, int, int, const QModelIndex &, int) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeUpdate; +} + +void QAccessibleTable2::columnsMoved( const QModelIndex &, int, int, const QModelIndex &, int) +{ + lastChange.firstRow = 0; + lastChange.lastRow = 0; + lastChange.firstColumn = 0; + lastChange.lastColumn = 0; + lastChange.type = QAccessible2::TableModelChangeUpdate; +} + +QAccessibleTable2Cell *QAccessibleTable2::cell(const QModelIndex &index) const +{ + if (index.isValid()) + return new QAccessibleTable2Cell(view, index, cellRole()); + return 0; +} + +QAccessibleTable2CellInterface *QAccessibleTable2::cellAt(int row, int column) const +{ + Q_ASSERT(role(0) != QAccessible::Tree); + QModelIndex index = view->model()->index(row, column); + //Q_ASSERT(index.isValid()); + if (!index.isValid()) { + qWarning() << "QAccessibleTable2::cellAt: invalid index: " << index << " for " << view; + return 0; + } + return cell(index); +} + +QAccessibleInterface *QAccessibleTable2::caption() const +{ + return 0; +} + +QString QAccessibleTable2::columnDescription(int column) const +{ + return view->model()->headerData(column, Qt::Horizontal).toString(); +} + +int QAccessibleTable2::columnCount() const +{ + return view->model()->columnCount(); +} + +int QAccessibleTable2::rowCount() const +{ + return view->model()->rowCount(); +} + +int QAccessibleTable2::selectedCellCount() const +{ + return view->selectionModel()->selectedIndexes().count(); +} + +int QAccessibleTable2::selectedColumnCount() const +{ + return view->selectionModel()->selectedColumns().count(); +} + +int QAccessibleTable2::selectedRowCount() const +{ + return view->selectionModel()->selectedRows().count(); +} + +QString QAccessibleTable2::rowDescription(int row) const +{ + return view->model()->headerData(row, Qt::Vertical).toString(); +} + +QList QAccessibleTable2::selectedCells() const +{ + QList cells; + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedIndexes()) { + cells.append(cell(index)); + } + return cells; +} + +QList QAccessibleTable2::selectedColumns() const +{ + QList columns; + Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedColumns()) { + columns.append(index.column()); + } + return columns; +} + +QList QAccessibleTable2::selectedRows() const +{ + QList rows; + Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedRows()) { + rows.append(index.row()); + } + return rows; +} + +QAccessibleInterface *QAccessibleTable2::summary() const +{ + return 0; +} + +bool QAccessibleTable2::isColumnSelected(int column) const +{ + return view->selectionModel()->isColumnSelected(column, QModelIndex()); +} + +bool QAccessibleTable2::isRowSelected(int row) const +{ + return view->selectionModel()->isRowSelected(row, QModelIndex()); +} + +bool QAccessibleTable2::selectRow(int row) +{ + QModelIndex index = view->model()->index(row, 0); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +bool QAccessibleTable2::selectColumn(int column) +{ + QModelIndex index = view->model()->index(0, column); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +bool QAccessibleTable2::unselectRow(int row) +{ + QModelIndex index = view->model()->index(row, 0); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Deselect); + return true; +} + +bool QAccessibleTable2::unselectColumn(int column) +{ + QModelIndex index = view->model()->index(0, column); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Columns & QItemSelectionModel::Deselect); + return true; +} + +QAccessible2::TableModelChange QAccessibleTable2::modelChange() const +{ + QAccessible2::TableModelChange change; + // FIXME + return change; +} + +QAccessible::Role QAccessibleTable2::role(int child) const +{ + Q_ASSERT(child >= 0); + if (child > 0) + return QAccessible::Cell; + return m_role; +} + +QAccessible::State QAccessibleTable2::state(int child) const +{ + Q_ASSERT(child == 0); + return QAccessible::Normal | HasInvokeExtension; +} + +int QAccessibleTable2::childAt(int x, int y) const +{ + QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); + QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); + // FIXME: if indexPosition < 0 in one coordinate, return header + + QModelIndex index = view->indexAt(indexPosition); + if (index.isValid()) { + return logicalIndex(index); + } + return -1; +} + +int QAccessibleTable2::childCount() const +{ + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + return (view->model()->rowCount()+hHeader) * (view->model()->columnCount()+vHeader); +} + +int QAccessibleTable2::indexOfChild(const QAccessibleInterface *iface) const +{ + Q_ASSERT(iface->role(0) != QAccessible::TreeItem); // should be handled by tree class + if (iface->role(0) == QAccessible::Cell || iface->role(0) == QAccessible::ListItem) { + const QAccessibleTable2Cell* cell = static_cast(iface); + return logicalIndex(cell->m_index); + } else if (iface->role(0) == QAccessible::ColumnHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + return cell->index + (verticalHeader() ? 1 : 0) + 1; + } else if (iface->role(0) == QAccessible::RowHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + return (cell->index+1) * (view->model()->rowCount()+1) + 1; + } else if (iface->role(0) == QAccessible::Pane) { + return 1; // corner button + } else { + qWarning() << "WARNING QAccessibleTable2::indexOfChild Fix my children..." + << iface->role(0) << iface->text(QAccessible::Name, 0); + } + // FIXME: we are in denial of our children. this should stop. + return -1; +} + +QString QAccessibleTable2::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + if (t == QAccessible::Description) + return view->accessibleDescription(); + return view->accessibleName(); +} + +QRect QAccessibleTable2::rect(int child) const +{ + Q_ASSERT(!child); + if (!view->isVisible()) + return QRect(); + QPoint pos = view->mapToGlobal(QPoint(0, 0)); + return QRect(pos.x(), pos.y(), view->width(), view->height()); +} + +int QAccessibleTable2::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + *iface = 0; + switch (relation) { + case Ancestor: { + if (index == 1 && view->parent()) { + *iface = QAccessible::queryAccessibleInterface(view->parent()); + if (*iface) + return 0; + } + break; + } + case QAccessible::Child: { + Q_ASSERT(index > 0); + *iface = childFromLogical(index); + if (*iface) { + return 0; + } + break; + } + default: + break; + } + return -1; +} + +QAccessible::Relation QAccessibleTable2::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2::userActionCount(int) const +{ + return 0; +} +QString QAccessibleTable2::actionText(int, Text, int) const +{ + return QString(); +} +bool QAccessibleTable2::doAction(int, int, const QVariantList &) +{ + return false; +} +#endif + + +// TREE VIEW + +QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const +{ + const QTreeView *treeView = qobject_cast(view); + QModelIndex modelIndex = treeView->d_func()->viewItems.at(row).index; + + if (modelIndex.isValid() && column > 0) { + modelIndex = view->model()->index(modelIndex.row(), column, modelIndex.parent()); + } + return modelIndex; +} + +int QAccessibleTree::childAt(int x, int y) const +{ + QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); + QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); + + QModelIndex index = view->indexAt(indexPosition); + if (!index.isValid()) + return -1; + + const QTreeView *treeView = qobject_cast(view); + int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0); + int column = index.column(); + + int i = row * view->model()->columnCount() + column + 1; + Q_ASSERT(i > view->model()->columnCount()); + return i; +} + +int QAccessibleTree::childCount() const +{ + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + if (!view->model()) + return 0; + + int hHeader = horizontalHeader() ? 1 : 0; + return (treeView->d_func()->viewItems.count() + hHeader)* view->model()->columnCount(); +} + +int QAccessibleTree::rowCount() const +{ + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + return treeView->d_func()->viewItems.count(); +} + +int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const +{ + if (iface->role(0) == QAccessible::TreeItem) { + const QAccessibleTable2Cell* cell = static_cast(iface); + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + int row = treeView->d_func()->viewIndex(cell->m_index) + (horizontalHeader() ? 1 : 0); + int column = cell->m_index.column(); + + int index = row * view->model()->columnCount() + column + 1; + //qDebug() << "QAccessibleTree::indexOfChild r " << row << " c " << column << "index " << index; + Q_ASSERT(index > treeView->model()->columnCount()); + return index; + } else if (iface->role(0) == QAccessible::ColumnHeader){ + const QAccessibleTable2HeaderCell* cell = static_cast(iface); + //qDebug() << "QAccessibleTree::indexOfChild header " << cell->index << "is: " << cell->index + 1; + return cell->index + 1; + } else { + qWarning() << "WARNING QAccessibleTable2::indexOfChild invalid child" + << iface->role(0) << iface->text(QAccessible::Name, 0); + } + // FIXME: add scrollbars and don't just ignore them + return -1; +} + +int QAccessibleTree::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + switch (relation) { + case QAccessible::Child: { + Q_ASSERT(index > 0); + --index; + int hHeader = horizontalHeader() ? 1 : 0; + + if (hHeader) { + if (index < view->model()->columnCount()) { + *iface = new QAccessibleTable2HeaderCell(view, index, Qt::Horizontal); + return 0; + } else { + index -= view->model()->columnCount(); + } + } + + int row = index / view->model()->columnCount(); + int column = index % view->model()->columnCount(); + QModelIndex modelIndex = indexFromLogical(row, column); + if (modelIndex.isValid()) { + *iface = cell(modelIndex); + return 0; + } + return -1; + } + default: + break; + } + return QAccessibleTable2::navigate(relation, index, iface); +} + +QAccessible::Relation QAccessibleTree::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +QAccessibleTable2CellInterface *QAccessibleTree::cellAt(int row, int column) const +{ + QModelIndex index = indexFromLogical(row, column); + if (!index.isValid()) { + qWarning() << "Requested invalid tree cell: " << row << column; + return 0; + } + return new QAccessibleTable2Cell(view, index, cellRole()); +} + +QString QAccessibleTree::rowDescription(int) const +{ + return QString(); // no headers for rows in trees +} + +bool QAccessibleTree::isRowSelected(int row) const +{ + QModelIndex index = indexFromLogical(row); + return view->selectionModel()->isRowSelected(index.row(), index.parent()); +} + +bool QAccessibleTree::selectRow(int row) +{ + QModelIndex index = indexFromLogical(row); + if (!index.isValid() || view->selectionMode() & QAbstractItemView::NoSelection) + return false; + view->selectionModel()->select(index, QItemSelectionModel::Select); + return true; +} + +// TABLE CELL + +QAccessibleTable2Cell::QAccessibleTable2Cell(QAbstractItemView *view_, const QModelIndex &index_, QAccessible::Role role_) + : /* QAccessibleSimpleEditableTextInterface(this), */ view(view_), m_index(index_), m_role(role_) +{ + Q_ASSERT(index_.isValid()); +} + +int QAccessibleTable2Cell::columnExtent() const { return 1; } +int QAccessibleTable2Cell::rowExtent() const { return 1; } + +QList QAccessibleTable2Cell::rowHeaderCells() const +{ + QList headerCell; + if (verticalHeader()) { + headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.row(), Qt::Vertical)); + } + return headerCell; +} + +QList QAccessibleTable2Cell::columnHeaderCells() const +{ + QList headerCell; + if (horizontalHeader()) { + headerCell.append(new QAccessibleTable2HeaderCell(view, m_index.column(), Qt::Horizontal)); + } + return headerCell; +} + +QHeaderView *QAccessibleTable2Cell::horizontalHeader() const +{ + QHeaderView *header = 0; + + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + header = tv->horizontalHeader(); +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + + return header; +} + +QHeaderView *QAccessibleTable2Cell::verticalHeader() const +{ + QHeaderView *header = 0; +#ifndef QT_NO_TABLEVIEW + if (const QTableView *tv = qobject_cast(view)) + header = tv->verticalHeader(); +#endif + return header; +} + +int QAccessibleTable2Cell::columnIndex() const +{ + return m_index.column(); +} + +int QAccessibleTable2Cell::rowIndex() const +{ + if (role(0) == QAccessible::TreeItem) { + const QTreeView *treeView = qobject_cast(view); + Q_ASSERT(treeView); + int row = treeView->d_func()->viewIndex(m_index); + return row; + } + return m_index.row(); +} + +bool QAccessibleTable2Cell::isSelected() const +{ + return view->selectionModel()->isSelected(m_index); +} + +void QAccessibleTable2Cell::rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const +{ + *row = m_index.row(); + *column = m_index.column(); + *rowExtents = 1; + *columnExtents = 1; + *selected = isSelected(); +} + +QAccessibleTable2Interface* QAccessibleTable2Cell::table() const +{ + return QAccessible::queryAccessibleInterface(view)->table2Interface(); +} + +QAccessible::Role QAccessibleTable2Cell::role(int child) const +{ + Q_ASSERT(child == 0); + return m_role; +} + +QAccessible::State QAccessibleTable2Cell::state(int child) const +{ + Q_ASSERT(child == 0); + State st = Normal; + + QRect globalRect = view->rect(); + globalRect.translate(view->mapToGlobal(QPoint(0,0))); + if (!globalRect.intersects(rect(0))) + st |= Invisible; + + if (view->selectionModel()->isSelected(m_index)) + st |= Selected; + if (view->selectionModel()->currentIndex() == m_index) + st |= Focused; + if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked) + st |= Checked; + + Qt::ItemFlags flags = m_index.flags(); + if (flags & Qt::ItemIsSelectable) { + st |= Selectable; + st |= Focusable; + if (view->selectionMode() == QAbstractItemView::MultiSelection) + st |= MultiSelectable; + if (view->selectionMode() == QAbstractItemView::ExtendedSelection) + st |= ExtSelectable; + } + if (m_role == QAccessible::TreeItem) { + const QTreeView *treeView = qobject_cast(view); + if (treeView->isExpanded(m_index)) + st |= Expanded; + } + return st; +} + +bool QAccessibleTable2Cell::isExpandable() const +{ + return view->model()->hasChildren(m_index); +} + +QRect QAccessibleTable2Cell::rect(int child) const +{ + Q_ASSERT(child == 0); + + QRect r; + r = view->visualRect(m_index); + + if (!r.isNull()) + r.translate(view->viewport()->mapTo(view, QPoint(0,0))); + r.translate(view->mapToGlobal(QPoint(0, 0))); + return r; +} + +QString QAccessibleTable2Cell::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + QAbstractItemModel *model = view->model(); + QString value; + switch(t) { + case QAccessible::Value: + case QAccessible::Name: + value = model->data(m_index, Qt::AccessibleTextRole).toString(); + if (value.isEmpty()) + value = model->data(m_index, Qt::DisplayRole).toString(); + break; + case QAccessible::Description: + value = model->data(m_index, Qt::AccessibleDescriptionRole).toString(); + break; + default: + break; + } + return value; +} + +void QAccessibleTable2Cell::setText(Text /*t*/, int child, const QString &text) +{ + Q_ASSERT(child == 0); + if (!m_index.flags() & Qt::ItemIsEditable) + return; + view->model()->setData(m_index, text); +} + +bool QAccessibleTable2Cell::isValid() const +{ + if (!m_index.isValid()) { + qDebug() << "Interface is not valid"; + } + + return m_index.isValid(); +} + +int QAccessibleTable2Cell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + if (relation == Ancestor && index == 1) { + if (m_role == QAccessible::TreeItem) { + *iface = new QAccessibleTree(view); + } else { + *iface = new QAccessibleTable2(view); + } + return 0; + } + + *iface = 0; + if (!view) + return -1; + + switch (relation) { + + case Child: { + return -1; + } + case Sibling: + if (index > 0) { + QAccessibleInterface *parent = queryAccessibleInterface(view); + int ret = parent->navigate(QAccessible::Child, index, iface); + delete parent; + if (*iface) + return ret; + } + return -1; + +// From table1 implementation: +// case Up: +// case Down: +// case Left: +// case Right: { +// // This is in the "not so nice" category. In order to find out which item +// // is geometrically around, we have to set the current index, navigate +// // and restore the index as well as the old selection +// view->setUpdatesEnabled(false); +// const QModelIndex oldIdx = view->currentIndex(); +// QList kids = children(); +// const QModelIndex currentIndex = index ? kids.at(index - 1) : QModelIndex(row); +// const QItemSelection oldSelection = view->selectionModel()->selection(); +// view->setCurrentIndex(currentIndex); +// const QModelIndex idx = view->moveCursor(toCursorAction(relation), Qt::NoModifier); +// view->setCurrentIndex(oldIdx); +// view->selectionModel()->select(oldSelection, QItemSelectionModel::ClearAndSelect); +// view->setUpdatesEnabled(true); +// if (!idx.isValid()) +// return -1; + +// if (idx.parent() != row.parent() || idx.row() != row.row()) +// *iface = cell(idx); +// return index ? kids.indexOf(idx) + 1 : 0; } + default: + break; + } + + return -1; +} + +QAccessible::Relation QAccessibleTable2Cell::relationTo(int child, const QAccessibleInterface *other, int otherChild) const +{ + Q_ASSERT(child == 0); + Q_ASSERT(otherChild == 0); + // we only check for parent-child relationships in trees + if (m_role == QAccessible::TreeItem && other->role(0) == QAccessible::TreeItem) { + QModelIndex otherIndex = static_cast(other)->m_index; + // is the other our parent? + if (otherIndex.parent() == m_index) + return QAccessible::Ancestor; + // are we the other's child? + if (m_index.parent() == otherIndex) + return QAccessible::Child; + } + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2Cell::userActionCount(int) const +{ + return 0; +} + +QString QAccessibleTable2Cell::actionText(int, Text, int) const +{ + return QString(); +} + +bool QAccessibleTable2Cell::doAction(int, int, const QVariantList &) +{ + return false; +} + +QAccessibleTable2HeaderCell::QAccessibleTable2HeaderCell(QAbstractItemView *view_, int index_, Qt::Orientation orientation_) + : view(view_), index(index_), orientation(orientation_) +{ + Q_ASSERT(index_ >= 0); +} + +QAccessible::Role QAccessibleTable2HeaderCell::role(int child) const +{ + Q_ASSERT(child == 0); + if (orientation == Qt::Horizontal) + return QAccessible::ColumnHeader; + return QAccessible::RowHeader; +} + +QAccessible::State QAccessibleTable2HeaderCell::state(int child) const +{ + Q_ASSERT(child == 0); + return QAccessible::Normal; +} + +QRect QAccessibleTable2HeaderCell::rect(int child) const +{ + Q_ASSERT(child == 0); + + QHeaderView *header = 0; + if (false) { +#ifndef QT_NO_TABLEVIEW + } else if (const QTableView *tv = qobject_cast(view)) { + if (orientation == Qt::Horizontal) { + header = tv->horizontalHeader(); + } else { + header = tv->verticalHeader(); + } +#endif +#ifndef QT_NO_TREEVIEW + } else if (const QTreeView *tv = qobject_cast(view)) { + header = tv->header(); +#endif + } + QPoint zero = header->mapToGlobal(QPoint(0, 0)); + int sectionSize = header->sectionSize(index); + int sectionPos = header->sectionPosition(index); + return orientation == Qt::Horizontal + ? QRect(zero.x() + sectionPos, zero.y(), sectionSize, header->height()) + : QRect(zero.x(), zero.y() + sectionPos, header->width(), sectionSize); +} + +QString QAccessibleTable2HeaderCell::text(Text t, int child) const +{ + Q_ASSERT(child == 0); + QAbstractItemModel *model = view->model(); + QString value; + switch (t) { + case QAccessible::Value: + case QAccessible::Name: + value = model->headerData(index, orientation, Qt::AccessibleTextRole).toString(); + if (value.isEmpty()) + value = model->headerData(index, orientation, Qt::DisplayRole).toString(); + break; + case QAccessible::Description: + value = model->headerData(index, orientation, Qt::AccessibleDescriptionRole).toString(); + break; + default: + break; + } + return value; +} + +void QAccessibleTable2HeaderCell::setText(Text, int, const QString &) +{ + return; +} + +bool QAccessibleTable2HeaderCell::isValid() const +{ + return true; +} + +int QAccessibleTable2HeaderCell::navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const +{ + if (relation == QAccessible::Ancestor && index == 1) { + if (false) { +#ifndef QT_NO_TREEVIEW + } else if (qobject_cast(view)) { + *iface = new QAccessibleTree(view); + return 0; +#endif + } else { + *iface = new QAccessibleTable2(view); + return 0; + } + } + *iface = 0; + return -1; +} + +QAccessible::Relation QAccessibleTable2HeaderCell::relationTo(int, const QAccessibleInterface *, int) const +{ + return QAccessible::Unrelated; +} + +#ifndef QT_NO_ACTION +int QAccessibleTable2HeaderCell::userActionCount(int) const +{ + return 0; +} + +QString QAccessibleTable2HeaderCell::actionText(int, Text, int) const +{ + return QString(); +} + +bool QAccessibleTable2HeaderCell::doAction(int, int, const QVariantList &) +{ + return false; +} +#endif + + + +#endif + +#endif // QT_NO_ITEMVIEWS + +QT_END_NAMESPACE + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h new file mode 100644 index 0000000..c8492e3 --- /dev/null +++ b/src/plugins/accessible/widgets/itemviews.h @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ACCESSIBLE_ITEMVIEWS_H +#define ACCESSIBLE_ITEMVIEWS_H + +#include +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_ACCESSIBILITY + +#ifndef QT_NO_ITEMVIEWS + +class QAccessibleTable2Cell; +class QAccessibleTable2HeaderCell; + +class QAccessibleTable2: public QAccessibleTable2Interface, public QAccessibleObjectEx +{ + Q_ACCESSIBLE_OBJECT +public: + explicit QAccessibleTable2(QWidget *w); + + virtual ~QAccessibleTable2(); + + QObject *object() const { return view; } + Role role(int child) const; + State state(int child) const; + QString text(Text t, int child) const; + QRect rect(int child) const; + + int childAt(int x, int y) const; + int childCount() const; + int indexOfChild(const QAccessibleInterface *) const; + + int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const; + Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const; + +#ifndef QT_NO_ACTION + int userActionCount(int child) const; + QString actionText(int action, Text t, int child) const; + bool doAction(int action, int child, const QVariantList ¶ms); +#endif + QVariant invokeMethodEx(Method, int, const QVariantList &) { return QVariant(); } + + // table2 interface + virtual QAccessibleTable2CellInterface *cellAt(int row, int column) const; + virtual QAccessibleInterface *caption() const; + virtual QAccessibleInterface *summary() const; + virtual QString columnDescription(int column) const; + virtual QString rowDescription(int row) const; + virtual int columnCount() const; + virtual int rowCount() const; + virtual QAccessible2::TableModelChange modelChange() const; + + // selection + virtual int selectedCellCount() const; + virtual int selectedColumnCount() const; + virtual int selectedRowCount() const; + virtual QList selectedCells() const; + virtual QList selectedColumns() const; + virtual QList selectedRows() const; + virtual bool isColumnSelected(int column) const; + virtual bool isRowSelected(int row) const; + virtual bool selectRow(int row); + virtual bool selectColumn(int column); + virtual bool unselectRow(int row); + virtual bool unselectColumn(int column); + +protected: + virtual void modelReset(); + virtual void rowsInserted(const QModelIndex &parent, int first, int last); + virtual void rowsRemoved(const QModelIndex &parent, int first, int last); + virtual void columnsInserted(const QModelIndex &parent, int first, int last); + virtual void columnsRemoved(const QModelIndex &parent, int first, int last); + virtual void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); + virtual void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column); + +protected: + QAbstractItemView* view; + QAccessible2::TableModelChange lastChange; + inline QAccessibleTable2Cell *cell(const QModelIndex &index) const; + inline QAccessible::Role cellRole() const { + switch (m_role) { + case QAccessible::List: + return QAccessible::ListItem; + case QAccessible::Table: + return QAccessible::Cell; + case QAccessible::Tree: + return QAccessible::TreeItem; + default: + Q_ASSERT(0); + } + return QAccessible::NoRole; + } + + QHeaderView *horizontalHeader() const; + QHeaderView *verticalHeader() const; +private: + // the child index for a model index + inline int logicalIndex(const QModelIndex &index) const; + // the model index from the child index + QAccessibleInterface *childFromLogical(int logicalIndex) const; + QAccessible::Role m_role; +}; + +class QAccessibleTree :public QAccessibleTable2 +{ +public: + explicit QAccessibleTree(QWidget *w) + : QAccessibleTable2(w) + {} + + virtual ~QAccessibleTree() {} + + int childAt(int x, int y) const; + int childCount() const; + int indexOfChild(const QAccessibleInterface *) const; + + int rowCount() const; + + int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const; + Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const; + + // table2 interface + QAccessibleTable2CellInterface *cellAt(int row, int column) const; + QString rowDescription(int row) const; + bool isRowSelected(int row) const; + bool selectRow(int row); + +private: + QModelIndex indexFromLogical(int row, int column = 0) const; +}; + +class QAccessibleTable2Cell: public QAccessibleTable2CellInterface /*), public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface*/ +{ +public: + QAccessibleTable2Cell(QAbstractItemView *view, const QModelIndex &m_index, QAccessible::Role role); + + QObject *object() const { return 0; } + Role role(int child) const; + State state(int child) const; + QRect rect(int child) const; + bool isValid() const; + + int childAt(int, int) const { return 0; } + int childCount() const { return 0; } + int indexOfChild(const QAccessibleInterface *) const { return -1; } + + QString text(Text t, int child) const; + void setText(Text t, int child, const QString &text); + + int navigate(RelationFlag relation, int m_index, QAccessibleInterface **iface) const; + Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const; + + bool isExpandable() const; + +#ifndef QT_NO_ACTION + int userActionCount(int child) const; + QString actionText(int action, Text t, int child) const; + bool doAction(int action, int child, const QVariantList ¶ms); +#endif + + // cell interface + virtual int columnExtent() const; + virtual QList columnHeaderCells() const; + virtual int columnIndex() const; + virtual int rowExtent() const; + virtual QList rowHeaderCells() const; + virtual int rowIndex() const; + virtual bool isSelected() const; + virtual void rowColumnExtents(int *row, int *column, int *rowExtents, int *columnExtents, bool *selected) const; + virtual QAccessibleTable2Interface* table() const; + +private: + QHeaderView *verticalHeader() const; + QHeaderView *horizontalHeader() const; + QAbstractItemView *view; + QModelIndex m_index; + QAccessible::Role m_role; + +friend class QAccessibleTable2; +friend class QAccessibleTree; +}; + + +class QAccessibleTable2HeaderCell: public QAccessibleInterface /*), public QAccessibleTextInterface, public QAccessibleSimpleEditableTextInterface*/ +{ +public: + // For header cells, pass the header view in addition + QAccessibleTable2HeaderCell(QAbstractItemView *view, int index, Qt::Orientation orientation); + + QObject *object() const { return 0; } + Role role(int child) const; + State state(int child) const; + QRect rect(int child) const; + bool isValid() const; + + int childAt(int, int) const { return 0; } + int childCount() const { return 0; } + int indexOfChild(const QAccessibleInterface *) const { return -1; } + + QString text(Text t, int child) const; + void setText(Text t, int child, const QString &text); + + int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const; + Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const; + +#ifndef QT_NO_ACTION + int userActionCount(int child) const; + QString actionText(int action, Text t, int child) const; + bool doAction(int action, int child, const QVariantList ¶ms); +#endif + +private: + QAbstractItemView *view; + int index; + Qt::Orientation orientation; + +friend class QAccessibleTable2; +friend class QAccessibleTree; +}; + +// This is the corner button on the top left of a table. +// It can be used to select all cells or it is not active at all. +// For now it is ignored. +class QAccessibleTable2CornerButton: public QAccessibleInterface +{ +public: + QAccessibleTable2CornerButton(QAbstractItemView *view_) + :view(view_) + {} + + QObject *object() const { return 0; } + Role role(int child) const { Q_ASSERT(child == 0); return QAccessible::Pane; } + State state(int child) const { Q_ASSERT(child == 0); return QAccessible::Normal; } + QRect rect(int child) const { Q_ASSERT(child == 0); return QRect(); } + bool isValid() const { return true; } + + int childAt(int, int) const { return 0; } + int childCount() const { return 0; } + int indexOfChild(const QAccessibleInterface *) const { return -1; } + + QString text(Text, int) const { return QString(); } + void setText(Text, int, const QString &) {} + + int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const + { + if (relation == QAccessible::Ancestor && index == 1) { + *iface = QAccessible::queryAccessibleInterface(view); + return 0; + } + return -1; + } + Relation relationTo(int, const QAccessibleInterface *, int) const + { + return QAccessible::Unrelated; + } + +#ifndef QT_NO_ACTION + int userActionCount(int) const { return 0; } + QString actionText(int, Text, int) const { return QString(); } + bool doAction(int, int, const QVariantList &) { return false; } +#endif +private: + QAbstractItemView *view; +}; + + +#endif + +#endif // QT_NO_ACCESSIBILITY + +QT_END_NAMESPACE + +#endif // ACCESSIBLE_ITEMVIEWS_H diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp index aa5459c..cd17a6e 100644 --- a/src/plugins/accessible/widgets/main.cpp +++ b/src/plugins/accessible/widgets/main.cpp @@ -44,11 +44,13 @@ #include "simplewidgets.h" #include "rangecontrols.h" #include "complexwidgets.h" +#include "itemviews.h" #include #include #include #include +#include #include #include @@ -56,6 +58,7 @@ QT_BEGIN_NAMESPACE + class AccessibleFactory : public QAccessiblePlugin { public: @@ -251,6 +254,22 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec iface = new QAccessibleMenu(widget); #endif #ifndef QT_NO_ITEMVIEWS +#ifdef Q_WS_X11 + } else if (classname == QLatin1String("QAbstractItemView")) { + if (qobject_cast(widget)) { + iface = new QAccessibleTree(widget); + } else { + iface = new QAccessibleTable2(widget); + } + } else if (classname == QLatin1String("QWidget") + && widget->objectName() == QLatin1String("qt_scrollarea_viewport") + && qobject_cast(widget->parentWidget())) { + if (qobject_cast(widget->parentWidget())) { + iface = new QAccessibleTree(widget->parentWidget()); + } else { + iface = new QAccessibleTable2(widget->parentWidget()); + } +#else } else if (classname == QLatin1String("QHeaderView")) { iface = new QAccessibleHeader(widget); } else if (classname == QLatin1String("QAbstractItemView")) { @@ -259,7 +278,8 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec && widget->objectName() == QLatin1String("qt_scrollarea_viewport") && qobject_cast(widget->parentWidget())) { iface = new QAccessibleItemView(widget); -#endif +#endif // Q_WS_X11 +#endif // QT_NO_ITEMVIEWS #ifndef QT_NO_TABBAR } else if (classname == QLatin1String("QTabBar")) { iface = new QAccessibleTabBar(widget); diff --git a/src/plugins/accessible/widgets/widgets.pro b/src/plugins/accessible/widgets/widgets.pro index 79110cb..9632f41 100644 --- a/src/plugins/accessible/widgets/widgets.pro +++ b/src/plugins/accessible/widgets/widgets.pro @@ -7,14 +7,18 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/accessible QTDIR_build:REQUIRES += "contains(QT_CONFIG, accessibility)" SOURCES += main.cpp \ - simplewidgets.cpp \ - rangecontrols.cpp \ - complexwidgets.cpp \ - qaccessiblewidgets.cpp \ - qaccessiblemenu.cpp + simplewidgets.cpp \ + rangecontrols.cpp \ + complexwidgets.cpp \ + qaccessiblewidgets.cpp \ + qaccessiblemenu.cpp \ + itemviews.cpp HEADERS += qaccessiblewidgets.h \ - simplewidgets.h \ - rangecontrols.h \ - complexwidgets.h \ - qaccessiblemenu.h + simplewidgets.h \ + rangecontrols.h \ + complexwidgets.h \ + qaccessiblemenu.h \ + itemviews.h + + diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index d764187..f8d6b6d 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -270,6 +270,9 @@ private slots: void scrollAreaTest(); void tableWidgetTest(); void tableViewTest(); + void table2ListTest(); + void table2TreeTest(); + void table2TableTest(); void calendarWidgetTest(); void dockWidgetTest(); void pushButtonTest(); @@ -3725,6 +3728,311 @@ void tst_QAccessibility::tableViewTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::table2ListTest() +{ + QListWidget listView; + listView.addItem("Oslo"); + listView.addItem("Berlin"); + listView.addItem("Brisbane"); + listView.resize(400,400); + listView.show(); + QTest::qWait(1); // Need this for indexOfchild to work. +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&listView); + QTest::qWait(100); +#endif + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + + QCOMPARE((int)iface->role(0), (int)QAccessible::List); + QCOMPARE(iface->childCount(), 3); + + QAccessibleInterface *child1 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 1, &child1), 0); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 1); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("Oslo")); + QCOMPARE(child1->role(0), QAccessible::ListItem); + delete child1; + + QAccessibleInterface *child2 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 2, &child2), 0); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 2); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("Berlin")); + delete child2; + + QAccessibleInterface *child3 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 3, &child3), 0); + QVERIFY(child3); + QCOMPARE(iface->indexOfChild(child3), 3); + QCOMPARE(child3->text(QAccessible::Name, 0), QString("Brisbane")); + delete child3; + QTestAccessibility::clearEvents(); + + // Check for events + QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(1)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 2, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 2, QAccessible::Focus))); + QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(2)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 3, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 3, QAccessible::Focus))); + + listView.addItem("Munich"); + QCOMPARE(iface->childCount(), 4); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 1); + QCOMPARE(table2->rowCount(), 4); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Oslo")); + QAccessibleTable2CellInterface *cell4; + QVERIFY(cell4 = table2->cellAt(3,0)); + QCOMPARE(cell4->text(QAccessible::Name, 0), QString("Munich")); + QCOMPARE(cell4->role(0), QAccessible::ListItem); + QCOMPARE(cell4->rowIndex(), 3); + QCOMPARE(cell4->columnIndex(), 0); + QVERIFY(!cell4->isExpandable()); + + delete cell4; + delete cell1; + + delete iface; + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::table2TreeTest() +{ + QTreeWidget treeView; + treeView.setColumnCount(2); + QTreeWidgetItem *header = new QTreeWidgetItem; + header->setText(0, "Artist"); + header->setText(1, "Work"); + treeView.setHeaderItem(header); + + QTreeWidgetItem *root1 = new QTreeWidgetItem; + root1->setText(0, "Spain"); + treeView.addTopLevelItem(root1); + + QTreeWidgetItem *item1 = new QTreeWidgetItem; + item1->setText(0, "Picasso"); + item1->setText(1, "Guernica"); + root1->addChild(item1); + + QTreeWidgetItem *item2 = new QTreeWidgetItem; + item2->setText(0, "Tapies"); + item2->setText(1, "Ambrosia"); + root1->addChild(item2); + + QTreeWidgetItem *root2 = new QTreeWidgetItem; + root2->setText(0, "Austria"); + treeView.addTopLevelItem(root2); + + QTreeWidgetItem *item3 = new QTreeWidgetItem; + item3->setText(0, "Klimt"); + item3->setText(1, "The Kiss"); + root2->addChild(item3); + + treeView.resize(400,400); + treeView.show(); + QTest::qWait(1); // Need this for indexOfchild to work. +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&treeView); + QTest::qWait(100); +#endif + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&treeView); + + QCOMPARE((int)iface->role(0), (int)QAccessible::Tree); + // header and 2 rows (the others are not expanded, thus not visible) + QCOMPARE(iface->childCount(), 6); + + QAccessibleInterface *header1 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 1, &header1), 0); + QVERIFY(header1); + QCOMPARE(iface->indexOfChild(header1), 1); + QCOMPARE(header1->text(QAccessible::Name, 0), QString("Artist")); + QCOMPARE(header1->role(0), QAccessible::ColumnHeader); + delete header1; + + QAccessibleInterface *child1 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 3, &child1), 0); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 3); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("Spain")); + QCOMPARE(child1->role(0), QAccessible::TreeItem); + QVERIFY(!(child1->state(0) & QAccessible::Expanded)); + delete child1; + + QAccessibleInterface *child2 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 5, &child2), 0); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 5); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("Austria")); + delete child2; + + QTestAccessibility::clearEvents(); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 2); + QCOMPARE(table2->rowCount(), 2); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Spain")); + QAccessibleTable2CellInterface *cell2; + QVERIFY(cell2 = table2->cellAt(1,0)); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Austria")); + QCOMPARE(cell2->role(0), QAccessible::TreeItem); + QCOMPARE(cell2->rowIndex(), 1); + QCOMPARE(cell2->columnIndex(), 0); + QVERIFY(cell2->isExpandable()); + QCOMPARE(iface->indexOfChild(cell2), 5); + QVERIFY(!(cell2->state(0) & QAccessible::Expanded)); + QCOMPARE(table2->columnDescription(1), QString("Work")); + delete cell2; + delete cell1; + + treeView.expandAll(); + + QTest::qWait(1); // Need this for indexOfchild to work. +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&treeView); + QTest::qWait(100); +#endif +// QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&treeView, 0, QAccessible::TableModelChanged))); + + QCOMPARE(table2->columnCount(), 2); + QCOMPARE(table2->rowCount(), 5); + cell1 = table2->cellAt(1,0); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Picasso")); + QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item + + cell2 = table2->cellAt(4,0); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Klimt")); + QCOMPARE(cell2->role(0), QAccessible::TreeItem); + QCOMPARE(cell2->rowIndex(), 4); + QCOMPARE(cell2->columnIndex(), 0); + QVERIFY(!cell2->isExpandable()); + QCOMPARE(iface->indexOfChild(cell2), 11); + + QCOMPARE(table2->columnDescription(0), QString("Artist")); + QCOMPARE(table2->columnDescription(1), QString("Work")); + + delete iface; + QTestAccessibility::clearEvents(); +} + + +void tst_QAccessibility::table2TableTest() +{ + QTableWidget tableView(3, 3); + tableView.setColumnCount(3); + QStringList hHeader; + hHeader << "h1" << "h2" << "h3"; + tableView.setHorizontalHeaderLabels(hHeader); + + QStringList vHeader; + vHeader << "v1" << "v2" << "v3"; + tableView.setVerticalHeaderLabels(vHeader); + + for (int i = 0; i<9; ++i) { + QTableWidgetItem *item = new QTableWidgetItem; + item->setText(QString::number(i/3) + QString(".") + QString::number(i%3)); + tableView.setItem(i/3, i%3, item); + } + + tableView.resize(600,600); + tableView.show(); + QTest::qWait(1); // Need this for indexOfchild to work. +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&tableView); + QTest::qWait(100); +#endif + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&tableView); + + QCOMPARE((int)iface->role(0), (int)QAccessible::Table); + // header and 2 rows (the others are not expanded, thus not visible) + QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button + + QAccessibleInterface *cornerButton = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 1, &cornerButton), 0); + QVERIFY(cornerButton); + QCOMPARE(iface->indexOfChild(cornerButton), 1); + QCOMPARE(cornerButton->role(0), QAccessible::PushButton); + delete cornerButton; + + QAccessibleInterface *child1 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 3, &child1), 0); + QVERIFY(child1); + QCOMPARE(iface->indexOfChild(child1), 3); + QCOMPARE(child1->text(QAccessible::Name, 0), QString("h2")); + QCOMPARE(child1->role(0), QAccessible::ColumnHeader); + QVERIFY(!(child1->state(0) & QAccessible::Expanded)); + delete child1; + + QAccessibleInterface *child2 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 11, &child2), 0); + QVERIFY(child2); + QCOMPARE(iface->indexOfChild(child2), 11); + QCOMPARE(child2->text(QAccessible::Name, 0), QString("1.1")); + QAccessibleTable2CellInterface *cell2Iface = static_cast(child2); + QCOMPARE(cell2Iface->rowIndex(), 1); + QCOMPARE(cell2Iface->columnIndex(), 1); + delete child2; + + QAccessibleInterface *child3 = 0; + QCOMPARE(iface->navigate(QAccessible::Child, 12, &child3), 0); + QCOMPARE(iface->indexOfChild(child3), 12); + QCOMPARE(child3->text(QAccessible::Name, 0), QString("1.2")); + delete child3; + + QTestAccessibility::clearEvents(); + + // table 2 + QAccessibleTable2Interface *table2 = iface->table2Interface(); + QVERIFY(table2); + QCOMPARE(table2->columnCount(), 3); + QCOMPARE(table2->rowCount(), 3); + QAccessibleTable2CellInterface *cell1; + QVERIFY(cell1 = table2->cellAt(0,0)); + QCOMPARE(cell1->text(QAccessible::Name, 0), QString("0.0")); + QCOMPARE(iface->indexOfChild(cell1), 6); + + QAccessibleTable2CellInterface *cell2; + QVERIFY(cell2 = table2->cellAt(0,1)); + QCOMPARE(cell2->text(QAccessible::Name, 0), QString("0.1")); + QCOMPARE(cell2->role(0), QAccessible::Cell); + QCOMPARE(cell2->rowIndex(), 0); + QCOMPARE(cell2->columnIndex(), 1); + QCOMPARE(iface->indexOfChild(cell2), 7); + delete cell2; + + QAccessibleTable2CellInterface *cell3; + QVERIFY(cell3 = table2->cellAt(1,2)); + QCOMPARE(cell3->text(QAccessible::Name, 0), QString("1.2")); + QCOMPARE(cell3->role(0), QAccessible::Cell); + QCOMPARE(cell3->rowIndex(), 1); + QCOMPARE(cell3->columnIndex(), 2); + QCOMPARE(iface->indexOfChild(cell3), 12); + delete cell3; + + QCOMPARE(table2->columnDescription(0), QString("h1")); + QCOMPARE(table2->columnDescription(1), QString("h2")); + QCOMPARE(table2->columnDescription(2), QString("h3")); + QCOMPARE(table2->rowDescription(0), QString("v1")); + QCOMPARE(table2->rowDescription(1), QString("v2")); + QCOMPARE(table2->rowDescription(2), QString("v3")); + + delete iface; + QTestAccessibility::clearEvents(); +} + void tst_QAccessibility::calendarWidgetTest() { #ifndef QT_NO_CALENDARWIDGET -- cgit v0.12 From eff5ecc5d8f65fa25d6cfd6ed96a9d2a00d0c663 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 13 Jul 2011 16:53:01 +0200 Subject: Style cleanup - space after flow control keywords. Reviewed-by: TrustMe --- src/plugins/accessible/widgets/itemviews.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index d7432e9..4618f87 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -284,7 +284,7 @@ QList QAccessibleTable2::selectedCells() const QList QAccessibleTable2::selectedColumns() const { QList columns; - Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedColumns()) { + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedColumns()) { columns.append(index.column()); } return columns; @@ -293,7 +293,7 @@ QList QAccessibleTable2::selectedColumns() const QList QAccessibleTable2::selectedRows() const { QList rows; - Q_FOREACH(const QModelIndex &index, view->selectionModel()->selectedRows()) { + Q_FOREACH (const QModelIndex &index, view->selectionModel()->selectedRows()) { rows.append(index.row()); } return rows; @@ -773,7 +773,7 @@ QString QAccessibleTable2Cell::text(Text t, int child) const Q_ASSERT(child == 0); QAbstractItemModel *model = view->model(); QString value; - switch(t) { + switch (t) { case QAccessible::Value: case QAccessible::Name: value = model->data(m_index, Qt::AccessibleTextRole).toString(); -- cgit v0.12 From 8226f869250a67e33e1f3b5ddba73975c85b6794 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jun 2011 19:04:24 +0200 Subject: fix argument quoting on windows quotes prefixed with multiple backslashes would not be escaped correctly. --- src/corelib/io/qprocess_win.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 1761c0e..dba3de4 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -256,10 +257,8 @@ static QString qt_create_commandline(const QString &program, const QStringList & for (int i=0; i Date: Thu, 30 Jun 2011 19:05:57 +0200 Subject: make argument quoting code on windows less arcane --- src/corelib/io/qprocess_win.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index dba3de4..510f723 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -263,16 +263,13 @@ static QString qt_create_commandline(const QString &program, const QStringList & // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" - QString endQuote(QLatin1Char('\"')); int i = tmp.length(); - while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) { + while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) --i; - endQuote += QLatin1Char('\\'); - } - args += QLatin1String(" \"") + tmp.left(i) + endQuote; - } else { - args += QLatin1Char(' ') + tmp; + tmp.insert(i, QLatin1Char('"')); + tmp.prepend(QLatin1Char('"')); } + args += QLatin1Char(' ') + tmp; } return args; } -- cgit v0.12 From d29876008fad400bca8d6b37e5d5f61dd1bcb39d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 09:40:06 +0200 Subject: Fix autotest for accessible tables. The new table2 interface is ifdef'ed to only be used on X11. This adapts the auto test. Improve handling of accessible events and clean up. There are two xfails for the Table and Tree where sibling navigation is not implemented yet. Reviewed-by: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 147 +++++++++++++++-------- 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index f8d6b6d..2db9f75 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -190,7 +190,8 @@ static int verifyHierarchy(QAccessibleInterface *iface) if (middleChild) { entry = if2->navigate(QAccessible::Sibling, middle, &if3); EXPECT(entry == 0 && if3->object() == middleChild->object()); - delete if3; + if (entry == 0) + delete if3; EXPECT(iface->indexOfChild(middleChild) == middle); } @@ -307,6 +308,10 @@ QString eventName(const int ev) case 0x0012: return "ScrollingStart"; case 0x0013: return "ScrollingEnd"; case 0x0018: return "MenuCommand"; + + case 0x0116: return "TableModelChanged"; + case 0x011B: return "TextCaretMoved"; + case 0x8000: return "ObjectCreated"; case 0x8001: return "ObjectDestroyed"; case 0x8002: return "ObjectShow"; @@ -1755,18 +1760,22 @@ void tst_QAccessibility::applicationTest() void tst_QAccessibility::mainWindowTest() { - QMainWindow mw; - mw.resize(300, 200); - mw.show(); // triggers layout + QMainWindow *mw = new QMainWindow; + mw->resize(300, 200); + mw->show(); // triggers layout QLatin1String name = QLatin1String("I am the main window"); - mw.setWindowTitle(name); - QTest::qWaitForWindowShown(&mw); + mw->setWindowTitle(name); + QTest::qWaitForWindowShown(mw); + QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mw); + QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw); QCOMPARE(interface->text(QAccessible::Name, 0), name); QCOMPARE(interface->role(0), QAccessible::Window); delete interface; + delete mw; + QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); + QTestAccessibility::clearEvents(); } class CounterButton : public QPushButton { @@ -2752,9 +2761,12 @@ void tst_QAccessibility::textBrowserTest() void tst_QAccessibility::listViewTest() { +#if defined(Q_WS_X11) + QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll); +#else { QListView listView; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); QVERIFY(iface); QCOMPARE(iface->childCount(), 1); delete iface; @@ -2768,11 +2780,11 @@ void tst_QAccessibility::listViewTest() listView.show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&listView); + qt_x11_wait_for_window_manager(listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); QCOMPARE((int)iface->role(0), (int)QAccessible::Client); QCOMPARE((int)iface->role(1), (int)QAccessible::List); QCOMPARE(iface->childCount(), 1); @@ -2817,6 +2829,7 @@ void tst_QAccessibility::listViewTest() } QTestAccessibility::clearEvents(); +#endif } @@ -3071,9 +3084,11 @@ void tst_QAccessibility::lineEditTest() le3->deselect(); le3->setCursorPosition(3); QCOMPARE(textIface->cursorPosition(), 3); + QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved))); QCOMPARE(textIface->selectionCount(), 0); - int start, end; + QTestAccessibility::clearEvents(); + int start, end; QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always")); QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I")); QCOMPARE(start, 0); @@ -3116,6 +3131,7 @@ void tst_QAccessibility::lineEditTest() delete iface; delete toplevel; + QTestAccessibility::clearEvents(); } void tst_QAccessibility::workspaceTest() @@ -3526,6 +3542,9 @@ void tst_QAccessibility::scrollAreaTest() void tst_QAccessibility::tableWidgetTest() { +#if defined(Q_WS_X11) + QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll); +#else { QWidget *topLevel = new QWidget; QTableWidget *w = new QTableWidget(8,4,topLevel); @@ -3565,6 +3584,7 @@ void tst_QAccessibility::tableWidgetTest() delete topLevel; } QTestAccessibility::clearEvents(); +#endif } class QtTestTableModel: public QAbstractTableModel @@ -3647,6 +3667,9 @@ public: void tst_QAccessibility::tableViewTest() { +#if defined(Q_WS_X11) + QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll); +#else { QtTestTableModel *model = new QtTestTableModel(3, 4); QTableView *w = new QTableView(); @@ -3726,23 +3749,28 @@ void tst_QAccessibility::tableViewTest() delete model; } QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2ListTest() { - QListWidget listView; - listView.addItem("Oslo"); - listView.addItem("Berlin"); - listView.addItem("Brisbane"); - listView.resize(400,400); - listView.show(); +#if !defined(Q_WS_X11) + QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll); +#else + QListWidget *listView = new QListWidget; + listView->addItem("Oslo"); + listView->addItem("Berlin"); + listView->addItem("Brisbane"); + listView->resize(400,400); + listView->show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&listView); + qt_x11_wait_for_window_manager(listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QCOMPARE(verifyHierarchy(iface), 0); QCOMPARE((int)iface->role(0), (int)QAccessible::List); QCOMPARE(iface->childCount(), 3); @@ -3771,14 +3799,14 @@ void tst_QAccessibility::table2ListTest() QTestAccessibility::clearEvents(); // Check for events - QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(1)).center()); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 2, QAccessible::Selection))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 2, QAccessible::Focus))); - QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(2)).center()); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 3, QAccessible::Selection))); - QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&listView, 3, QAccessible::Focus))); - - listView.addItem("Munich"); + QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus))); + QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center()); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection))); + QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus))); + + listView->addItem("Munich"); QCOMPARE(iface->childCount(), 4); // table 2 @@ -3799,23 +3827,27 @@ void tst_QAccessibility::table2ListTest() delete cell4; delete cell1; - delete iface; + delete listView; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2TreeTest() { - QTreeWidget treeView; - treeView.setColumnCount(2); +#if !defined(Q_WS_X11) + QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll); +#else + QTreeWidget *treeView = new QTreeWidget; + treeView->setColumnCount(2); QTreeWidgetItem *header = new QTreeWidgetItem; header->setText(0, "Artist"); header->setText(1, "Work"); - treeView.setHeaderItem(header); + treeView->setHeaderItem(header); QTreeWidgetItem *root1 = new QTreeWidgetItem; root1->setText(0, "Spain"); - treeView.addTopLevelItem(root1); + treeView->addTopLevelItem(root1); QTreeWidgetItem *item1 = new QTreeWidgetItem; item1->setText(0, "Picasso"); @@ -3829,22 +3861,24 @@ void tst_QAccessibility::table2TreeTest() QTreeWidgetItem *root2 = new QTreeWidgetItem; root2->setText(0, "Austria"); - treeView.addTopLevelItem(root2); + treeView->addTopLevelItem(root2); QTreeWidgetItem *item3 = new QTreeWidgetItem; item3->setText(0, "Klimt"); item3->setText(1, "The Kiss"); root2->addChild(item3); - treeView.resize(400,400); - treeView.show(); + treeView->resize(400,400); + treeView->show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&treeView); + qt_x11_wait_for_window_manager(treeView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&treeView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView); + QEXPECT_FAIL("", "Implement Sibling navigation for table2 cells.", Continue); + QCOMPARE(verifyHierarchy(iface), 0); QCOMPARE((int)iface->role(0), (int)QAccessible::Tree); // header and 2 rows (the others are not expanded, thus not visible) @@ -3897,14 +3931,13 @@ void tst_QAccessibility::table2TreeTest() delete cell2; delete cell1; - treeView.expandAll(); + treeView->expandAll(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&treeView); + qt_x11_wait_for_window_manager(treeView); QTest::qWait(100); #endif -// QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(&treeView, 0, QAccessible::TableModelChanged))); QCOMPARE(table2->columnCount(), 2); QCOMPARE(table2->rowCount(), 5); @@ -3925,36 +3958,42 @@ void tst_QAccessibility::table2TreeTest() delete iface; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::table2TableTest() { - QTableWidget tableView(3, 3); - tableView.setColumnCount(3); +#if !defined(Q_WS_X11) + QSKIP( "Accessible table2 interface is currently only supported on X11.", SkipAll); +#else + QTableWidget *tableView = new QTableWidget(3, 3); + tableView->setColumnCount(3); QStringList hHeader; hHeader << "h1" << "h2" << "h3"; - tableView.setHorizontalHeaderLabels(hHeader); + tableView->setHorizontalHeaderLabels(hHeader); QStringList vHeader; vHeader << "v1" << "v2" << "v3"; - tableView.setVerticalHeaderLabels(vHeader); + tableView->setVerticalHeaderLabels(vHeader); for (int i = 0; i<9; ++i) { QTableWidgetItem *item = new QTableWidgetItem; item->setText(QString::number(i/3) + QString(".") + QString::number(i%3)); - tableView.setItem(i/3, i%3, item); + tableView->setItem(i/3, i%3, item); } - tableView.resize(600,600); - tableView.show(); + tableView->resize(600,600); + tableView->show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(&tableView); + qt_x11_wait_for_window_manager(tableView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&tableView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView); + QEXPECT_FAIL("", "Implement Sibling navigation for table2 cells.", Continue); + QCOMPARE(verifyHierarchy(iface), 0); QCOMPARE((int)iface->role(0), (int)QAccessible::Table); // header and 2 rows (the others are not expanded, thus not visible) @@ -3964,7 +4003,7 @@ void tst_QAccessibility::table2TableTest() QCOMPARE(iface->navigate(QAccessible::Child, 1, &cornerButton), 0); QVERIFY(cornerButton); QCOMPARE(iface->indexOfChild(cornerButton), 1); - QCOMPARE(cornerButton->role(0), QAccessible::PushButton); + QCOMPARE(cornerButton->role(0), QAccessible::Pane); delete cornerButton; QAccessibleInterface *child1 = 0; @@ -4030,7 +4069,11 @@ void tst_QAccessibility::table2TableTest() QCOMPARE(table2->rowDescription(2), QString("v3")); delete iface; + + delete tableView; + QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::calendarWidgetTest() @@ -4288,6 +4331,9 @@ void tst_QAccessibility::comboBoxTest() void tst_QAccessibility::treeWidgetTest() { +#if defined(Q_WS_X11) + QSKIP( "Accessible table1 interface is no longer supported on X11.", SkipAll); +#else QWidget *w = new QWidget; QTreeWidget *tree = new QTreeWidget(w); QHBoxLayout *l = new QHBoxLayout(w); @@ -4345,6 +4391,7 @@ void tst_QAccessibility::treeWidgetTest() delete w; QTestAccessibility::clearEvents(); +#endif } void tst_QAccessibility::labelTest() -- cgit v0.12 From 63b4e11ca2e7211e2a444de54eff3a3e233d64ce Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Thu, 14 Jul 2011 11:11:03 +0200 Subject: Documentation fix. Fixes: QTBUG-20390 --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 7014571..3fd4fcd 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -560,13 +560,11 @@ QRect QDeclarativeTextInput::cursorRectangle() const \qmlproperty int TextInput::selectionStart The cursor position before the first character in the current selection. - Setting this and selectionEnd allows you to specify a selection in the - text edit. - Note that if selectionStart == selectionEnd then there is no current - selection. + This property is read-only. To change the selection, use select(start,end), + selectAll(), or selectWord(). - \sa selectionEnd, cursorPosition, selectedText, select() + \sa selectionEnd, cursorPosition, selectedText */ int QDeclarativeTextInput::selectionStart() const { @@ -578,13 +576,11 @@ int QDeclarativeTextInput::selectionStart() const \qmlproperty int TextInput::selectionEnd The cursor position after the last character in the current selection. - Setting this and selectionStart allows you to specify a selection in the - text edit. - Note that if selectionStart == selectionEnd then there is no current - selection. + This property is read-only. To change the selection, use select(start,end), + selectAll(), or selectWord(). - \sa selectionStart, cursorPosition, selectedText, select() + \sa selectionStart, cursorPosition, selectedText */ int QDeclarativeTextInput::selectionEnd() const { -- cgit v0.12 From c68d433f14542485fa602409d0a099602ac04c46 Mon Sep 17 00:00:00 2001 From: Martin Pejcoch Date: Thu, 14 Jul 2011 13:55:15 +0200 Subject: Added Solaris build fix to the changes file. --- dist/changes-4.8.0 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dist/changes-4.8.0 b/dist/changes-4.8.0 index ae6d2c5..1e86803 100644 --- a/dist/changes-4.8.0 +++ b/dist/changes-4.8.0 @@ -156,7 +156,8 @@ Qt for Windows CE **************************************************************************** * Compiler Specific Changes * **************************************************************************** - +- Sun Studio 12 + * Fixed build issues in the OpenGL module on Solaris with CC 5.9. [QTBUG-19641] **************************************************************************** * Tools * -- cgit v0.12 From a1f2b68e97477440cf508e6d497eb5f5d9971971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Mill=C3=A1n=20Soto?= Date: Thu, 14 Jul 2011 14:25:57 +0200 Subject: Call QAccessible::updateAccessibility when setText is called on QLabel The method is called when the text of a label is changed and setAccessibleName has not been called on the label, as the text of the label acts as the accessible name of the label. Merge-request: 1301 Reviewed-by: Frederik Gladhorn --- src/gui/widgets/qlabel.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 26dd0e1..dcf35aa 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -55,6 +55,10 @@ #include "private/qstylesheetstyle_p.h" #include +#ifndef QT_NO_ACCESSIBILITY +#include +#endif + QT_BEGIN_NAMESPACE /*! @@ -370,6 +374,11 @@ void QLabel::setText(const QString &text) #endif d->updateLabel(); + +#ifndef QT_NO_ACCESSIBILITY + if (accessibleName().isEmpty()) + QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged); +#endif } QString QLabel::text() const -- cgit v0.12 From 81036d4be6122dfcb55a4852bcc1037c7d8f7309 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 10:57:02 +0200 Subject: Add constants to QAccessible::Event enum. Reviewed-by: Gabi --- src/gui/accessible/qaccessible.h | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 16869bb..24a6744 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -84,40 +84,40 @@ public: MenuCommand = 0x0018, // Values from IAccessible2 - ActionChanged = 0x0101, - ActiveDescendantChanged, - AttributeChanged, - DocumentContentChanged, - DocumentLoadComplete, - DocumentLoadStopped, - DocumentReload, - HyperlinkEndIndexChanged, - HyperlinkNumberOfAnchorsChanged, - HyperlinkSelectedLinkChanged, - HypertextLinkActivated, - HypertextLinkSelected, - HyperlinkStartIndexChanged, - HypertextChanged, - HypertextNLinksChanged, - ObjectAttributeChanged, - PageChanged, - SectionChanged, - TableCaptionChanged, - TableColumnDescriptionChanged, - TableColumnHeaderChanged, - TableModelChanged, - TableRowDescriptionChanged, - TableRowHeaderChanged, - TableSummaryChanged, - TextAttributeChanged, - TextCaretMoved, - // TextChanged, deprecated, use TextUpdated - TextColumnChanged = TextCaretMoved + 2, - TextInserted, - TextRemoved, - TextUpdated, - TextSelectionChanged, - VisibleDataChanged, + ActionChanged = 0x0101, + ActiveDescendantChanged = 0x0102, + AttributeChanged = 0x0103, + DocumentContentChanged = 0x0104, + DocumentLoadComplete = 0x0105, + DocumentLoadStopped = 0x0106, + DocumentReload = 0x0107, + HyperlinkEndIndexChanged = 0x0108, + HyperlinkNumberOfAnchorsChanged = 0x0109, + HyperlinkSelectedLinkChanged = 0x010A, + HypertextLinkActivated = 0x010B, + HypertextLinkSelected = 0x010C, + HyperlinkStartIndexChanged = 0x010D, + HypertextChanged = 0x010E, + HypertextNLinksChanged = 0x010F, + ObjectAttributeChanged = 0x0110, + PageChanged = 0x0111, + SectionChanged = 0x0112, + TableCaptionChanged = 0x0113, + TableColumnDescriptionChanged = 0x0114, + TableColumnHeaderChanged = 0x0115, + TableModelChanged = 0x0116, + TableRowDescriptionChanged = 0x0117, + TableRowHeaderChanged = 0x0118, + TableSummaryChanged = 0x0119, + TextAttributeChanged = 0x011A, + TextCaretMoved = 0x011B, + // TextChanged = 0x011C, is deprecated in IA2, use TextUpdated + TextColumnChanged = 0x011D, + TextInserted = 0x011E, + TextRemoved = 0x011F, + TextUpdated = 0x0120, + TextSelectionChanged = 0x0121, + VisibleDataChanged = 0x0122, ObjectCreated = 0x8000, ObjectDestroyed = 0x8001, -- cgit v0.12 From 90dac1e856e4d3648ce19ae6b356f9aeb090af49 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Thu, 14 Jul 2011 14:49:55 +0200 Subject: sync qws_dataDir() with coreapp's internal qws_dataDir() Merge-request: 1295 Reviewed-by: Harald Fernengel --- tools/qvfb/qvfbshmem.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tools/qvfb/qvfbshmem.cpp b/tools/qvfb/qvfbshmem.cpp index a03b25d..b05b69c 100644 --- a/tools/qvfb/qvfbshmem.cpp +++ b/tools/qvfb/qvfbshmem.cpp @@ -69,27 +69,40 @@ QT_BEGIN_NAMESPACE // live. static QString qws_dataDir(int qws_display_id) { - QByteArray dataDir = QT_VFB_DATADIR(qws_display_id).toLocal8Bit(); - if (mkdir(dataDir, 0700)) { + static QString result; + if (!result.isEmpty()) + return result; + result = QT_VFB_DATADIR(qws_display_id); + QByteArray dataDir = result.toLocal8Bit(); + +#if defined(Q_OS_INTEGRITY) + /* ensure filesystem is ready before starting requests */ + WaitForFileSystemInitialization(); +#endif + + if (QT_MKDIR(dataDir, 0700)) { if (errno != EEXIST) { qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); } } - struct stat buf; - if (lstat(dataDir, &buf)) + QT_STATBUF buf; + if (QT_LSTAT(dataDir, &buf)) qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData()); if (!S_ISDIR(buf.st_mode)) qFatal("%s is not a directory", dataDir.constData()); + +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_QNX) if (buf.st_uid != getuid()) qFatal("Qt for Embedded Linux data directory is not owned by user %uh", getuid()); if ((buf.st_mode & 0677) != 0600) qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); - dataDir += "/"; +#endif - return QString(dataDir); + result.append(QLatin1Char('/')); + return result; } -- cgit v0.12 From 1093d3363df4260cc738ccc1649d710414f07cb3 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Thu, 14 Jul 2011 14:49:56 +0200 Subject: get rid of unwanted dependencies and unused header includes Merge-request: 1295 Reviewed-by: Harald Fernengel --- tools/qvfb/qvfbmmap.cpp | 2 -- tools/qvfb/qvfbshmem.cpp | 25 ++++++------------------- tools/qvfb/qvfbview.cpp | 5 ----- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/tools/qvfb/qvfbmmap.cpp b/tools/qvfb/qvfbmmap.cpp index 7e80e37..01c1d9c 100644 --- a/tools/qvfb/qvfbmmap.cpp +++ b/tools/qvfb/qvfbmmap.cpp @@ -48,9 +48,7 @@ #include #include #include -#include #include -#include #include #include #include diff --git a/tools/qvfb/qvfbshmem.cpp b/tools/qvfb/qvfbshmem.cpp index b05b69c..c17a680 100644 --- a/tools/qvfb/qvfbshmem.cpp +++ b/tools/qvfb/qvfbshmem.cpp @@ -39,10 +39,9 @@ ** ****************************************************************************/ -#include "qlock_p.h" - #include "qvfbshmem.h" -#include "qvfbhdr.h" +#include +#include #include #include @@ -53,8 +52,6 @@ #include #include #include -#include -#include #include #include #include @@ -143,20 +140,10 @@ QShMemViewProtocol::QShMemViewProtocol(int displayid, const QSize &s, qws_dataDir(displayid); - QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString("QtEmbedded-%1").arg(displayid); - int oldPipeSemkey = ftok(oldPipe.toLatin1().constData(), 'd'); - if (oldPipeSemkey != -1) { - int oldPipeLockId = semget(oldPipeSemkey, 0, 0); - if (oldPipeLockId >= 0){ - sembuf sops; - sops.sem_num = 0; - sops.sem_op = 1; - sops.sem_flg = SEM_UNDO; - int rv; - do { - rv = semop(lockId,&sops,1); - } while (rv == -1 && errno == EINTR); - + { + QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString("QtEmbedded-%1").arg(displayid); + QLock oldPipeLock(oldPipe, 'd', false); + if (oldPipeLock.isValid()) { perror("QShMemViewProtocol::QShMemViewProtocol"); qFatal("Cannot create lock file as an old version of QVFb has " "opened %s. Close other QVFb and try again", diff --git a/tools/qvfb/qvfbview.cpp b/tools/qvfb/qvfbview.cpp index 3f13ecc..91c5380 100644 --- a/tools/qvfb/qvfbview.cpp +++ b/tools/qvfb/qvfbview.cpp @@ -61,12 +61,7 @@ #include #include -#include #include -#include -#include -#include -#include #include #include -- cgit v0.12 From c1788c07deaf4effb5e7c2d2564e7077b9ddcf95 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Thu, 14 Jul 2011 14:49:58 +0200 Subject: fix build both QLock and QWSSignalHandler are imported and must not be compiled-in as this breaks the build process due to unresolved dependencies inside QWSSignalHandler QTBUG: 20236 Merge-request: 1295 Reviewed-by: Harald Fernengel --- tools/qvfb/qvfb.pro | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro index c101d00..29ce202 100644 --- a/tools/qvfb/qvfb.pro +++ b/tools/qvfb/qvfb.pro @@ -8,9 +8,6 @@ DESTDIR = ../../bin target.path=$$[QT_INSTALL_BINS] INSTALLS += target -DEPENDPATH = ../../include -INCLUDEPATH += ../../src/gui/embedded - FORMS = config.ui HEADERS = qvfb.h \ qvfbview.h \ @@ -19,10 +16,7 @@ HEADERS = qvfb.h \ gammaview.h \ qvfbprotocol.h \ qvfbshmem.h \ - qvfbmmap.h \ - ../../src/gui/embedded/qvfbhdr.h \ - ../../src/gui/embedded/qlock_p.h \ - ../../src/gui/embedded/qwssignalhandler_p.h + qvfbmmap.h SOURCES = qvfb.cpp \ qvfbview.cpp \ @@ -31,9 +25,7 @@ SOURCES = qvfb.cpp \ qanimationwriter.cpp \ qvfbprotocol.cpp \ qvfbshmem.cpp \ - qvfbmmap.cpp \ - ../../src/gui/embedded/qlock.cpp \ - ../../src/gui/embedded/qwssignalhandler.cpp + qvfbmmap.cpp include(../shared/deviceskin/deviceskin.pri) -- cgit v0.12 From d4f7cc91cdaee88db35fd74666d631d44c8dd4b7 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 14 Jul 2011 17:55:45 +0200 Subject: namespace fix Reviewed-by: hjk --- src/corelib/tools/qelapsedtimer_win.cpp | 6 +++--- src/gui/text/qfontdatabase.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp index cd076a6..d79dc5d 100644 --- a/src/corelib/tools/qelapsedtimer_win.cpp +++ b/src/corelib/tools/qelapsedtimer_win.cpp @@ -42,14 +42,14 @@ #include "qelapsedtimer.h" #include -// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable -static quint64 counterFrequency = 0; - typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void); static PtrGetTickCount64 ptrGetTickCount64 = 0; QT_BEGIN_NAMESPACE +// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable +static quint64 counterFrequency = 0; + static void resolveLibs() { static bool done = false; diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 3762f39..26d9f2c 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1130,13 +1130,14 @@ QT_BEGIN_INCLUDE_NAMESPACE #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" #endif +QT_END_INCLUDE_NAMESPACE + #if !defined(Q_WS_X11) QString QFontDatabase::resolveFontFamilyAlias(const QString &family) { return family; } #endif -QT_END_INCLUDE_NAMESPACE static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey, const QString &styleName = QString()) -- cgit v0.12 From 2a326fdc8f8bf2bd2c5764394616100906d9db2d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 14 Jul 2011 16:27:44 -0700 Subject: Fix test for win and mac. Accidentally removed & in some places. Reviewed-by: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 2db9f75..abe7fa7 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -2766,7 +2766,7 @@ void tst_QAccessibility::listViewTest() #else { QListView listView; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); QVERIFY(iface); QCOMPARE(iface->childCount(), 1); delete iface; @@ -2780,11 +2780,11 @@ void tst_QAccessibility::listViewTest() listView.show(); QTest::qWait(1); // Need this for indexOfchild to work. #if defined(Q_WS_X11) - qt_x11_wait_for_window_manager(listView); + qt_x11_wait_for_window_manager(&listView); QTest::qWait(100); #endif - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView); QCOMPARE((int)iface->role(0), (int)QAccessible::Client); QCOMPARE((int)iface->role(1), (int)QAccessible::List); QCOMPARE(iface->childCount(), 1); -- cgit v0.12 From b66db48934bc13cc7439e0fc9c8ec54122678a02 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 14 Jul 2011 14:43:44 +0200 Subject: Fix the timeout calculation for futexes in QMutex. Recalculate how much time is remaining. This commit needs to be backported to 4.8. Change-Id: Ib587335bb90306e65969bb26256fb388f8f6bd24 Merge-request: 20 Reviewed-by: Olivier Goffart Reviewed-on: http://codereview.qt.nokia.com/1666 Reviewed-by: Qt Sanity Bot (cherry picked from commit 412ef92162f8874a1585221125c31ef5f8ccc9cb) --- src/corelib/thread/qmutex_unix.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 12bc795..e692e19 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -60,6 +60,7 @@ # include # include # include +# include #endif QT_BEGIN_NAMESPACE @@ -138,16 +139,31 @@ static inline int _q_futex(volatile int *addr, int op, int val, const struct tim bool QMutexPrivate::wait(int timeout) { + struct timespec ts, *pts = 0; + QElapsedTimer timer; + if (timeout >= 0) { + ts.tv_nsec = ((timeout % 1000) * 1000) * 1000; + ts.tv_sec = (timeout / 1000); + pts = &ts; + timer.start(); + } while (contenders.fetchAndStoreAcquire(2) > 0) { - struct timespec ts, *pts = 0; - if (timeout >= 0) { - ts.tv_nsec = ((timeout % 1000) * 1000) * 1000; - ts.tv_sec = (timeout / 1000); - pts = &ts; - } int r = _q_futex(&contenders._q_value, FUTEX_WAIT, 2, pts, 0, 0); if (r != 0 && errno == ETIMEDOUT) return false; + + if (pts) { + // recalculate the timeout + qint64 xtimeout = timeout * 1000 * 1000; + xtimeout -= timer.nsecsElapsed(); + if (xtimeout < 0) { + // timer expired after we returned + return false; + } + + ts.tv_sec = timeout / Q_INT64_C(1000) / 1000 / 1000; + ts.tv_nsec = timeout % (Q_INT64_C(1000) * 1000 * 1000); + } } return true; } -- cgit v0.12 From b5d357d63aeb28b8be62f1a3004a6a7969c7a81e Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Mon, 18 Jul 2011 08:46:01 +0300 Subject: Fixes leaking X11 SyncCounter when widgets get open/destroyed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xmeminfo showed leaking memory and unreleased X11 SyncCounter for test application opening and destroying one QWidget. It was not that critical: on 1000+ openings, heap grew ~4MB. This patch fixes the leak. Reviewed-by: Samuel Rødal --- src/gui/kernel/qwidget_x11.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index a3173eb..65d9837 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -2827,6 +2827,12 @@ void QWidgetPrivate::deleteTLSysExtra() { // don't destroy input context here. it will be destroyed in // QWidget::destroy() destroyInputContext(); +#ifndef QT_NO_XSYNC + if (extra && extra->topextra && extra->topextra->syncUpdateCounter) { + XSyncDestroyCounter(X11->display, extra->topextra->syncUpdateCounter); + extra->topextra->syncUpdateCounter = 0; + } +#endif } void QWidgetPrivate::registerDropSite(bool on) -- cgit v0.12 From 9b72e79e20d0d3560e0b064b8b0d75e35feb720e Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Sun, 17 Jul 2011 12:16:17 -0700 Subject: Fix accessibility test for QWS. For some reason we don't get the hide signal on QWS. Reviewed-by: Gabi --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index abe7fa7..79d7ee2 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -1774,6 +1774,9 @@ void tst_QAccessibility::mainWindowTest() QCOMPARE(interface->role(0), QAccessible::Window); delete interface; delete mw; +#ifndef Q_WS_QWS + QEXPECT_FAIL("", "The object hide event is missing on QWS.", Continue); +#endif QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); QTestAccessibility::clearEvents(); } -- cgit v0.12 From 075b0f744363842ed4179c644d933d461389544f Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 20 Jul 2011 01:09:27 -0700 Subject: Remove testing for Hide of mainwindow. This event is not used anywhere and the test seems to fail randomly. Since this line causes more trouble than it helps simply remove it. Reviewed-by: TrustMe --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 79d7ee2..d452820 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -1774,10 +1774,6 @@ void tst_QAccessibility::mainWindowTest() QCOMPARE(interface->role(0), QAccessible::Window); delete interface; delete mw; -#ifndef Q_WS_QWS - QEXPECT_FAIL("", "The object hide event is missing on QWS.", Continue); -#endif - QVERIFY_EVENT(mw, 0, QAccessible::ObjectHide); QTestAccessibility::clearEvents(); } -- cgit v0.12