diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2011-03-16 08:44:44 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2011-03-16 08:44:44 (GMT) |
commit | 245e0454a82a0fba7a1605320acf6b231c8d4205 (patch) | |
tree | 8e1ccd930b22a82c45e77b452bb5f0a230c499d1 | |
parent | 517290f73be74d1cf08fbd603870d3dacc379ff3 (diff) | |
parent | b18bd68dd05f000c65e33a975bca6bf24dabb8d3 (diff) | |
download | Qt-245e0454a82a0fba7a1605320acf6b231c8d4205.zip Qt-245e0454a82a0fba7a1605320acf6b231c8d4205.tar.gz Qt-245e0454a82a0fba7a1605320acf6b231c8d4205.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-water-team into 4.7
228 files changed, 6696 insertions, 1244 deletions
diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index 17a066f..c7e0089 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -16,35 +16,48 @@ Qt Bug Tracker: http://bugreports.qt.nokia.com Merge Request: http://qt.gitorious.org **************************************************************************** -* General * -**************************************************************************** - -New features ------------- - - - SomeClass, SomeOtherClass - * New classes for foo, bar and baz - -Optimizations -------------- - - - Optimized foo in QSomeClass - * See list of Important Behavior Changes below - - -**************************************************************************** * Library * **************************************************************************** QtCore ------ + - QMutex + * [QTBUG-16115] Fixed deadlock when calling tryLock repeatedly. - QStateMachine - * [QTBUG-14491] Fix compilation on AIX 5.3 with gcc. + * [QTBUG-14491] Fixed compilation on AIX 5.3 with gcc. + - QThread + * [QTBUG-15378] QThread::exec returaed immediately if QThread::exit had + been called when event loop was not running. QtGui ----- + - Painting + * [QTBUG-14907] Fix OpenVG painting artifacts after restoreState(). + * [QTBUG-15320] QPainter::drawRect crashed when drawing a null QRectF + with OpenGL. + * [QTBUG-15693] Prevent crash in drawhelper code when the cpu has MMXEXT + but no SSE. + - QDoubleValidator + * [QTBUG-14935] With some locales, QDoubleValidator would not accept "C" + locale valid numbers. + - QFileDialog + * [QTBUG-17298] QFileDialog::getOpenFileNames didn't show any file. + - QGraphicsView + * [QTBUG-16063] Fix precision loss when querying micro focus rectangle + in QGraphicsView. + - QPainterPath + * [QTBUG-16377] Prevent QPainterPath::connectPath() returning incorrect + path, which caused OpenGL paint engine to crash. + - QTableWidget + * [QTBUG-15973] Resizinag a QTableWidget column where a cell contains a + QProgressBar made it crash. + - QTextDocument + * [QTBUG-15777] Fxied crash in QTextDocument::markContentsDirty. + - QTextLayout + * [QTBUG-15823] Fixed crash in QTextLayout when drawing full width + selection spanning multiple QTextLine's. - QWidget * [QTMOBILITY-645] Send WinIdChange event when winId is set to zero. The window handle of a native widget may be set to zero in two @@ -52,27 +65,32 @@ QtGui widget destruction. Previously, no WinIdChange event was sent in either of these cases; now, it is sent in both cases. -QtDBus ------- - - - foo - * bar - QtNetwork --------- - - foo - * bar + - Bearer Management + * [QTBUG-15276] Fixed possible crash when parsing new connection. + - QUrl + * [QTBUG-16425] QUrl::setUrl() did not call detach(). -QtOpenGL --------- +QtQuick +------- - - foo - * bar + - [QTBUG-14374] Fixed broken alignment of rich text. + - [QTBUG-14727] QML Text element did not play nice with transformations. + - [QTBUG-14761] Fixed memory leak in QDeclarativeComponent. + - [QTBUG-14830] Fixed crash when adjusting width inside onWidthChanged. + - [QTBUG-15710] Ensure header is considered when positioning content with + snapping. + - [QTBUG-16365] When using a PathView with a VisualDataModel which in turn + used a Tree model (DirModel, for example), nothing was shown. + - [QTBUG-16769] QML BorderImage failed if .sci file contained a URL. QtScript -------- + - General + * [QTBUG-17166] Fix ScopeChainNode memory leak in JavaScriptCore. - QScriptContext * [QTBUG-17137] Fix crash when generating backtrace involving a built-in (ECMA) function. @@ -94,56 +112,55 @@ QtScript QtSql ----- - - foo - * bar - -QtXml ------ - - - foo - * bar - -Qt Plugins ----------- - - - foo - * bar - -Third party components ----------------------- - - - Updated foo to version 2.3.9. - - - Updated bar to the latest version from baz.org. + - [QTBUG-14132] Fix errors in Oracle (xe) stored procedures with bind + variables. + - [QTBUG-14831] Fix regression in dynamic sorting of a QSortFilterProxyModel + on a QSqlTableModel with OnManualSubmit. + - [QTBUG-17076] Fix plugins/sqldrivers/oci compile error when using + QT_NAMESPACE. **************************************************************************** * Platform Specific Changes * **************************************************************************** -Qt for Unix (X11 and Mac OS X) ------------------------------- - - - - Qt for Linux/X11 ---------------- - - + - [QTBUG-15008] Fix broken prefix setting in configure when EPOCROOT shell + variable is set. Qt for Windows -------------- - - + - QtQuick + * [QTBUG-16885] QDeclarativeEngine::addImportPath() did not work if the + drive letter is in lowercase. + * [QTBUG-17360] Make sure $QTDIR/plugins/qmldebugging/tcpserver.dll is + found in windows release builds. Qt for Mac OS X --------------- - - + - [QTBUG-13772] Returning form fullscreen mode causes assertion failure. + - [QTBUG-14023] Added missing plugins to debug-libs package. + - [QTBUG-14420] Switching from an application with undocked widgets hid the + application. + - [QTBUG-15638] Fixed incorrect QComboBox drop-down menu Z-ordering. + - [QTBUG-15666] Fixed crash when closing QFontDialog::getFont() dialog before + its event loop finished. + - [QTBUG-16279] Fixed deadlock in QSyntaxHighlighter::highlightBlock. Qt for Symbian -------------- + - Multimedia + * [QTBUG-17040] Prevent menu and native title pane area popping up when + setting fullscreen mode off during video playback. + - Packaging changes + * [QTBUG-17399] Remove sqlite3 from Qt SIS for S60 3.2 and 5.0 to allow + Nokia Content Signing, which doesn't permit sis files to have other + sis files embedded inside. - Paging changes * [QT-3503] Remove PAGED keyword from all Qt-based binaries for MMP-based build systems (abld, SBSv2 (a.k.a. Raptor)). @@ -159,65 +176,92 @@ Qt for Symbian appropriate types of paging rather than being forced by the binary (which may be deployed to several different devices with different characteristics). - - Phonon MMF backend * [QTBUG-11436] Added a MediaObject property which allows the client to specify which Internet Access Point should be used for streaming. - - - QNetworkProxyFactory - * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing - network proxies configured on the device to be used by applications. - - QApplication - * [QTBUG-15915] Fix crash when creating more than one QApplication in single test case. - + * [QTBUG-15915] Fix crash when creating more than one QApplication in single + test case. + * [QTBUG-16065] QApplication object with QApplication::GuiServer type caused + crash on Symbian devices. - QDesktopWidget * [QTBUG-16095] Resize event for QDesktopWidget was sent too early. - - - QFileDialog - * [QTBUG-16204] Fix using QFileDialog statics in Symbian. - - QDialog * [QTBUG-16277] Fix fullscreen/Maximized dialog misplacement in Symbian. - - - QSystemSemaphore - * [QTBUG-16615] Fix QSystemSemaphore handle management issues in Symbian. - + * [QTBUG-16110] QMessageBox softkeys were dimmed when application returned + to foreground. + - QEventDispatcherSymbian + * [QTBUG-16380] Fix leaking of RTimer handles. + - QFileDialog + * [QTBUG-16204] Fix using QFileDialog statics in Symbian. + - QFontDatabase + * [QTBUG-16514] Avoid collision of application fonts. + - QGraphicsView + * [QTBUG-16932] Fix rendering errors on QGraphicsView with OpenVG engine. - QLineEdit * [QTBUG-16238] Fix one character displacement for cursor in line edits. - - - QtScript - * [QTBUG-16685] Fix crash in JavaScript stack allocator. - * [QTBUG-15847] Add compiler optimizations. - * [QTBUG-14293] Enhanced JavaScript heap allocator. - - qmake & mkspecs * [QT-4193] Only add ICON for application projects in symbianpkgrules.pri - * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate files. - * [QTBUG-13367] Make default application deployment removable & added .flags modifier - support for DEPLOYMENT items in Symbian. + * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate + files. + * [QTBUG-13367] Make default application deployment removable & added .flags + modifier support for DEPLOYMENT items in Symbian. * [QTBUG-14280] Implement support for DEPLOYMENT.display_name in Symbian. * [QTBUG-13917] Localize .loc and .pkg content based on TRANSLATIONS. - * [QTBUG-15159] Use include(original mkspec) instead of copying of mkspec to default. + * [QTBUG-15159] Use include(original mkspec) instead of copying of mkspec to + default. * [QTBUG-15393] Resolve EPOCROOT in qt.conf using same logic as in .pro. * [QTBUG-15501] Fix symbian-mmp.conf include path. - * [QTBUG-15539] Use parent class function to generate Makefile headers in Symbian. - * [QTBUG-14472] Add NetworkServices capability automatically for network apps + * [QTBUG-15539] Use parent class function to generate Makefile headers. + * [QTBUG-14472] Add NetworkServices capability automatically for network apps. * [QTBUG-14736] Add libinfix support for QML plugins in Symbian. - * [QT-4375] Fix incorrect file name case for OpenGL libraries in symbian.conf. - * [QTBUG-16172] Use relative include instead of absolute in default qmake.conf. + * [QT-4375] Fix incorrect file name case for OpenGL libraries in + symbian.conf. + * [QTBUG-16172] Use relative include instead of absolute in default + qmake.conf. * [QTBUG-16221] Fix libinfixed usage in Symbian when def files are used. * [QTBUG-16261] Fix infinite loop in qmake when reading malformed .ts files. * [QTBUG-16298] Ignore static_and_shared in Symbian builds. + * [QTBUG-16477] Fix compile error when QT_NO_BEARERMANAGEMENT is defined. * [QTBUG-13769] Generate freeze targets in Symbian. - * [QTBUG-16691] Remove toolcheck from generic clean targets for symbian-sbsv2. - * [QT-4476] Fixed UTF-8 application names in device application menu in Symbian. + * [QTBUG-16691] Remove toolcheck from generic clean targets for + symbian-sbsv2. + * [QT-4476] Fixed UTF-8 application names in device application menu. * [QTBUG-16753] Improved QMAKE_POST_LINK support in symbian-sbsv2. - * [QTBUG-16881] Fix QMAKE_POST_LINK in Symbian for targets with special characters. - * [QTBUG-16888] No longer replace dash and dot in TARGET with underscore in Symbian. + * [QTBUG-16881] Fix QMAKE_POST_LINK for targets with special characters. + * [QTBUG-16888] No longer replace dash and dot in TARGET with underscore. + * [QTBUG-17187] Ensure that package generated against Symbian^3 SDK has no + Symbian^1 platforms as dependencies. * Fix partial upgrade package UID for libinfixed Qt. * Cleaned up sis_targets.prf. - + - QNetworkProxyFactory + * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing + network proxies configured on the device to be used by applications. + - QPaintEngine + * [QTBUG-16008] Fixed broken constant alpha blending on ARMV6. + * [QTBUG-16240] Fix blurry text in word-wrapped, center-aligned text items + with OpenVG. + - QSystemSemaphore + * [QTBUG-16615] Fix QSystemSemaphore handle management issues in Symbian. + - qtmain.lib + * [QTBUG-14735] Use qtmain.lib to provide entry point for all applications. + - QtQuick + * [QTBUG-15405] QML Plugins were not loaded when installed on different + drives. + - QtScript + * [QTBUG-14293] Enhanced JavaScript heap allocator. + * [QTBUG-15800] Creating QScriptEngine on the heap caused app crash. + * [QTBUG-15847] Add compiler optimizations. + * [QTBUG-16685] Fix crash in JavaScript stack allocator. + - QWidget + * [QTBUG-16578] In cases where the widget was created from the event loop + instead of main(), the middle three softkeys would not get the right + visibility and would leave a "hole" in the application where one could + see what was beneath it. + * [QT-4416, QTBUG-17288] On devices which lack support for transparency + in EGL surfaces, setting Qt::WA_TranslucentBackground on a widget + whose windowType() is Qt::Window causes that widget to be rendered + using the raster graphics system. - Tool scripts * [QTBUG-13886] Disallow patching capabilities of executables. * [QTBUG-13891] Add Location as self signable capability in patch_capabilities.pl. @@ -225,49 +269,10 @@ Qt for Symbian * Fix epocroot handling in createpackage.pl script. * Unify epocroot usage in createpackage and patch_capabilities scripts. - - qtmain.lib - * [QTBUG-14735] Use qtmain.lib to provide entry point for all Symbian applications. - - - QWidget - * [QT-4416, QTBUG-17288] On devices which lack support for transparency - in EGL surfaces, setting Qt::WA_TranslucentBackground on a widget - whose windowType() is Qt::Window causes that widget to be rendered - using the raster graphics system. - -Qt for Embedded Linux ---------------------- - - - - -DirectFB --------- - - - - -Qt for Windows CE ------------------ - - - - **************************************************************************** * Tools * **************************************************************************** - - Designer - * foo - - - qdoc3 - * bar - - - Linguist - * baz - - qmake * [QTBUG-14357] Make qmake to pass all UTF-8 characters unchanged through parser. -**************************************************************************** -* Important Behavior Changes * -**************************************************************************** - - - - diff --git a/dist/changes-4.7.3 b/dist/changes-4.7.3 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dist/changes-4.7.3 diff --git a/doc/src/declarative/dynamicobjects.qdoc b/doc/src/declarative/dynamicobjects.qdoc index 316fe6b..f2ca0fd 100644 --- a/doc/src/declarative/dynamicobjects.qdoc +++ b/doc/src/declarative/dynamicobjects.qdoc @@ -68,9 +68,11 @@ the component. This function can take one or two arguments: \o The first is the parent for the new item. Since graphical items will not appear on the scene without a parent, it is recommended that you set the parent this way. However, if you wish to set the parent later you can safely pass \c null to this function. -\o The second is optional and is a script which assigns values to the item's properties during creation. This avoids warnings - when certain properties have been bound to before they have been set by the code. Additionally, there are small performance - benefits when instantiating objects in this way. +\o The second is optional and is a map of property-value items that define initial any property values for the item. + Property values specified by this argument are applied to the object before its creation is finalized, avoiding + binding errors that may occur if particular properties must be initialized to enable other property bindings. + when certain properties have been bound to before they have been set by the code. Additionally, there are small + performance benefits when compared to defining property values and bindings after the object is created. \endlist Here is an example. First there is \c Sprite.qml, which defines a simple QML component: diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index 466b940..e2d9350 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -76,7 +76,7 @@ To see the QML elements listed by functional area, see the \o \l {FocusScope} - Element that mediate keyboard focus changes \o \l {Flickable} - Provides a surface that can be "flicked" \o \l {Flipable} - Provides a surface that produces "flipping" effects -\o \l {GestureArea} - Enables simple gesture handling +\o \l {PinchArea} - Enables simple pinch gesture handling \endlist \section1 Positioners and Repeater diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 5a95551..4b4e05e 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -51,7 +51,7 @@ to either instantiating an object instance, or assigning a property a value. QML relies heavily on Qt's meta object system and can only instantiate classes that derive from QObject. For visual element types, this will usually mean a subclass of QDeclarativeItem; for models used with the view elements, a subclass of QAbstractItemModel; -and for abitrary objects with properties, a direct subclass of QObject. +and for arbitrary objects with properties, a direct subclass of QObject. The QML engine has no intrinsic knowledge of any class types. Instead the programmer must register the C++ types with their corresponding QML names. @@ -522,7 +522,7 @@ The \c {invite()} method is similarly available if it is declared as a slot. \snippet examples/declarative/cppextensions/referenceexamples/valuesource/example.qml 0 \snippet examples/declarative/cppextensions/referenceexamples/valuesource/example.qml 1 -The QML snippet shown above applies a property value source to the \c announcment property. +The QML snippet shown above applies a property value source to the \c announcement property. A property value source generates a value for a property that changes over time. Property value sources are most commonly used to do animation. Rather than @@ -562,7 +562,7 @@ assignment fails does the engine call the \l {QDeclarativePropertyValueSource::} the type to also be used in contexts other than just as a value source. \l {Extending QML - Property Value Source Example} shows the complete code used -implement the \c HappyBirthdaySong property value source. +to implement the \c HappyBirthdaySong property value source. \section1 Property Binding diff --git a/doc/src/declarative/qmlinuse.qdoc b/doc/src/declarative/qmlinuse.qdoc index 7380ef5..131be1b 100644 --- a/doc/src/declarative/qmlinuse.qdoc +++ b/doc/src/declarative/qmlinuse.qdoc @@ -207,7 +207,7 @@ <li><a href="qml-flipable.html">Flipable Element</a> - The Flipable item provides a surface that can be flipped or reflected.</li> <li><a href="qml-focuspanel.html">FocusPanel Element</a> - The FocusPanel item explicitly creates a focus panel.</li> <li><a href="qml-focusscope.html">FocusScope Element</a> - The FocusScope object explicitly creates a focus scope for focus management.</li> - <li><a href="qml-gesturearea.html">GestureArea Element</a> - The GestureArea item enables simple gesture handling.</li> + <li><a href="qml-pincharea.html">PinchArea Element</a> - The PinchArea item enables simple pinch gesture handling.</li> <li><a href="qml-keynavigation.html">KeyNavigation Element</a> - The KeyNavigation attached property supports key navigation by arrow keys.</li> <li><a href="qml-keys.html">Keys Element</a> - The Keys attached property provides key handling to Items.</li> <li><a href="qml-mousearea.html">MouseArea Element</a> - The MouseArea item enables simple mouse handling.</li> diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc index f4359f9..e8c2124 100644 --- a/doc/src/declarative/whatsnew.qdoc +++ b/doc/src/declarative/whatsnew.qdoc @@ -41,10 +41,10 @@ PinchArea provides support for the common two finger pinch gesture. Added the following properties: \list -\o lineSpacing -\o lineCount -\o maximumLineCount -\o truncated +\o \l {Text::}{lineHeight} +\o \l {Text::}{lineCount} +\o \l {Text::}{maximumLineCount} +\o \l {Text::}{truncated} \endlist horizontalAlignment now accepts Text.AlignJustify alignment mode. @@ -53,85 +53,88 @@ horizontalAlignment now accepts Text.AlignJustify alignment mode. Added the following properties, methods and signal handlers: \list -\o canPaste -\o lineCount -\o deselect() -\o moveCursorSelection(int pos, SelectionMode mode) to enable selection by word -\o onLinkActivated(string link) +\o \l {TextEdit::}{canPaste} +\o \l {TextEdit::}{lineCount} +\o \l {TextEdit::}{deselect()} +\o \l {TextEdit::}{moveCursorSelection()} to enable selection by word +\o \l {TextEdit::}{onLinkActivated} \endlist \section2 TextInput Added the following properties and methods: \list -\o canPaste -\o deselect() -\o moveCursorSelection(int pos, SelectionMode mode) to enable selection by word +\o \l{TextInput::}{canPaste} +\o \l{TextInput::}{deselect()} +\o \l{TextInput::}{moveCursorSelection()} to enable selection by word \endlist \section2 Image, BorderImage and AnimatedImage Added the following properties: \list -\o cache -\o mirror +\o \l{Image::}{cache} +\o \l{Image::}{mirror} \endlist \section2 Item Added the following properties: \list -\o implicitWidth and implicitHeight +\o \l{Item::}{implicitWidth} and \l{Item::}{implicitHeight} \endlist \section2 Flickable Added the following methods: \list -\o resizeContent(qreal w, qreal h, QPointF center) -\o returnToBounds() +\o \l{Flickable::}{resizeContent()} +\o \l{Flickable::}{returnToBounds()} \endlist \section2 ListView and GridView Added the following methods: \list -\o positionViewAtBeginning() -\o positionViewAtEnd() +\o \l{ListView::}{positionViewAtBeginning()} +\o \l{ListView::}{positionViewAtEnd()} \endlist -\section2 Flow, Grid, Row +\section2 Flow, Grid and Row Added the following properties: \list -\o layoutDirection +\o \l{Flow::}{layoutDirection} \endlist \section2 Repeater Added the following methods and signal handlers: \list -\o onItemAdded() -\o onItemRemoved() -\o itemAt(int index) +\o \l{Repeater::}{onItemAdded} +\o \l{Repeater::}{onItemRemoved} +\o \l{Repeater::}{itemAt()} \endlist \section2 Component -The createObject() method now accepts a map of initial property values for the created object. +\list +\o The \l{Component::}{createObject()} method now accepts a map of initial property values for +the created object. +\endlist \section2 Qt -Added the following properties and methods: \list -\o application.layoutDirection -\o application.active +\o Added the \l {QML:Qt::application}{Qt.application} object to hold generic global application +properties. \endlist \section2 Other changes \list -\o Functions can be assigned to properties from JavaScript to create property bindings +\o Functions can be \l{Binding Properties from JavaScript}{assigned to properties from JavaScript} +to create property bindings. \endlist diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc index 9a46ea8..9695d84 100644 --- a/doc/src/development/qmake-manual.qdoc +++ b/doc/src/development/qmake-manual.qdoc @@ -1650,8 +1650,7 @@ \section1 INCLUDEPATH This variable specifies the #include directories which should be - searched when compiling the project. Use ';' or a space as the - directory separator. + searched when compiling the project. For example: diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc index c906f84..6d0256e 100644 --- a/doc/src/getting-started/installation.qdoc +++ b/doc/src/getting-started/installation.qdoc @@ -874,9 +874,10 @@ If the installation fails, please make sure that there is no previously installed version of Qt on the phone. Qt requires some dependent packages to be installed on the device, -they are shipped in the Symbian SDK and can be installed using the -runonphone tool as well. -The packages can be found in the EPOCROOT at the following locations; +which can be installed using the runonphone tool as well. One is +the \c{sqlite3.sis}, which is included in the Qt distribution, while +the others are shipped with the Symbian SDK. The required packages +can be found from the following locations: \snippet doc/src/snippets/code/doc_src_installation.qdoc 50 @@ -1274,10 +1275,18 @@ We hope you will enjoy using Qt. in this release. \endlist - Running Qt on real device requires the Open C to be installed on the device. - The Open C installation packages are embedded into \c{qt_installer.sis}, which is included in - Qt for Symbian binary package. If you are building Qt from scratch, you can find the - required packages in the Symbian SDK where you installed Open C/C++: + Running Qt on real device requires the Open C and sqlite3 to be installed on the device. + These installation packages are embedded into \c{qt_installer.sis}, which is included in + Qt for Symbian binary package. + + If you are building Qt from scratch, you can find the sqlite3 package from + under your Qt installation: + + \list + \o \c{src\s60installs\sqlite3.sis} + \endlist + + The Open C packages you can find in the Symbian SDK where you installed Open C/C++: \list \o \c{nokia_plugin\openc\s60opencsis\pips_s60_<version>.sis} \o \c{nokia_plugin\openc\s60opencsis\openc_ssl_s60_<version>.sis} diff --git a/doc/src/images/roaming-states.png b/doc/src/images/roaming-states.png Binary files differnew file mode 100644 index 0000000..bc61cac --- /dev/null +++ b/doc/src/images/roaming-states.png diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc index aac6bb0..de6eb7f 100644 --- a/doc/src/platforms/platform-notes.qdoc +++ b/doc/src/platforms/platform-notes.qdoc @@ -735,9 +735,9 @@ \row \o QtCore \o \c AllFiles when \l{http://developer.symbian.org/wiki/index.php/Capabilities_%28Symbian_Signed%29/AllFiles_Capability}{accessing specific areas.} \row \o QtDeclarative - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \row \o QtNetwork - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \row \o QtNetwork \o \c ReadUserData is required to include all the phone's SSL certificates in the system's default CA certificate list (for example those added by the user or stored in the SIM card), @@ -745,7 +745,7 @@ \row \o QtMultiMedia \o \c UserEnvironment if QAudioInput is used. \row \o QtWebkit - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \endtable \note Some modules rely on other modules. E.g. QtWebkit and QtDeclarative diff --git a/doc/src/snippets/code/doc_src_installation.qdoc b/doc/src/snippets/code/doc_src_installation.qdoc index 0374320..1a87566 100644 --- a/doc/src/snippets/code/doc_src_installation.qdoc +++ b/doc/src/snippets/code/doc_src_installation.qdoc @@ -328,9 +328,10 @@ runonphone -s myapp.sis myapp.exe //! [49] //! [50] -nokia_plugin/openc/s60opencsis/openc_ssl_s60_1_6_ss.sis -nokia_plugin/openc/s60opencsis/pips_s60_1_6_ss.sis -nokia_plugin/opencpp/s60opencppsis/stdcpp_s60_1_6_ss.sis +src/s60installs/sqlite3.sis +$EPOCROOT/nokia_plugin/openc/s60opencsis/openc_ssl_s60_1_6_ss.sis +$EPOCROOT/nokia_plugin/openc/s60opencsis/pips_s60_1_6_ss.sis +$EPOCROOT/nokia_plugin/opencpp/s60opencppsis/stdcpp_s60_1_6_ss.sis //! [50] diff --git a/doc/src/snippets/declarative/componentCreation.js b/doc/src/snippets/declarative/componentCreation.js index cf59777..7364139 100644 --- a/doc/src/snippets/declarative/componentCreation.js +++ b/doc/src/snippets/declarative/componentCreation.js @@ -32,13 +32,10 @@ function createSpriteObjects() { //![finishCreation] function finishCreation() { if (component.status == Component.Ready) { - sprite = component.createObject(appWindow); + sprite = component.createObject(appWindow, {"x": 100, "y": 100}); if (sprite == null) { // Error Handling - } else { - sprite.x = 100; - sprite.y = 100; - // ... + console.log("Error creating object"); } } else if (component.status == Component.Error) { // Error Handling diff --git a/examples/declarative/keyinteraction/focus/focus.qml b/examples/declarative/keyinteraction/focus/focus.qml index 9cb1fef..935db25 100644 --- a/examples/declarative/keyinteraction/focus/focus.qml +++ b/examples/declarative/keyinteraction/focus/focus.qml @@ -91,7 +91,7 @@ Rectangle { MouseArea { anchors.fill: parent; anchors.margins: -10 - onClicked: window.state = "contextMenuOpen" + onClicked: contextMenu.focus = true } } diff --git a/examples/declarative/touchinteraction/pincharea/flickresize.qml b/examples/declarative/touchinteraction/pincharea/flickresize.qml index a2f81ff..9439ace 100644 --- a/examples/declarative/touchinteraction/pincharea/flickresize.qml +++ b/examples/declarative/touchinteraction/pincharea/flickresize.qml @@ -54,14 +54,21 @@ Rectangle { PinchArea { width: Math.max(flick.contentWidth, flick.width) height: Math.max(flick.contentHeight, flick.height) + + property real initialWidth + property real initialHeight + onPinchStarted: { + initialWidth = flick.contentWidth + initialHeight = flick.contentHeight + } + onPinchUpdated: { // adjust content pos due to drag flick.contentX += pinch.previousCenter.x - pinch.center.x flick.contentY += pinch.previousCenter.y - pinch.center.y // resize content - var scale = 1.0 + pinch.scale - pinch.previousScale - flick.resizeContent(flick.contentWidth * scale, flick.contentHeight * scale, pinch.center) + flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center) } onPinchFinished: { diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index 0bb3a29..5f5c7e1 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -70,16 +70,17 @@ QMAKE_LINK_OBJECT_SCRIPT= QMAKE_LIBS = -llibc -llibm -leuser -llibdl QMAKE_LIBS_CORE = $$QMAKE_LIBS -lefsrv -lhal -lbafl -lapparc -QMAKE_LIBS_GUI = $$QMAKE_LIBS_CORE -lfbscli -lbitgdi -lgdi -lws32 -lapgrfx -lcone -leikcore -lmediaclientaudio -lcentralrepository +QMAKE_LIBS_CFBSBITMAP = -lfbscli -lbitgdi -lgdi +QMAKE_LIBS_GUI = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_CFBSBITMAP -lws32 -lapgrfx -lcone -leikcore -lmediaclientaudio -lcentralrepository QMAKE_LIBS_NETWORK = QMAKE_LIBS_EGL = -llibEGL QMAKE_LIBS_OPENGL = -llibGLESv2 QMAKE_LIBS_OPENGL_ES1 = -llibGLESv1_CM QMAKE_LIBS_OPENGL_ES2 = -llibGLESv2 -QMAKE_LIBS_OPENGL_QT = -llibGLESv2 -lcone -lws32 -QMAKE_LIBS_OPENGL_ES1_QT = -llibGLESv1_CM -lcone -lws32 -QMAKE_LIBS_OPENGL_ES2_QT = -llibGLESv2 -lcone -lws32 -QMAKE_LIBS_OPENVG = -llibOpenVG -lfbscli -lbitgdi -lgdi +QMAKE_LIBS_OPENGL_QT = $$QMAKE_LIBS_OPENGL $$QMAKE_LIBS_CFBSBITMAP -lcone -lws32 +QMAKE_LIBS_OPENGL_ES1_QT = $$QMAKE_LIBS_OPENGL_ES1 $$QMAKE_LIBS_CFBSBITMAP -lcone -lws32 +QMAKE_LIBS_OPENGL_ES2_QT = $$QMAKE_LIBS_OPENGL_ES2 $$QMAKE_LIBS_CFBSBITMAP -lcone -lws32 +QMAKE_LIBS_OPENVG = $$QMAKE_LIBS_CFBSBITMAP -llibOpenVG QMAKE_LIBS_THREAD = -llibpthread QMAKE_LIBS_COMPAT = QMAKE_LIBS_S60 = -lavkon -leikcoctl @@ -229,16 +230,41 @@ defineReplace(symbianRemoveSpecialCharacters) { # Determines translations that are Symbian supported defineTest(matchSymbianLanguages) { + # Qt language codes for which we need to parse .ts file SYMBIAN_MATCHED_LANGUAGES = + # List of translation files for matched languages SYMBIAN_MATCHED_TRANSLATIONS = + # List of Qt language codes for which we have no mapped Symbian code but we have a fallback code + # and therefore need to generate a mapping for in localize_deployment.prf. + # The fallback code means plain language code for languages that have both language and country codes. + # E.g. the fallback code for language "zh_CN" would be "zh". + SYMBIAN_UNMAPPED_LANGUAGES = + # List of handled Qt language codes to avoid duplicate Symbian language codes in case both + # unmapped language+country combination and its fallback code, or multiple unmapped language+country + # combinations that have same fallback code are included. + HANDLED_LANGUAGES = # Cannot parse .ts file for language here, so detect it from filename. # Allow two and three character language and country codes. for(translation, TRANSLATIONS) { language = $$replace(translation, "^(.*/)?[^/]+_(([^_]{2,3}_)?[^_]{2,3})\\.ts$", \\2) - contains(SYMBIAN_SUPPORTED_LANGUAGES, $$language) { - SYMBIAN_MATCHED_LANGUAGES += $$language - SYMBIAN_MATCHED_TRANSLATIONS += $$translation + !contains(HANDLED_LANGUAGES, $$language) { + HANDLED_LANGUAGES += $$language + contains(SYMBIAN_SUPPORTED_LANGUAGES, $$language) { + SYMBIAN_MATCHED_LANGUAGES += $$language + SYMBIAN_MATCHED_TRANSLATIONS += $$translation + } else { + # No direct mapping for specified language found. Check if a fallback language code can be used. + strippedLanguage = $$replace(language, "_.*$",) + contains(SYMBIAN_SUPPORTED_LANGUAGES, $$strippedLanguage):!contains(HANDLED_LANGUAGES, $$strippedLanguage) { + HANDLED_LANGUAGES += $$strippedLanguage + SYMBIAN_UNMAPPED_LANGUAGES += $$language + SYMBIAN_MATCHED_LANGUAGES += $$language + SYMBIAN_MATCHED_TRANSLATIONS += $$translation + SYMBIAN_LANGUAGE_FALLBACK.$$language = $$strippedLanguage + export(SYMBIAN_LANGUAGE_FALLBACK.$$language) + } + } } } @@ -246,6 +272,7 @@ defineTest(matchSymbianLanguages) { export(SYMBIAN_MATCHED_LANGUAGES) export(SYMBIAN_MATCHED_TRANSLATIONS) + export(SYMBIAN_UNMAPPED_LANGUAGES) } # Symbian pkg files that define multiple languages require a language specific string to be diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 964e13b..24c84a5 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -53,15 +53,15 @@ defineTest(qtAddLibrary) { # Needed for because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtXmlPatterns INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 } else:isEqual(LIB_NAME, QtXmlPatterns) { # Needed for #include <QtXmlPatterns/QtXmlPatterns> because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork } else:isEqual(LIB_NAME, QtNetwork) { - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices } else:isEqual(LIB_NAME, QtDeclarative) { - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 } export(TARGET.EPOCHEAPSIZE) diff --git a/mkspecs/features/symbian/localize_deployment.prf b/mkspecs/features/symbian/localize_deployment.prf index 26a254b..185c713 100644 --- a/mkspecs/features/symbian/localize_deployment.prf +++ b/mkspecs/features/symbian/localize_deployment.prf @@ -101,6 +101,15 @@ isEmpty(SYMBIAN_MATCHED_LANGUAGES) { matchSymbianLanguages() } +# If there are translations that do not have Symbian language code defined for that exact +# language + country combination, but have Symbian language code defined for just the language, +# map the language + country combination to the same value as the plain language. +for(language, SYMBIAN_UNMAPPED_LANGUAGES) { + languageVar = SYMBIAN_LANG.$${language} + fallbackLanguageVar = SYMBIAN_LANG.$$eval(SYMBIAN_LANGUAGE_FALLBACK.$$language) + $$languageVar = $$eval($$fallbackLanguageVar) +} + !isEmpty(SYMBIAN_MATCHED_TRANSLATIONS) { # Generate dependencies to .ts files for pkg files template_pkg_target.depends += $$SYMBIAN_MATCHED_TRANSLATIONS diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm new file mode 100644 index 0000000..c9a88fc --- /dev/null +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm @@ -0,0 +1,18 @@ +# /**************************************************************************** +# ** +# ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# ** Contact: Nokia Corporation (qt-info@nokia.com) +# ** +# ** This file is part of symbian-sbsv2 mkspec. +# ** +# ****************************************************************************/ + + +SINGLETON:=$(call sanitise,QMAKE_CLEAN_SINGLETON_$(EXTENSION_ROOT)) + +ifeq ($($(SINGLETON)),) +# Prevent duplicate targets from being created +$(SINGLETON):=1 +$(eval $(call GenerateStandardCleanTarget,$(wildcard $(patsubst "%",%,$(CLEAN_FILES))))) +endif + diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm index 39ab0f0..8791a47 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm @@ -33,5 +33,6 @@ ifeq ($($(SINGLETON)),) $(eval $(call qmake_emulator_deployment, $(subst $(CHAR_SPACE),\$(CHAR_SPACE),$(DEPLOY_TARGET)), $(subst $(CHAR_SPACE),\$(CHAR_SPACE),$(DEPLOY_SOURCE)))) $(call makepath,$(dir $(DEPLOY_TARGET))) $(eval $(call GenerateStandardCleanTarget,$(CLEAN_TARGET),'')) +$(eval $(call whatmacro,$(CLEAN_TARGET))) endif diff --git a/mkspecs/symbian-sbsv2/flm/qt/qt.xml b/mkspecs/symbian-sbsv2/flm/qt/qt.xml index ddd8d55..f2f32ee 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qt.xml +++ b/mkspecs/symbian-sbsv2/flm/qt/qt.xml @@ -38,4 +38,9 @@ <interface name="qt.qmake_store_build" extends="Symbian.UserFLM" flm="qmake_store_build.flm"> </interface> + + <interface name="qt.qmake_clean" extends="Symbian.UserFLM" + flm="qmake_clean.flm"> + <param name='CLEAN_FILES' /> + </interface> </build> diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index 9eccd46..0fdef86 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -721,6 +721,21 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t t << "END" << endl; t << endl; + // Handle QMAKE_CLEAN + QStringList cleanFiles = project->values("QMAKE_CLEAN"); + if (!cleanFiles.isEmpty()) { + QStringList absoluteCleanFiles; + foreach (QString cleanFile, cleanFiles) { + QFileInfo fi(cleanFile); + QString fileName = QLatin1String("\""); + fileName.append(fi.absoluteFilePath()); + fileName.append(QLatin1String("\"")); + absoluteCleanFiles << fileName; + } + t << "START EXTENSION qt/qmake_clean" << endl; + t << "OPTION CLEAN_FILES " << absoluteCleanFiles.join(" ") << endl; + t << "END" << endl; + } t << endl; } diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index d92eb69..44e5164 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -662,10 +662,10 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) if(project->isActiveConfig("shared") && !project->values("DLLDESTDIR").isEmpty()) { QStringList dlldirs = project->values("DLLDESTDIR"); for (QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) { - t << "\n\t" << "-$(COPY_FILE) \"$(DESTDIR_TARGET)\" " << Option::fixPathToTargetOS(*dlldir, false); + t << "\t" << "-$(COPY_FILE) \"$(DESTDIR_TARGET)\" " << Option::fixPathToTargetOS(*dlldir, false) << endl; } } - t << endl << endl; + t << endl; writeRcFilePart(t); diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 981dba2..37d216d 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -15,7 +15,7 @@ symbian: { webkitlibs.path = /sys/bin vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h index 63d9e55..2c0bf6d 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h @@ -22,9 +22,9 @@ #include <QtCore/qglobal.h> -#define QTWEBKIT_VERSION_STR "2.0.1" +#define QTWEBKIT_VERSION_STR "2.0.2" // QTWEBKIT_VERSION is (major << 16) + (minor << 8) + patch. Similar to Qt. -#define QTWEBKIT_VERSION 0x020001 +#define QTWEBKIT_VERSION 0x020002 // Use: #if (QTWEBKIT_VERSION >= QTWEBKIT_VERSION_CHECK(2, 0, 0)). Similar to Qt. #define QTWEBKIT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) diff --git a/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri b/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri index b98617f..07754a7 100644 --- a/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri +++ b/src/3rdparty/webkit/WebKit/qt/qt_webkit_version.pri @@ -1,5 +1,5 @@ -QT_WEBKIT_VERSION = 4.7.2 +QT_WEBKIT_VERSION = 4.7.3 QT_WEBKIT_MAJOR_VERSION = 4 QT_WEBKIT_MINOR_VERSION = 7 -QT_WEBKIT_PATCH_VERSION = 2 +QT_WEBKIT_PATCH_VERSION = 3 QT_CONFIG += webkit diff --git a/src/corelib/concurrent/qfutureinterface.cpp b/src/corelib/concurrent/qfutureinterface.cpp index 6256944..627d0c7 100644 --- a/src/corelib/concurrent/qfutureinterface.cpp +++ b/src/corelib/concurrent/qfutureinterface.cpp @@ -421,9 +421,11 @@ bool QFutureInterfaceBase::referenceCountIsOne() const QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState) : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0), - state(initialState), progressTimeStarted(false), pendingResults(0), + state(initialState), pendingResults(0), manualProgress(false), m_expectedResultCount(0), runnable(0) -{ } +{ + progressTime.invalidate(); +} int QFutureInterfaceBasePrivate::internal_resultCount() const { @@ -455,12 +457,11 @@ bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress, m_progressValue = progress; m_progressText = progressText; - if (progressTimeStarted == true && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted. + if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted. if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond)) return false; progressTime.start(); - progressTimeStarted = true; return true; } diff --git a/src/corelib/concurrent/qfutureinterface_p.h b/src/corelib/concurrent/qfutureinterface_p.h index 7f93c75..538947e 100644 --- a/src/corelib/concurrent/qfutureinterface_p.h +++ b/src/corelib/concurrent/qfutureinterface_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include <QtCore/qdatetime.h> +#include <QtCore/qelapsedtimer.h> #include <QtCore/qcoreevent.h> #include <QtCore/qlist.h> #include <QtCore/qwaitcondition.h> @@ -137,8 +137,7 @@ public: int m_progressMinimum; int m_progressMaximum; QFutureInterfaceBase::State state; - QTime progressTime; - bool progressTimeStarted; + QElapsedTimer progressTime; QWaitCondition pausedWaitCondition; int pendingResults; QtConcurrent::ResultStoreBase m_results; diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index c2fb16c..d0fc753 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -44,11 +44,11 @@ #include <stddef.h> -#define QT_VERSION_STR "4.7.2" +#define QT_VERSION_STR "4.7.3" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x040702 +#define QT_VERSION 0x040703 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -2446,9 +2446,17 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); # define QT_SYMBIAN_SUPPORTS_SGIMAGE #endif -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef SYMBIAN_GRAPHICS_SET_SURFACE_TRANSPARENCY_AVAILABLE # define Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE #endif + +#ifdef SYMBIAN_GRAPHICS_TRANSITION_EFFECTS_SIGNALING_AVAILABLE +# define Q_SYMBIAN_TRANSITION_EFFECTS +#endif +#endif + +#ifdef SYMBIAN_WSERV_AND_CONE_MULTIPLE_SCREENS +#define Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS #endif //Symbian does not support data imports from a DLL diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index e492345..4d70744 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -541,6 +541,7 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, + AA_S60DisablePartialScreenInputMode = 9, // Add new attributes before this line AA_AttributeCount @@ -574,7 +575,8 @@ public: PreferDither = 0x00000040, AvoidDither = 0x00000080, - NoOpaqueDetection = 0x00000100 + NoOpaqueDetection = 0x00000100, + NoFormatConversion = 0x00000200 }; Q_DECLARE_FLAGS(ImageConversionFlags, ImageConversionFlag) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 65cd7f4..a79411b 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,6 +156,13 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \omitvalue AA_S60DisablePartialScreenInputMode By default in Symbian^3, + a separate editing window is opened on top of an application. This is exactly + like editing on previous versions of Symbian behave. When this attribute + is true, a virtual keyboard window is shown on top of application and it + is ensured that the focused text widget is visible. This is only supported in + Symbian^3. (internal) + \omitvalue AA_AttributeCount */ @@ -732,6 +739,10 @@ until a non-opaque pixel is found, or if you want the pixmap to retain an alpha channel for some other reason. If the image has no alpha channel this flag has no effect. + + \omitvalue NoFormatConversion Don't do any format conversions on the image. + Can be useful when converting a QImage to a QPixmap for a one-time + rendering operation for example. */ /*! \enum Qt::GUIStyle diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index ab1455f..ac3b5fa 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -176,10 +176,10 @@ QDBusArgument::ElementType QDBusDemarshaller::currentType() case DBUS_TYPE_INVALID: return QDBusArgument::UnknownType; - default: - qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", - q_dbus_message_iter_get_arg_type(&iterator), - q_dbus_message_iter_get_arg_type(&iterator)); +// default: +// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", +// q_dbus_message_iter_get_arg_type(&iterator), +// q_dbus_message_iter_get_arg_type(&iterator)); } return QDBusArgument::UnknownType; } @@ -232,10 +232,15 @@ QVariant QDBusDemarshaller::toVariantInternal() return qVariantFromValue(duplicate()); default: - qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", - q_dbus_message_iter_get_arg_type(&iterator), - q_dbus_message_iter_get_arg_type(&iterator)); - return QVariant(); +// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", +// q_dbus_message_iter_get_arg_type(&iterator), +// q_dbus_message_iter_get_arg_type(&iterator)); + char *ptr = 0; + ptr += q_dbus_message_iter_get_arg_type(&iterator); + q_dbus_message_iter_next(&iterator); + + // I hope you never dereference this pointer! + return QVariant::fromValue<void *>(ptr); break; }; } diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 6683505..df8bc1d 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -193,14 +193,19 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, QByteArray typeName = annotations.value(annotationName).toLatin1(); // verify that it's a valid one - if (typeName.isEmpty()) - return result; // invalid - - type = QVariant::nameToType(typeName); - if (type == QVariant::UserType) - type = QMetaType::type(typeName); - if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) - return result; // unknown type is invalid too + if (!typeName.isEmpty()) { + // type name found + type = QVariant::nameToType(typeName); + if (type == QVariant::UserType) + type = QMetaType::type(typeName); + } + + if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) { + // type is still unknown or doesn't match back to the signature that it + // was expected to, so synthesize a fake type + type = QMetaType::VoidStar; + typeName = "QDBusRawType<0x" + signature.toHex() + ">*"; + } result.name = typeName; } else if (type == QVariant::Invalid) { diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 1b99ced..3feedde 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -52,6 +52,13 @@ #ifndef QT_NO_DBUS +//#define QDBUS_PARSER_DEBUG +#ifdef QDBUS_PARSER_DEBUG +# define qDBusParserError qWarning +#else +# define qDBusParserError if (true) {} else qDebug +#endif + QT_BEGIN_NAMESPACE static QDBusIntrospection::Annotations @@ -69,8 +76,8 @@ parseAnnotations(const QDomElement& elem) value = ann.attribute(QLatin1String("value")); if (!QDBusUtil::isValidInterfaceName(name)) { - qWarning("Invalid D-BUS annotation '%s' found while parsing introspection", - qPrintable(name)); + qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection", + qPrintable(name)); continue; } @@ -99,9 +106,8 @@ parseArgs(const QDomElement& elem, const QLatin1String& direction, bool acceptEm argData.name = arg.attribute(QLatin1String("name")); // can be empty argData.type = arg.attribute(QLatin1String("type")); if (!QDBusUtil::isValidSingleSignature(argData.type)) { - qWarning("Invalid D-BUS type signature '%s' found while parsing introspection", - qPrintable(argData.type)); - continue; + qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection", + qPrintable(argData.type)); } retval << argData; @@ -141,8 +147,8 @@ QDBusXmlParser::interfaces() const if (iface.isNull()) continue; // for whatever reason if (!QDBusUtil::isValidInterfaceName(ifaceName)) { - qWarning("Invalid D-BUS interface name '%s' found while parsing introspection", - qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection", + qPrintable(ifaceName)); continue; } @@ -166,8 +172,8 @@ QDBusXmlParser::interfaces() const if (method.isNull()) continue; if (!QDBusUtil::isValidMemberName(methodName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(methodName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(methodName), qPrintable(ifaceName)); continue; } @@ -192,8 +198,8 @@ QDBusXmlParser::interfaces() const if (signal.isNull()) continue; if (!QDBusUtil::isValidMemberName(signalName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(signalName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(signalName), qPrintable(ifaceName)); continue; } @@ -217,8 +223,8 @@ QDBusXmlParser::interfaces() const if (property.isNull()) continue; if (!QDBusUtil::isValidMemberName(propertyName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(propertyName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(propertyName), qPrintable(ifaceName)); continue; } @@ -231,10 +237,9 @@ QDBusXmlParser::interfaces() const if (!QDBusUtil::isValidSingleSignature(propertyData.type)) { // cannot be! - qWarning("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", - qPrintable(propertyData.type), qPrintable(ifaceName), - qPrintable(propertyName)); - continue; + qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", + qPrintable(propertyData.type), qPrintable(ifaceName), + qPrintable(propertyName)); } QString access = property.attribute(QLatin1String("access")); @@ -245,9 +250,9 @@ QDBusXmlParser::interfaces() const else if (access == QLatin1String("readwrite")) propertyData.access = QDBusIntrospection::Property::ReadWrite; else { - qWarning("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", - qPrintable(access), qPrintable(ifaceName), - qPrintable(propertyName)); + qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", + qPrintable(access), qPrintable(ifaceName), + qPrintable(propertyName)); continue; // invalid one! } @@ -286,8 +291,8 @@ QDBusXmlParser::object() const if (obj.isNull()) continue; // for whatever reason if (!QDBusUtil::isValidObjectPath(m_path + QLatin1Char('/') + objName)) { - qWarning("Invalid D-BUS object path '%s/%s' found while parsing introspection", - qPrintable(m_path), qPrintable(objName)); + qDBusParserError("Invalid D-BUS object path '%s/%s' found while parsing introspection", + qPrintable(m_path), qPrintable(objName)); continue; } @@ -301,8 +306,8 @@ QDBusXmlParser::object() const if (iface.isNull()) continue; if (!QDBusUtil::isValidInterfaceName(ifaceName)) { - qWarning("Invalid D-BUS interface name '%s' found while parsing introspection", - qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection", + qPrintable(ifaceName)); continue; } diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h index 1730d11..5e30350 100644 --- a/src/declarative/debugger/qdeclarativedebugservice_p.h +++ b/src/declarative/debugger/qdeclarativedebugservice_p.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeDebugServicePrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugService : public QObject +class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeDebugService) diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index c03c624..8f37e90 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -149,6 +149,20 @@ QT_BEGIN_NAMESPACE \sa Image, AnimatedImage */ +/*! + \qmlproperty bool BorderImage::asynchronous + + Specifies that images on the local filesystem should be loaded + asynchronously in a separate thread. The default value is + false, causing the user interface thread to block while the + image is loaded. Setting \a asynchronous to true is useful where + maintaining a responsive user interface is more desirable + than having images immediately visible. + + Note that this property is only valid for images read from the + local filesystem. Images loaded via a network resource (e.g. HTTP) + are always loaded asynchonously. +*/ QDeclarativeBorderImage::QDeclarativeBorderImage(QDeclarativeItem *parent) : QDeclarativeImageBase(*(new QDeclarativeBorderImagePrivate), parent) { @@ -200,6 +214,15 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() */ /*! + \qmlproperty bool BorderImage::cache + \since Quick 1.1 + + Specifies whether the image should be cached. The default value is + true. Setting \a cache to false is useful when dealing with large images, + to make sure that they aren't cached at the expense of small 'ui element' images. +*/ + +/*! \qmlproperty bool BorderImage::mirror \since Quick 1.1 diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 8b2d094..d64c347 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -143,7 +143,7 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() , stealMouse(false), pressed(false), interactive(true), calcVelocity(false) , deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600) - , vTime(0), visibleArea(0) + , fixupMode(Normal), vTime(0), visibleArea(0) , flickableDirection(QDeclarativeFlickable::AutoFlickDirection) , boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds) { @@ -219,6 +219,7 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal { Q_Q(QDeclarativeFlickable); qreal maxDistance = -1; + data.fixingUp = false; bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; // -ve velocity means list is moving up if (velocity > 0) { @@ -288,24 +289,45 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal if (data.move.value() > minExtent || maxExtent > minExtent) { timeline.reset(data.move); if (data.move.value() != minExtent) { - if (fixupDuration) { - qreal dist = minExtent - data.move; - timeline.move(data.move, minExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); - timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); - } else { + switch (fixupMode) { + case Immediate: timeline.set(data.move, minExtent); + break; + case ExtentChanged: + // The target has changed. Don't start from the beginning; just complete the + // second half of the animation using the new extent. + timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); + data.fixingUp = true; + break; + default: { + qreal dist = minExtent - data.move; + timeline.move(data.move, minExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); + data.fixingUp = true; + } } } } else if (data.move.value() < maxExtent) { timeline.reset(data.move); - if (fixupDuration) { - qreal dist = maxExtent - data.move; - timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); - timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); - } else { + switch (fixupMode) { + case Immediate: timeline.set(data.move, maxExtent); + break; + case ExtentChanged: + // The target has changed. Don't start from the beginning; just complete the + // second half of the animation using the new extent. + timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); + data.fixingUp = true; + break; + default: { + qreal dist = maxExtent - data.move; + timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); + timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); + data.fixingUp = true; + } } } + fixupMode = Normal; vTime = timeline.time(); } @@ -688,6 +710,12 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven vData.velocity = 0; hData.dragStartOffset = 0; vData.dragStartOffset = 0; + hData.dragMinBound = q->minXExtent(); + vData.dragMinBound = q->minYExtent(); + hData.dragMaxBound = q->maxXExtent(); + vData.dragMaxBound = q->maxYExtent(); + hData.fixingUp = false; + vData.fixingUp = false; lastPos = QPoint(); QDeclarativeItemPrivate::start(lastPosTime); pressPos = event->pos(); @@ -716,8 +744,8 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (!vMoved) vData.dragStartOffset = dy; qreal newY = dy + vData.pressPos - vData.dragStartOffset; - const qreal minY = q->minYExtent(); - const qreal maxY = q->maxYExtent(); + const qreal minY = vData.dragMinBound; + const qreal maxY = vData.dragMaxBound; if (newY > minY) newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY <= 0) @@ -748,8 +776,8 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (!hMoved) hData.dragStartOffset = dx; qreal newX = dx + hData.pressPos - hData.dragStartOffset; - const qreal minX = q->minXExtent(); - const qreal maxX = q->maxXExtent(); + const qreal minX = hData.dragMinBound; + const qreal maxX = hData.dragMaxBound; if (newX > minX) newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX <= 0) @@ -845,7 +873,8 @@ void QDeclarativeFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); if (d->interactive) { - d->handleMousePressEvent(event); + if (!d->pressed) + d->handleMousePressEvent(event); event->accept(); } else { QDeclarativeItem::mousePressEvent(event); @@ -910,11 +939,27 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) } } +bool QDeclarativeFlickablePrivate::isOutermostPressDelay() const +{ + Q_Q(const QDeclarativeFlickable); + QDeclarativeItem *item = q->parentItem(); + while (item) { + QDeclarativeFlickable *flick = qobject_cast<QDeclarativeFlickable*>(item); + if (flick && flick->pressDelay() > 0 && flick->isInteractive()) + return false; + item = item->parentItem(); + } + + return true; +} + void QDeclarativeFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); if (!q->scene() || pressDelay <= 0) return; + if (!isOutermostPressDelay()) + return; delayedPressTarget = q->scene()->mouseGrabberItem(); delayedPressEvent = new QGraphicsSceneMouseEvent(event->type()); delayedPressEvent->setAccepted(false); @@ -970,9 +1015,10 @@ void QDeclarativeFlickable::timerEvent(QTimerEvent *event) if (scene()->mouseGrabberItem() == d->delayedPressTarget) d->delayedPressTarget->ungrabMouse(); //Use the event handler that will take care of finding the proper item to propagate the event - QApplication::sendEvent(scene(), d->delayedPressEvent); + QApplication::postEvent(scene(), d->delayedPressEvent); + } else { + delete d->delayedPressEvent; } - delete d->delayedPressEvent; d->delayedPressEvent = 0; } } @@ -1047,10 +1093,8 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, } // Make sure that we're entirely in view. if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { - int oldDuration = d->fixupDuration; - d->fixupDuration = 0; + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupX(); - d->fixupDuration = oldDuration; } } if (newGeometry.height() != oldGeometry.height()) { @@ -1062,10 +1106,8 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, } // Make sure that we're entirely in view. if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { - int oldDuration = d->fixupDuration; - d->fixupDuration = 0; + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupY(); - d->fixupDuration = oldDuration; } } @@ -1240,10 +1282,11 @@ void QDeclarativeFlickable::setContentWidth(qreal w) d->contentItem->setWidth(w); // Make sure that we're entirely in view. if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { - int oldDuration = d->fixupDuration; - d->fixupDuration = 0; + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupX(); + } else if (!d->pressed && d->hData.fixingUp) { + d->fixupMode = QDeclarativeFlickablePrivate::ExtentChanged; d->fixupX(); - d->fixupDuration = oldDuration; } emit contentWidthChanged(); d->updateBeginningEnd(); @@ -1267,10 +1310,11 @@ void QDeclarativeFlickable::setContentHeight(qreal h) d->contentItem->setHeight(h); // Make sure that we're entirely in view. if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { - int oldDuration = d->fixupDuration; - d->fixupDuration = 0; + d->fixupMode = QDeclarativeFlickablePrivate::Immediate; + d->fixupY(); + } else if (!d->pressed && d->vData.fixingUp) { + d->fixupMode = QDeclarativeFlickablePrivate::ExtentChanged; d->fixupY(); - d->fixupDuration = oldDuration; } emit contentHeightChanged(); d->updateBeginningEnd(); @@ -1279,11 +1323,10 @@ void QDeclarativeFlickable::setContentHeight(qreal h) /*! \qmlmethod Flickable::resizeContent(real width, real height, QPointF center) \preliminary + \since Quick 1.1 Resizes the content to \a width x \a height about \a center. - \bold {This method was added in QtQuick 1.1.} - This does not scale the contents of the Flickable - it only resizes the \l contentWidth and \l contentHeight. @@ -1315,11 +1358,10 @@ void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center) /*! \qmlmethod Flickable::returnToBounds() \preliminary + \since Quick 1.1 Ensures the content is within legal bounds. - \bold {This method was added in QtQuick 1.1.} - This may be called to ensure that the content is within legal bounds after manually positioning the content. */ @@ -1364,6 +1406,22 @@ bool QDeclarativeFlickable::yflick() const return d->flickableDirection & QDeclarativeFlickable::VerticalFlick; } +bool QDeclarativeFlickable::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + Q_D(QDeclarativeFlickable); + if (d->pressed) { + // if our mouse grab has been removed (probably by another Flickable), + // fix our state + d->pressed = false; + d->stealMouse = false; + setKeepMouseGrab(false); + } + } + return rv; +} + bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); @@ -1391,7 +1449,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->handleMouseMoveEvent(&mouseEvent); break; case QEvent::GraphicsSceneMousePress: - if (d->delayedPressEvent) + if (d->pressed) // we are already pressed - this is a delayed replay return false; d->handleMousePressEvent(&mouseEvent); @@ -1410,6 +1468,8 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) // We send the release scene()->sendEvent(s->mouseGrabberItem(), event); // And the event has been consumed + d->stealMouse = false; + d->pressed = false; return true; } d->handleMouseReleaseEvent(&mouseEvent); @@ -1432,6 +1492,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->stealMouse = false; d->pressed = false; } + return false; } @@ -1530,6 +1591,9 @@ bool QDeclarativeFlickable::isFlickingVertically() const If the flickable is dragged/flicked before the delay times out the press event will not be delivered. If the button is released within the timeout, both the press and release will be delivered. + + Note that for nested Flickables with pressDelay set, the pressDelay of + inner Flickables is overridden by the outermost Flickable. */ int QDeclarativeFlickable::pressDelay() const { @@ -1622,6 +1686,7 @@ void QDeclarativeFlickable::movementXEnding() emit movementEnded(); } } + d->hData.fixingUp = false; } void QDeclarativeFlickable::movementYEnding() @@ -1644,6 +1709,7 @@ void QDeclarativeFlickable::movementYEnding() emit movementEnded(); } } + d->vData.fixingUp = false; } void QDeclarativeFlickablePrivate::updateVelocity() diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 4fde1d5..a14cc1c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -204,6 +204,7 @@ protected: virtual void viewportMoved(); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + bool sceneEvent(QEvent *event); bool sendMouseEvent(QGraphicsSceneMouseEvent *event); bool xflick() const; diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 5ad6ff6..38a5eb3 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -94,17 +94,21 @@ public: struct AxisData { AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal)) : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true) + , fixingUp(false) {} QDeclarativeTimeLineValueProxy<QDeclarativeFlickablePrivate> move; qreal viewSize; qreal pressPos; qreal dragStartOffset; + qreal dragMinBound; + qreal dragMaxBound; qreal velocity; qreal flickTarget; QDeclarativeFlickablePrivate::Velocity smoothVelocity; bool atEnd : 1; bool atBeginning : 1; + bool fixingUp : 1; }; void flickX(qreal velocity); @@ -118,6 +122,7 @@ public: void updateBeginningEnd(); + bool isOutermostPressDelay() const; void captureDelayedPress(QGraphicsSceneMouseEvent *event); void clearDelayedPress(); @@ -160,6 +165,9 @@ public: int pressDelay; int fixupDuration; + enum FixupMode { Normal, Immediate, ExtentChanged }; + FixupMode fixupMode; + static void fixupY_callback(void *); static void fixupX_callback(void *); diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 694130b..1d2ad1c 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -82,7 +82,7 @@ public: item->setPos(QPointF(row, col)); } } - bool contains(int x, int y) const { + bool contains(qreal x, qreal y) const { return (x >= item->x() && x < item->x() + view->cellWidth() && y >= item->y() && y < item->y() + view->cellHeight()); } @@ -912,8 +912,7 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m || (flow == QDeclarativeGridView::LeftToRight && &data == &hData)) return; - int oldDuration = fixupDuration; - fixupDuration = moveReason == Mouse ? fixupDuration : 0; + fixupMode = moveReason == Mouse ? fixupMode : Immediate; if (snapMode != QDeclarativeGridView::NoSnap) { FxGridItem *topItem = snapItemAt(position()+highlightRangeStart); @@ -932,7 +931,6 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m pos = qMax(qMin(bottomItem->rowPos() - highlightRangeStart, -maxExtent), -minExtent); } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); - fixupDuration = oldDuration; return; } if (currentItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) { @@ -947,10 +945,12 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m qreal dist = qAbs(data.move + pos); if (dist > 0) { timeline.reset(data.move); - if (fixupDuration) + if (fixupMode != Immediate) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + data.fixingUp = true; + } else { timeline.set(data.move, -pos); + } vTime = timeline.time(); } } else if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) { @@ -965,23 +965,26 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); if (viewPos != position()) { - if (fixupDuration) + if (fixupMode != Immediate) { timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + data.fixingUp = true; + } else { timeline.set(data.move, -viewPos); + } } vTime = timeline.time(); } } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } - fixupDuration = oldDuration; + fixupMode = Normal; } void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity) { Q_Q(QDeclarativeGridView); + data.fixingUp = false; moveReason = Mouse; if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange) && snapMode == QDeclarativeGridView::NoSnap) { @@ -2250,6 +2253,7 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) /*! \qmlmethod GridView::positionViewAtBeginning() \qmlmethod GridView::positionViewAtEnd() + \since Quick 1.1 Positions the view at the beginning or end, taking into account any header or footer. @@ -2294,7 +2298,7 @@ void QDeclarativeGridView::positionViewAtEnd() \bold Note: methods should only be called after the Component has completed. */ -int QDeclarativeGridView::indexAt(int x, int y) const +int QDeclarativeGridView::indexAt(qreal x, qreal y) const { Q_D(const QDeclarativeGridView); for (int i = 0; i < d->visibleItems.count(); ++i) { diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index 248b9ef..e68a9ba 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -158,7 +158,7 @@ public: enum PositionMode { Beginning, Center, End, Visible, Contain }; Q_INVOKABLE void positionViewAtIndex(int index, int mode); - Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE int indexAt(qreal x, qreal y) const; Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index bc4a2d0..3c8f64e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -180,6 +180,7 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType<QDeclarativePinch>("QtQuick",1,1,"Pinch"); qmlRegisterType<QDeclarativePinchEvent>(); qmlRegisterType<QDeclarativeItem,1>("QtQuick",1,1,"Item"); + qmlRegisterType<QDeclarativeMouseArea,1>("QtQuick",1,1,"MouseArea"); qmlRegisterType<QDeclarativeFlickable,1>("QtQuick",1,1,"Flickable"); qmlRegisterType<QDeclarativeListView,1>("QtQuick",1,1,"ListView"); qmlRegisterType<QDeclarativeGridView,1>("QtQuick",1,1,"GridView"); diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index a60a4aa..e369ba6 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -148,7 +148,7 @@ public: else item->setWidth(size); } - bool contains(int x, int y) const { + bool contains(qreal x, qreal y) const { return (x >= item->x() && x < item->x() + item->width() && y >= item->y() && y < item->y() + item->height()); } @@ -228,6 +228,26 @@ public: return 0; } + // Returns the item before modelIndex, if created. + // May return an item marked for removal. + FxListItem *itemBefore(int modelIndex) const { + if (modelIndex < visibleIndex) + return 0; + int idx = 1; + int lastIndex = -1; + while (idx < visibleItems.count()) { + FxListItem *item = visibleItems.at(idx); + if (item->index != -1) + lastIndex = item->index; + if (item->index == modelIndex) + return visibleItems.at(idx-1); + ++idx; + } + if (lastIndex == modelIndex-1) + return visibleItems.last(); + return 0; + } + qreal position() const { Q_Q(const QDeclarativeListView); return orient == QDeclarativeListView::Vertical ? q->contentY() : q->contentX(); @@ -561,7 +581,7 @@ FxListItem *QDeclarativeListViewPrivate::createItem(int modelIndex) QString propValue = model->stringValue(modelIndex, sectionCriteria->property()); listItem->attached->m_section = sectionCriteria->sectionString(propValue); if (modelIndex > 0) { - if (FxListItem *item = visibleItem(modelIndex-1)) + if (FxListItem *item = itemBefore(modelIndex)) listItem->attached->m_prevSection = item->attached->section(); else listItem->attached->m_prevSection = sectionAt(modelIndex-1); @@ -922,7 +942,7 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) } else { QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q)); context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); - QObject *nobj = sectionCriteria->delegate()->create(context); + QObject *nobj = sectionCriteria->delegate()->beginCreate(context); if (nobj) { QDeclarative_setParent_noEvent(context, nobj); listItem->section = qobject_cast<QDeclarativeItem *>(nobj); @@ -936,6 +956,7 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) } else { delete context; } + sectionCriteria->delegate()->completeCreate(); } listItem->setPosition(pos); } else { @@ -969,18 +990,18 @@ void QDeclarativeListViewPrivate::updateSections() QDeclarativeListViewAttached *prevAtt = 0; int idx = -1; for (int i = 0; i < visibleItems.count(); ++i) { + QDeclarativeListViewAttached *attached = visibleItems.at(i)->attached; + attached->setPrevSection(prevSection); if (visibleItems.at(i)->index != -1) { - QDeclarativeListViewAttached *attached = visibleItems.at(i)->attached; - attached->setPrevSection(prevSection); QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property()); attached->setSection(sectionCriteria->sectionString(propValue)); - if (prevAtt) - prevAtt->setNextSection(attached->section()); - createSection(visibleItems.at(i)); - prevSection = attached->section(); - prevAtt = attached; idx = visibleItems.at(i)->index; } + createSection(visibleItems.at(i)); + if (prevAtt) + prevAtt->setNextSection(attached->section()); + prevSection = attached->section(); + prevAtt = attached; } if (prevAtt) { if (idx > 0 && idx < model->count()-1) @@ -1177,8 +1198,7 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m return; correctFlick = false; - int oldDuration = fixupDuration; - fixupDuration = moveReason == Mouse ? fixupDuration : 0; + fixupMode = moveReason == Mouse ? fixupMode : Immediate; if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange) { updateHighlight(); @@ -1191,10 +1211,12 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); if (viewPos != position()) { - if (fixupDuration) + if (fixupMode != Immediate) { timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + data.fixingUp = true; + } else { timeline.set(data.move, -viewPos); + } } vTime = timeline.time(); } else if (snapMode != QDeclarativeListView::NoSnap) { @@ -1210,23 +1232,24 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m pos = qMax(qMin(bottomItem->position() - highlightRangeStart, -maxExtent), -minExtent); } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); - fixupDuration = oldDuration; return; } qreal dist = qAbs(data.move + pos); if (dist > 0) { timeline.reset(data.move); - if (fixupDuration) + if (fixupMode != Immediate) { timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - else + data.fixingUp = true; + } else { timeline.set(data.move, -pos); + } vTime = timeline.time(); } } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } - fixupDuration = oldDuration; + fixupMode = Normal; } void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, @@ -1234,6 +1257,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m { Q_Q(QDeclarativeListView); + data.fixingUp = false; moveReason = Mouse; if ((!haveHighlightRange || highlightRange != QDeclarativeListView::StrictlyEnforceRange) && snapMode == QDeclarativeListView::NoSnap) { correctFlick = true; @@ -2688,6 +2712,7 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) /*! \qmlmethod ListView::positionViewAtBeginning() \qmlmethod ListView::positionViewAtEnd() + \since Quick 1.1 Positions the view at the beginning or end, taking into account any header or footer. @@ -2732,7 +2757,7 @@ void QDeclarativeListView::positionViewAtEnd() \bold Note: methods should only be called after the Component has completed. */ -int QDeclarativeListView::indexAt(int x, int y) const +int QDeclarativeListView::indexAt(qreal x, qreal y) const { Q_D(const QDeclarativeListView); for (int i = 0; i < d->visibleItems.count(); ++i) { @@ -2777,6 +2802,8 @@ void QDeclarativeListView::updateSections() roles << d->sectionCriteria->property().toUtf8(); d->model->setWatchedRoles(roles); d->updateSections(); + if (d->itemCount) + d->layout(); } } @@ -3096,6 +3123,7 @@ void QDeclarativeListView::destroyRemoved() } // Correct the positioning of the items + d->updateSections(); d->layout(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 10fbf10..265f4bd 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -208,7 +208,7 @@ public: enum PositionMode { Beginning, Center, End, Visible, Contain }; Q_INVOKABLE void positionViewAtIndex(int index, int mode); - Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE int indexAt(qreal x, qreal y) const; Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 5b73a29..da11b00 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -416,6 +416,40 @@ void QDeclarativeMouseArea::setEnabled(bool a) emit enabledChanged(); } } + +/*! + \qmlproperty bool MouseArea::preventStealing + \since Quick 1.1 + This property holds whether the mouse events may be stolen from this + MouseArea. + + If a MouseArea is placed within an item that filters child mouse + events, such as Flickable, the mouse + events may be stolen from the MouseArea if a gesture is recognized + by the parent element, e.g. a flick gesture. If preventStealing is + set to true, no element will steal the mouse events. + + Note that setting preventStealing to true once an element has started + stealing events will have no effect until the next press event. + + By default this property is false. +*/ +bool QDeclarativeMouseArea::preventStealing() const +{ + Q_D(const QDeclarativeMouseArea); + return d->preventStealing; +} + +void QDeclarativeMouseArea::setPreventStealing(bool prevent) +{ + Q_D(QDeclarativeMouseArea); + if (prevent != d->preventStealing) { + d->preventStealing = prevent; + setKeepMouseGrab(d->preventStealing && d->absorb); + emit preventStealingChanged(); + } +} + /*! \qmlproperty MouseButtons MouseArea::pressedButtons This property holds the mouse buttons currently pressed. @@ -443,7 +477,7 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeMouseArea); d->moved = false; - d->stealMouse = false; + d->stealMouse = d->preventStealing; if (!d->absorb) QDeclarativeItem::mousePressEvent(event); else { @@ -460,7 +494,7 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) // we should only start timer if pressAndHold is connected to. if (d->isPressAndHoldConnected()) d->pressAndHoldTimer.start(PressAndHoldDelay, this); - setKeepMouseGrab(false); + setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(true)); } } diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index 937ac78..985f27e 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -129,6 +129,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeMouseArea : public QDeclarativeItem Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged) Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged) Q_PROPERTY(QDeclarativeDrag *drag READ drag CONSTANT) //### add flicking to QDeclarativeDrag or add a QDeclarativeFlick ??? + Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) public: QDeclarativeMouseArea(QDeclarativeItem *parent=0); @@ -153,6 +154,9 @@ public: QDeclarativeDrag *drag(); + bool preventStealing() const; + void setPreventStealing(bool prevent); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); @@ -161,6 +165,7 @@ Q_SIGNALS: void hoverEnabledChanged(); void positionChanged(QDeclarativeMouseEvent *mouse); void mousePositionChanged(QDeclarativeMouseEvent *mouse); + Q_REVISION(1) void preventStealingChanged(); void pressed(QDeclarativeMouseEvent *mouse); void pressAndHold(QDeclarativeMouseEvent *mouse); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h index 2a327af..67694fb 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h @@ -68,7 +68,7 @@ class QDeclarativeMouseAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativeMouseAreaPrivate() : absorb(true), hovered(false), pressed(false), longPress(false), - moved(false), stealMouse(false), doubleClick(false), drag(0) + moved(false), stealMouse(false), doubleClick(false), preventStealing(false), drag(0) { } @@ -110,6 +110,7 @@ public: bool dragY : 1; bool stealMouse : 1; bool doubleClick : 1; + bool preventStealing : 1; QDeclarativeDrag *drag; QPointF startScene; qreal startX; diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 27a1301..c0be2a2 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -584,6 +584,8 @@ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent) /*! \qmlproperty enumeration Row::layoutDirection + \since Quick 1.1 + This property holds the layoutDirection of the row. Possible values: @@ -859,6 +861,8 @@ void QDeclarativeGrid::setFlow(Flow flow) /*! \qmlproperty enumeration Grid::layoutDirection + \since Quick 1.1 + This property holds the layout direction of the layout. Possible values are: @@ -1201,6 +1205,8 @@ void QDeclarativeFlow::setFlow(Flow flow) /*! \qmlproperty enumeration Flow::layoutDirection + \since Quick 1.1 + This property holds the layout direction of the layout. Possible values are: diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 049169e..044425d 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -1168,6 +1168,7 @@ void QDeclarativeText::setWrapMode(WrapMode mode) /*! \qmlproperty int Text::lineCount + \since Quick 1.1 Returns the number of lines visible in the text item. @@ -1183,6 +1184,7 @@ int QDeclarativeText::lineCount() const /*! \qmlproperty bool Text::truncated + \since Quick 1.1 Returns true if the text has been truncated due to \l maximumLineCount or \l elide. @@ -1199,6 +1201,7 @@ bool QDeclarativeText::truncated() const /*! \qmlproperty int Text::maximumLineCount + \since Quick 1.1 Set this property to limit the number of lines that the text item will show. If elide is set to Text.ElideRight, the text will be elided appropriately. @@ -1451,6 +1454,7 @@ qreal QDeclarativeText::paintedHeight() const /*! \qmlproperty real Text::lineHeight + \since Quick 1.1 Sets the line height for the text. The value can be in pixels or a multiplier depending on lineHeightMode. diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index e2f6265..d3c5b82 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -544,6 +544,7 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) /*! \qmlproperty int TextEdit::lineCount + \since Quick 1.1 Returns the total number of lines in the textEdit item. */ @@ -605,6 +606,22 @@ int QDeclarativeTextEdit::positionAt(int x, int y) const { Q_D(const QDeclarativeTextEdit); int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit); + QTextCursor cursor = d->control->textCursor(); + if (r > cursor.position()) { + // The cursor position includes positions within the preedit text, but only positions in the + // same text block are offset so it is possible to get a position that is either part of the + // preedit or the next text block. + QTextLayout *layout = cursor.block().layout(); + const int preeditLength = layout + ? layout->preeditAreaText().length() + : 0; + if (preeditLength > 0 + && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) { + r = r > cursor.position() + preeditLength + ? r - preeditLength + : cursor.position(); + } + } return r; } @@ -977,6 +994,10 @@ void QDeclarativeTextEdit::setSelectByMouse(bool on) if (d->selectByMouse != on) { d->selectByMouse = on; setKeepMouseGrab(on); + if (on) + setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse); + else + setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse); emit selectByMouseChanged(on); } } @@ -1029,11 +1050,10 @@ void QDeclarativeTextEdit::setReadOnly(bool r) setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r); Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse; - if (r) { + if (d->selectByMouse) flags = flags | Qt::TextSelectableByMouse; - } else { - flags = flags | Qt::TextEditorInteraction; - } + if (!r) + flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable; d->control->setTextInteractionFlags(flags); if (!r) d->control->moveCursor(QTextCursor::End); @@ -1125,12 +1145,13 @@ void QDeclarativeTextEdit::keyReleaseEvent(QKeyEvent *event) void QDeclarativeTextEditPrivate::focusChanged(bool hasFocus) { Q_Q(QDeclarativeTextEdit); - q->setCursorVisible(hasFocus); + q->setCursorVisible(hasFocus && scene && scene->hasFocus()); QDeclarativeItemPrivate::focusChanged(hasFocus); } /*! \qmlmethod void TextEdit::deselect() + \since Quick 1.1 Removes active text selection. */ @@ -1251,8 +1272,8 @@ void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) } } } - if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse) - d->control->processEvent(event, QPointF(0, -d->yoff)); + + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mousePressEvent(event); } @@ -1287,13 +1308,11 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, -d->yoff)); - if (!event->isAccepted()) - QDeclarativePaintedItem::mouseDoubleClickEvent(event); - } else { + + d->control->processEvent(event, QPointF(0, -d->yoff)); + if (!event->isAccepted()) QDeclarativePaintedItem::mouseDoubleClickEvent(event); - } + } /*! @@ -1303,14 +1322,9 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, -d->yoff)); - if (!event->isAccepted()) - QDeclarativePaintedItem::mouseMoveEvent(event); - event->setAccepted(true); - } else { + d->control->processEvent(event, QPointF(0, -d->yoff)); + if (!event->isAccepted()) QDeclarativePaintedItem::mouseMoveEvent(event); - } } /*! @@ -1320,7 +1334,10 @@ Handles the given input method \a event. void QDeclarativeTextEdit::inputMethodEvent(QInputMethodEvent *event) { Q_D(QDeclarativeTextEdit); + const bool wasComposing = isInputMethodComposing(); d->control->processEvent(event, QPointF(0, -d->yoff)); + if (wasComposing != isInputMethodComposing()) + emit inputMethodComposingChanged(); } /*! @@ -1385,19 +1402,38 @@ void QDeclarativeTextEdit::updateImgCache(const QRectF &rf) /*! \qmlproperty bool TextEdit::canPaste + \since QtQuick 1.1 Returns true if the TextEdit is writable and the content of the clipboard is suitable for pasting into the TextEdit. - - \since QtQuick 1.1 */ - bool QDeclarativeTextEdit::canPaste() const { Q_D(const QDeclarativeTextEdit); return d->canPaste; } +/*! + \qmlproperty bool TextEdit::isInputMethodComposing() + + \since QtQuick 1.1 + + This property holds whether the TextEdit has partial text input from an + input method. + + While it is composing an input method may rely on mouse or key events from + the TextEdit to edit or commit the partial text. This property can be used + to determine when to disable events handlers that may interfere with the + correct operation of an input method. +*/ +bool QDeclarativeTextEdit::isInputMethodComposing() const +{ + Q_D(const QDeclarativeTextEdit); + if (QTextLayout *layout = d->control->textCursor().block().layout()) + return layout->preeditAreaText().length() > 0; + return false; +} + void QDeclarativeTextEditPrivate::init() { Q_Q(QDeclarativeTextEdit); @@ -1409,7 +1445,7 @@ void QDeclarativeTextEditPrivate::init() control = new QTextControl(q); control->setIgnoreUnusedNavigationEvents(true); - control->setTextInteractionFlags(control->textInteractionFlags() | Qt::LinksAccessibleByMouse); + control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable); control->setDragEnabled(false); // QTextControl follows the default text color @@ -1433,6 +1469,7 @@ void QDeclarativeTextEditPrivate::init() #ifndef QT_NO_CLIPBOARD QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged())); QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged())); + canPaste = control->canPaste(); #endif document = control->document(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 7785a7a..612f9a9 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -94,6 +94,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativeImplicitSizePa Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) + Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged REVISION 1) public: QDeclarativeTextEdit(QDeclarativeItem *parent=0); @@ -215,6 +216,8 @@ public: QRectF boundingRect() const; + bool isInputMethodComposing() const; + Q_SIGNALS: void textChanged(const QString &); void paintedSizeChanged(); @@ -242,6 +245,7 @@ Q_SIGNALS: Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); Q_REVISION(1) void linkActivated(const QString &link); Q_REVISION(1) void canPasteChanged(); + Q_REVISION(1) void inputMethodComposingChanged(); public Q_SLOTS: void selectAll(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 3c95ab8..29b1f6b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -51,6 +51,7 @@ #include <QFontMetrics> #include <QPainter> #include <QTextBoundaryFinder> +#include <QInputContext> #include <qstyle.h> #ifndef QT_NO_LINEEDIT @@ -481,6 +482,7 @@ QRect QDeclarativeTextInput::cursorRectangle() const Q_D(const QDeclarativeTextInput); QRect r = d->control->cursorRect(); r.setHeight(r.height()-1); // Make consistent with TextEdit (QLineControl inexplicably adds 1) + r.moveLeft(r.x() - d->hscroll); return r; } @@ -920,14 +922,22 @@ void QDeclarativeTextInput::moveCursor() QRectF QDeclarativeTextInput::positionToRectangle(int pos) const { Q_D(const QDeclarativeTextInput); + if (pos > d->control->cursorPosition()) + pos += d->control->preeditAreaText().length(); return QRectF(d->control->cursorToX(pos)-d->hscroll, 0.0, d->control->cursorWidth(), cursorRectangle().height()); } +int QDeclarativeTextInput::positionAt(int x) const +{ + return positionAt(x, CursorBetweenCharacters); +} + /*! - \qmlmethod int TextInput::positionAt(int x) + \qmlmethod int TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters) + \since Quick 1.1 This function returns the character position at x pixels from the left of the textInput. Position 0 is before the @@ -936,18 +946,33 @@ QRectF QDeclarativeTextInput::positionToRectangle(int pos) const This means that for all x values before the first character this function returns 0, and for all x values after the last character this function returns text.length. + + The cursor position type specifies how the cursor position should be resolved. + + \list + \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x. + \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x. + \endlist */ -int QDeclarativeTextInput::positionAt(int x) const +int QDeclarativeTextInput::positionAt(int x, CursorPosition position) const { Q_D(const QDeclarativeTextInput); - return d->control->xToPos(x + d->hscroll); + int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position)); + const int cursor = d->control->cursor(); + if (pos > cursor) { + const int preeditLength = d->control->preeditAreaText().length(); + pos = pos > cursor + preeditLength + ? pos - preeditLength + : cursor; + } + return pos; } void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) { Q_Q(QDeclarativeTextInput); focused = hasFocus; - q->setCursorVisible(hasFocus); + q->setCursorVisible(hasFocus && scene && scene->hasFocus()); if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus) control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events if (!hasFocus) @@ -981,18 +1006,22 @@ void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev) { Q_D(QDeclarativeTextInput); ev->ignore(); + const bool wasComposing = d->control->preeditAreaText().length() > 0; inputMethodPreHandler(ev); - if (ev->isAccepted()) - return; - if (d->control->isReadOnly()) { - ev->ignore(); - } else { - d->control->processInputMethodEvent(ev); - updateSize(); - d->updateHorizontalScroll(); + if (!ev->isAccepted()) { + if (d->control->isReadOnly()) { + ev->ignore(); + } else { + d->control->processInputMethodEvent(ev); + updateSize(); + d->updateHorizontalScroll(); + } } if (!ev->isAccepted()) QDeclarativePaintedItem::inputMethodEvent(ev); + + if (wasComposing != (d->control->preeditAreaText().length() > 0)) + emit inputMethodComposingChanged(); } /*! @@ -1002,6 +1031,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick)) + return; if (d->selectByMouse) { int cursor = d->xToPos(event->pos().x()); d->control->selectWordAtPos(cursor); @@ -1014,6 +1045,8 @@ void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress)) + return; if(d->focusOnPress){ bool hadActiveFocus = hasActiveFocus(); forceActiveFocus(); @@ -1041,6 +1074,8 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseMove)) + return; if (d->selectByMouse) { if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance()) setKeepMouseGrab(true); @@ -1058,6 +1093,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease)) + return; if (d->selectByMouse) setKeepMouseGrab(false); if (!d->showInputPanelOnFocus) { // input panel on click @@ -1075,6 +1112,44 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QDeclarativePaintedItem::mouseReleaseEvent(event); } +bool QDeclarativeTextInputPrivate::sendMouseEventToInputContext( + QGraphicsSceneMouseEvent *event, QEvent::Type eventType) +{ +#if !defined QT_NO_IM + if (event->widget() && control->composeMode()) { + int tmp_cursor = xToPos(event->pos().x()); + int mousePos = tmp_cursor - control->cursor(); + if (mousePos < 0 || mousePos > control->preeditAreaText().length()) { + mousePos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + + QInputContext *qic = event->widget()->inputContext(); + if (qic) { + QMouseEvent mouseEvent( + eventType, + event->widget()->mapFromGlobal(event->screenPos()), + event->screenPos(), + event->button(), + event->buttons(), + event->modifiers()); + // may be causing reset() in some input methods + qic->mouseHandler(mousePos, &mouseEvent); + event->setAccepted(mouseEvent.isAccepted()); + } + if (!control->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(event); + Q_UNUSED(eventType) +#endif + + return false; +} + bool QDeclarativeTextInput::sceneEvent(QEvent *event) { bool rv = QDeclarativeItem::sceneEvent(event); @@ -1213,7 +1288,7 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) Q_D(const QDeclarativeTextInput); switch(property) { case Qt::ImMicroFocus: - return d->control->cursorRect(); + return cursorRectangle(); case Qt::ImFont: return font(); case Qt::ImCursorPosition: @@ -1238,6 +1313,7 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) /*! \qmlmethod void TextInput::deselect() + \since Quick 1.1 Removes active text selection. */ @@ -1419,6 +1495,13 @@ void QDeclarativeTextInput::setMouseSelectionMode(SelectionMode mode) } } +/*! + \qmlproperty bool TextInput::canPaste + \since QtQuick 1.1 + + Returns true if the TextInput is writable and the content of the clipboard is + suitable for pasting into the TextEdit. +*/ bool QDeclarativeTextInput::canPaste() const { Q_D(const QDeclarativeTextInput); @@ -1487,38 +1570,41 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) anchor = d->control->selectionStart(); if (anchor < pos || (anchor == pos && cursor < pos)) { - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + const QString text = d->control->text(); + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); finder.setPosition(anchor); const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (!(reasons & QTextBoundaryFinder::StartWord) + if (anchor < text.length() && !(reasons & QTextBoundaryFinder::StartWord) || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor)) { finder.toPreviousBoundary(); } - anchor = finder.position(); + anchor = finder.position() != -1 ? finder.position() : 0; finder.setPosition(pos); - if (!finder.isAtBoundary()) + if (pos > 0 && !finder.boundaryReasons()) finder.toNextBoundary(); + const int cursor = finder.position() != -1 ? finder.position() : text.length(); - d->control->setSelection(anchor, finder.position() - anchor); + d->control->setSelection(anchor, cursor - anchor); } else if (anchor > pos || (anchor == pos && cursor > pos)) { - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + const QString text = d->control->text(); + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); finder.setPosition(anchor); const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (!(reasons & QTextBoundaryFinder::EndWord) + if (anchor > 0 && !(reasons & QTextBoundaryFinder::EndWord) || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor)) { finder.toNextBoundary(); } - - anchor = finder.position(); + anchor = finder.position() != -1 ? finder.position() : text.length(); finder.setPosition(pos); - if (!finder.isAtBoundary()) + if (pos < text.length() && !finder.boundaryReasons()) finder.toPreviousBoundary(); + const int cursor = finder.position() != -1 ? finder.position() : 0; - d->control->setSelection(anchor, finder.position() - anchor); + d->control->setSelection(anchor, cursor - anchor); } } } @@ -1637,6 +1723,25 @@ void QDeclarativeTextInput::focusInEvent(QFocusEvent *event) QDeclarativePaintedItem::focusInEvent(event); } +/*! + \qmlproperty bool TextInput::isInputMethodComposing() + + \since QtQuick 1.1 + + This property holds whether the TextInput has partial text input from an + input method. + + While it is composing an input method may rely on mouse or key events from + the TextInput to edit or commit the partial text. This property can be + used to determine when to disable events handlers that may interfere with + the correct operation of an input method. +*/ +bool QDeclarativeTextInput::isInputMethodComposing() const +{ + Q_D(const QDeclarativeTextInput); + return d->control->preeditAreaText().length() > 0; +} + void QDeclarativeTextInputPrivate::init() { Q_Q(QDeclarativeTextInput); @@ -1661,7 +1766,10 @@ void QDeclarativeTextInputPrivate::init() q, SLOT(q_canPasteChanged())); q->connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged())); + canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0; #endif // QT_NO_CLIPBOARD + q->connect(control, SIGNAL(updateMicroFocus()), + q, SLOT(updateMicroFocus())); q->updateSize(); oldValidity = control->hasAcceptableInput(); lastSelectionStart = 0; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index e1e66a9..822d5e2 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -97,6 +97,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizeP Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) + Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged REVISION 1) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); @@ -120,8 +121,14 @@ public: SelectWords }; + enum CursorPosition { + CursorBetweenCharacters, + CursorOnCharacter + }; + //Auxilliary functions needed to control the TextInput from QML Q_INVOKABLE int positionAt(int x) const; + Q_INVOKABLE Q_REVISION(1) int positionAt(int x, CursorPosition position) const; Q_INVOKABLE QRectF positionToRectangle(int pos) const; Q_INVOKABLE void moveCursorSelection(int pos); Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode); @@ -204,6 +211,8 @@ public: QRectF boundingRect() const; bool canPaste() const; + bool isInputMethodComposing() const; + Q_SIGNALS: void textChanged(); void cursorPositionChanged(); @@ -231,6 +240,7 @@ Q_SIGNALS: void selectByMouseChanged(bool selectByMouse); Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); Q_REVISION(1) void canPasteChanged(); + Q_REVISION(1) void inputMethodComposingChanged(); protected: virtual void geometryChanged(const QRectF &newGeometry, diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index f7446b4..ab2838b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -104,6 +104,7 @@ public: void focusChanged(bool hasFocus); void updateHorizontalScroll(); int calculateTextWidth(); + bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType); QLineControl* control; diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp index b24dd2c..31819f5 100644 --- a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp @@ -99,7 +99,6 @@ class DrawTextItemRecorder: public QPaintEngine needFreshCurrentItem = false; last.numChars += ti.num_chars; - last.numGlyphs += ti.glyphs.numGlyphs; } } @@ -111,7 +110,7 @@ class DrawTextItemRecorder: public QPaintEngine currentItem.font = ti.font(); currentItem.charOffset = charOffset; currentItem.numChars = ti.num_chars; - currentItem.numGlyphs = ti.glyphs.numGlyphs; + currentItem.numGlyphs = 0; currentItem.glyphOffset = glyphOffset; currentItem.positionOffset = positionOffset; currentItem.useBackendOptimizations = m_useBackendOptimizations; @@ -121,6 +120,8 @@ class DrawTextItemRecorder: public QPaintEngine m_inertText->items.append(currentItem); } + QStaticTextItem ¤tItem = m_inertText->items.last(); + QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform(); matrix.translate(position.x(), position.y()); @@ -129,18 +130,18 @@ class DrawTextItemRecorder: public QPaintEngine ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); int size = glyphs.size(); - Q_ASSERT(size == ti.glyphs.numGlyphs); Q_ASSERT(size == positions.size()); + currentItem.numGlyphs += size; m_inertText->glyphs.resize(m_inertText->glyphs.size() + size); m_inertText->positions.resize(m_inertText->glyphs.size()); m_inertText->chars.resize(m_inertText->chars.size() + ti.num_chars); glyph_t *glyphsDestination = m_inertText->glyphs.data() + glyphOffset; - qMemCopy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * ti.glyphs.numGlyphs); + qMemCopy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * size); QFixedPoint *positionsDestination = m_inertText->positions.data() + positionOffset; - qMemCopy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * ti.glyphs.numGlyphs); + qMemCopy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * size); QChar *charsDestination = m_inertText->chars.data() + charOffset; qMemCopy(charsDestination, ti.chars, sizeof(QChar) * ti.num_chars); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 5840f70..fc393d1 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -615,10 +615,11 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q } /*! - \qmlmethod object Component::createObject(Item parent, Script valuemap = null) + \qmlmethod object Component::createObject(Item parent, object properties) - Creates and returns an object instance of this component that will have the given - \a parent. Returns null if object creation fails. + Creates and returns an object instance of this component that will have + the given \a parent and \a properties. The \a properties argument is optional. + Returns null if object creation fails. The object will be created in the same context as the one in which the component was created. This function will always return null when called on components @@ -630,14 +631,23 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q property, or else the object will not be visible. If a \a parent is not provided to createObject(), a reference to the returned object must be held so that - it is not destroyed by the garbage collector. This is regardless of Item.parent being set afterwards, + it is not destroyed by the garbage collector. This is true regardless of whether \l{Item::parent} is set afterwards, since setting the Item parent does not change object ownership; only the graphical parent is changed. - Since QtQuick 1.1, a map of property values can be optionally passed to the method that applies values to the object's properties - before its creation is finalised. This will avoid binding issues that can occur when the object is - instantiated before property bindings have been set. For example: + As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a + map of initial property values for the created object. These values are applied before object + creation is finalized. (This is more efficient than setting property values after object creation, + particularly where large sets of property values are defined, and also allows property bindings + to be set up before the object is created.) - \code component.createObject(parent, {"x": 100, "y": 100, "specialProperty": someObject}); \endcode + The \a properties argument is specified as a map of property-value items. For example, the code + below creates an object with initial \c x and \c y values of 100 and 200, respectively: + + \qml + var component = Qt.createComponent("Button.qml"); + if (component.status == Component.Ready) + component.createObject(parent, {"x": 100, "y": 100}); + \endqml Dynamically created instances can be deleted with the \c destroy() method. See \l {Dynamic Object Management in QML} for more information. @@ -870,7 +880,6 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -878,7 +887,6 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); - enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -909,7 +917,6 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -917,7 +924,6 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); - enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -955,14 +961,17 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri QDeclarativeEnginePrivate::clear(ps); } - for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) { - QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii); - QObject *obj = status.first; - if (obj) { - void *args[] = { 0 }; - QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, - status.second, args); + if (1 == enginePriv->inProgressCreations) { + for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) { + QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii); + QObject *obj = status.first; + if (obj) { + void *args[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, + status.second, args); + } } + enginePriv->finalizedParserStatus.clear(); } while (state->componentAttached) { @@ -977,7 +986,6 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri state->bindValues.clear(); state->parserStatus.clear(); - state->finalizedParserStatus.clear(); state->completePending = false; enginePriv->inProgressCreations--; @@ -987,7 +995,6 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri enginePriv->erroredBindings->removeError(); } } - } } diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index f8bec2b..020c5e0 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -101,7 +101,6 @@ public: ConstructionState() : componentAttached(0), completePending(false) {} QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> > bindValues; QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> > parserStatus; - QList<QPair<QDeclarativeGuard<QObject>, int> > finalizedParserStatus; QDeclarativeComponentAttached *componentAttached; QList<QDeclarativeError> errors; bool completePending; diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 8c7f3ad..31fd516 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -167,17 +167,19 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx) QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const { int userType = value.userType(); - if (QDeclarativeValueTypeFactory::isValueType(userType)) - return value; - /* - if (QDeclarativeMetaType::isList(userType)) { - int count = QDeclarativeMetaType::listCount(value); + if (value.type() == QVariant::List) { QVariantList contents; - for (int i=0; i<count; i++) - contents << valueContents(QDeclarativeMetaType::listAt(value, i)); + QVariantList list = value.toList(); + int count = list.size(); + for (int i = 0; i < count; i++) + contents << valueContents(list.at(i)); return contents; - } else */ + } + + if (QDeclarativeValueTypeFactory::isValueType(userType)) + return value; + if (QDeclarativeMetaType::isQObject(userType)) { QObject *o = QDeclarativeMetaType::toQObject(value); if (o) { diff --git a/src/declarative/qml/qdeclarativelist.cpp b/src/declarative/qml/qdeclarativelist.cpp index 9598d98..346fee5 100644 --- a/src/declarative/qml/qdeclarativelist.cpp +++ b/src/declarative/qml/qdeclarativelist.cpp @@ -88,6 +88,7 @@ void QDeclarativeListReferencePrivate::release() /*! \class QDeclarativeListReference \since 4.7 +\module QtDeclarative \brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties. QDeclarativeListReference allows C++ programs to read from, and assign values to a QML list property in a diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 2aa2059..dc3ecca 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -368,7 +368,7 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, newBinding = new QDeclarativeBinding(value, obj, evalContext); newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext)); - if (newBinding->expression().contains("this")) + if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 61e3002..0dd0edb 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -427,7 +427,7 @@ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const */ int QDeclarativeProperty::propertyType() const { - return d ? d->propertyType() : QVariant::Invalid; + return d ? d->propertyType() : int(QVariant::Invalid); } bool QDeclarativePropertyPrivate::isValueType() const diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index 200cc1c..4c312b5 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -184,7 +184,7 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); newBinding->setTarget(prop); - if (newBinding->expression().contains("this")) + if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 366c64b..2d551f2 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -938,7 +938,6 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarativeEnginePrivate::clear(bindValues); QDeclarativeEnginePrivate::clear(parserStatus); - ep->finalizedParserStatus.clear(); return 0; } diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index bd3234f..ac9c3c0 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -182,12 +182,11 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) { Q_D(QDeclarativeAbstractAnimation); if (!d->componentComplete) { - if (d->running && r == d->running) //don't re-register - return; d->running = r; if (r == false) d->avoidPropertyValueSourceStart = true; - else { + else if (!d->registered) { + d->registered = true; QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this)); engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()")); } @@ -204,6 +203,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) d->running = r; if (d->running) { + bool supressStart = false; if (d->alwaysRunToEnd && d->loopCount != 1 && qtAnimation()->state() == QAbstractAnimation::Running) { //we've restarted before the final loop finished; restore proper loop count @@ -211,6 +211,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) qtAnimation()->setLoopCount(d->loopCount); else qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount); + supressStart = true; //we want the animation to continue, rather than restart } if (!d->connectedTimeLine) { @@ -218,7 +219,8 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) this, SLOT(timelineComplete())); d->connectedTimeLine = true; } - d->commence(); + if (!supressStart) + d->commence(); emit started(); } else { if (d->alwaysRunToEnd) { diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index 84bc0ef..3c41565 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -210,7 +210,7 @@ public: : running(false), paused(false), alwaysRunToEnd(false), connectedTimeLine(false), componentComplete(true), avoidPropertyValueSourceStart(false), disableUserControl(false), - loopCount(1), group(0) {} + registered(false), loopCount(1), group(0) {} bool running:1; bool paused:1; @@ -219,6 +219,7 @@ public: bool componentComplete:1; bool avoidPropertyValueSourceStart:1; bool disableUserControl:1; + bool registered:1; int loopCount; diff --git a/src/declarative/util/qdeclarativeopenmetaobject.cpp b/src/declarative/util/qdeclarativeopenmetaobject.cpp index 0ceda35..8a8d05e 100644 --- a/src/declarative/util/qdeclarativeopenmetaobject.cpp +++ b/src/declarative/util/qdeclarativeopenmetaobject.cpp @@ -289,17 +289,19 @@ void QDeclarativeOpenMetaObject::setValue(const QByteArray &name, const QVariant int id = -1; if (iter == d->type->d->names.end()) { - id = d->type->createProperty(name.constData()) - d->type->d->propertyOffset; + id = createProperty(name.constData(), "") - d->type->d->propertyOffset; } else { id = *iter; } - QVariant &dataVal = d->getData(id); - if (dataVal == val) - return; + if (id >= 0) { + QVariant &dataVal = d->getData(id); + if (dataVal == val) + return; - dataVal = val; - activate(d->object, id + d->type->d->signalOffset, 0); + dataVal = val; + activate(d->object, id + d->type->d->signalOffset, 0); + } } // returns true if this value has been initialized by a call to either value() or setValue() diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index ccd122e..9bcb263 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -281,7 +281,7 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second); QVariant var; bool isScript = v.isScript(); - QDeclarativeBinding::Identifier id; + QDeclarativeBinding::Identifier id = 0; switch(v.type()) { case QDeclarativeParser::Variant::Boolean: var = QVariant(v.asBoolean()); diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp index 1a3e0be..915f027 100644 --- a/src/declarative/util/qdeclarativepropertymap.cpp +++ b/src/declarative/util/qdeclarativepropertymap.cpp @@ -182,7 +182,18 @@ QVariant QDeclarativePropertyMap::value(const QString &key) const void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value) { Q_D(QDeclarativePropertyMap); - d->mo->setValue(key.toUtf8(), value); + //The following strings shouldn't be used as property names + if (key != QLatin1String("keys") + && key != QLatin1String("valueChanged") + && key != QLatin1String("QObject") + && key != QLatin1String("destroyed") + && key != QLatin1String("deleteLater")) { + d->mo->setValue(key.toUtf8(), value); + } else { + qWarning() << "Creating property with name" + << key + << "is not permitted, conflicts with internal symbols."; + } } /*! @@ -258,7 +269,7 @@ QVariant &QDeclarativePropertyMap::operator[](const QString &key) Q_D(QDeclarativePropertyMap); QByteArray utf8key = key.toUtf8(); if (!d->keys.contains(key)) - d->mo->setValue(utf8key, QVariant()); //force creation -- needed below + insert(key, QVariant());//force creation -- needed below return (*(d->mo))[utf8key]; } diff --git a/src/declarative/util/qdeclarativespringanimation.cpp b/src/declarative/util/qdeclarativespringanimation.cpp index ec2b083..1212a1c 100644 --- a/src/declarative/util/qdeclarativespringanimation.cpp +++ b/src/declarative/util/qdeclarativespringanimation.cpp @@ -236,7 +236,7 @@ void QDeclarativeSpringAnimationPrivate::updateMode() /*! \qmlclass SpringAnimation QDeclarativeSpringAnimation \ingroup qml-animation-transition - \inherits Animation + \inherits NumberAnimation \since 4.7 \brief The SpringAnimation element allows a property to track a value in a spring-like motion. diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index cf3696b..5af53e6 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -46,11 +46,9 @@ #include <QDebug> #include <QStringList> -#include <QQueue> +#include <QMap> #include <QApplication> #include <QThread> -#include <QMutex> -#include <QWaitCondition> #include <QXmlQuery> #include <QXmlResultItems> #include <QXmlNodeModelIndex> @@ -58,6 +56,7 @@ #include <QNetworkRequest> #include <QNetworkReply> #include <QTimer> +#include <QMutex> #include <private/qobject_p.h> @@ -147,39 +146,32 @@ struct XmlQueryJob QStringList keyRoleResultsCache; }; -class QDeclarativeXmlQuery : public QThread +class QDeclarativeXmlQuery : public QObject { Q_OBJECT public: QDeclarativeXmlQuery(QObject *parent=0) - : QThread(parent), m_quit(false), m_abortQueryId(-1), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { + : QObject(parent), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult"); - m_currentJob.queryId = -1; + moveToThread(&m_thread); + m_thread.start(QThread::IdlePriority); } ~QDeclarativeXmlQuery() { - m_mutex.lock(); - m_quit = true; - m_condition.wakeOne(); - m_mutex.unlock(); - - wait(); + if(m_thread.isRunning()) { + m_thread.quit(); + m_thread.wait(); + } } void abort(int id) { - QMutexLocker locker(&m_mutex); - QQueue<XmlQueryJob>::iterator it; - for (it = m_jobs.begin(); it != m_jobs.end(); ++it) { - if ((*it).queryId == id) { - m_jobs.erase(it); - return; - } + QMutexLocker ml(&m_mutex); + if (id != -1) { + m_jobs.remove(id); } - m_abortQueryId = id; } - int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *> *roleObjects, QStringList keyRoleResultsCache) { - QMutexLocker locker(&m_mutex); + int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) { XmlQueryJob job; job.queryId = m_queryIds; @@ -198,69 +190,69 @@ public: if (roleObjects->at(i)->isKey()) job.keyRoleQueries << job.roleQueries.last(); } - m_jobs.enqueue(job); - m_queryIds++; - if (!isRunning()) - start(QThread::IdlePriority); - else - m_condition.wakeOne(); + { + QMutexLocker ml(&m_mutex); + m_jobs.insert(m_queryIds, job); + m_queryIds++; + if (m_queryIds <= 0) + m_queryIds = 1; + } + + QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId)); return job.queryId; } +private slots: + void processQuery(int queryId) { + XmlQueryJob job; + + { + QMutexLocker ml(&m_mutex); + if (!m_jobs.contains(queryId)) + return; + job = m_jobs.value(queryId); + } + + QDeclarativeXmlQueryResult r; + doQueryJob(&job); + doSubQueryJob(&job); + r.queryId = job.queryId; + r.size = m_size; + r.data = m_modelData; + r.inserted = m_insertedItemRanges; + r.removed = m_removedItemRanges; + r.keyRoleResultsCache = job.keyRoleResultsCache; + + { + QMutexLocker ml(&m_mutex); + if (m_jobs.contains(queryId)) { + emit queryCompleted(r); + m_jobs.remove(queryId); + } + } + } + Q_SIGNALS: void queryCompleted(const QDeclarativeXmlQueryResult &); void error(void*, const QString&); protected: - void run() { - m_mutex.lock(); - - while (!m_quit) { - if (!m_jobs.isEmpty()) - m_currentJob = m_jobs.dequeue(); - m_mutex.unlock(); - - QDeclarativeXmlQueryResult r; - if (m_currentJob.queryId != -1) { - doQueryJob(); - doSubQueryJob(); - r.queryId = m_currentJob.queryId; - r.size = m_size; - r.data = m_modelData; - r.inserted = m_insertedItemRanges; - r.removed = m_removedItemRanges; - r.keyRoleResultsCache = m_currentJob.keyRoleResultsCache; - } - m_mutex.lock(); - if (m_currentJob.queryId != -1 && m_abortQueryId != m_currentJob.queryId) - emit queryCompleted(r); - if (m_jobs.isEmpty() && !m_quit) - m_condition.wait(&m_mutex); - m_currentJob.queryId = -1; - m_abortQueryId = -1; - } - - m_mutex.unlock(); - } private: - void doQueryJob(); - void doSubQueryJob(); - void getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const; + void doQueryJob(XmlQueryJob* job); + void doSubQueryJob(XmlQueryJob* job); + void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const; void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const; private: QMutex m_mutex; - QWaitCondition m_condition; - QQueue<XmlQueryJob> m_jobs; - XmlQueryJob m_currentJob; - bool m_quit; - int m_abortQueryId; + QThread m_thread; + QMap<int, XmlQueryJob> m_jobs; + int m_queryIds; QString m_prefix; int m_size; - int m_queryIds; QList<QList<QVariant> > m_modelData; QList<QDeclarativeXmlListRange> m_insertedItemRanges; QList<QDeclarativeXmlListRange> m_removedItemRanges; @@ -268,16 +260,16 @@ private: Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery) -void QDeclarativeXmlQuery::doQueryJob() +void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob) { - Q_ASSERT(m_currentJob.queryId != -1); + Q_ASSERT(currentJob->queryId != -1); QString r; QXmlQuery query; - QBuffer buffer(&m_currentJob.data); + QBuffer buffer(¤tJob->data); buffer.open(QIODevice::ReadOnly); query.bindVariable(QLatin1String("src"), &buffer); - query.setQuery(m_currentJob.namespaces + m_currentJob.query); + query.setQuery(currentJob->namespaces + currentJob->query); query.evaluateTo(&r); //always need a single root element @@ -285,9 +277,9 @@ void QDeclarativeXmlQuery::doQueryJob() QBuffer b(&xml); b.open(QIODevice::ReadOnly); - QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_currentJob.namespaces; + QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + currentJob->namespaces; QString prefix = QLatin1String("doc($inputDocument)/dummy:items") + - m_currentJob.query.mid(m_currentJob.query.lastIndexOf(QLatin1Char('/'))); + currentJob->query.mid(currentJob->query.lastIndexOf(QLatin1Char('/'))); //figure out how many items we are dealing with int count = -1; @@ -302,18 +294,16 @@ void QDeclarativeXmlQuery::doQueryJob() count = item.toAtomicValue().toInt(); } - m_currentJob.data = xml; + currentJob->data = xml; m_prefix = namespaces + prefix + QLatin1Char('/'); m_size = 0; if (count > 0) m_size = count; } -void QDeclarativeXmlQuery::getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const +void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const { - Q_ASSERT(m_currentJob.queryId != -1); - - const QStringList &keysQueries = m_currentJob.keyRoleQueries; + const QStringList &keysQueries = currentJob.keyRoleQueries; QString keysQuery; if (keysQueries.count() == 1) keysQuery = m_prefix + keysQueries[0]; @@ -341,34 +331,34 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> * ranges->append(qMakePair(index, 1)); } -void QDeclarativeXmlQuery::doSubQueryJob() +void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) { - Q_ASSERT(m_currentJob.queryId != -1); + Q_ASSERT(currentJob->queryId != -1); m_modelData.clear(); - QBuffer b(&m_currentJob.data); + QBuffer b(¤tJob->data); b.open(QIODevice::ReadOnly); QXmlQuery subquery; subquery.bindVariable(QLatin1String("inputDocument"), &b); QStringList keyRoleResults; - getValuesOfKeyRoles(&keyRoleResults, &subquery); + getValuesOfKeyRoles(*currentJob, &keyRoleResults, &subquery); // See if any values of key roles have been inserted or removed. m_insertedItemRanges.clear(); m_removedItemRanges.clear(); - if (m_currentJob.keyRoleResultsCache.isEmpty()) { + if (currentJob->keyRoleResultsCache.isEmpty()) { m_insertedItemRanges << qMakePair(0, m_size); } else { - if (keyRoleResults != m_currentJob.keyRoleResultsCache) { + if (keyRoleResults != currentJob->keyRoleResultsCache) { QStringList temp; - for (int i=0; i<m_currentJob.keyRoleResultsCache.count(); i++) { - if (!keyRoleResults.contains(m_currentJob.keyRoleResultsCache[i])) + for (int i=0; i<currentJob->keyRoleResultsCache.count(); i++) { + if (!keyRoleResults.contains(currentJob->keyRoleResultsCache[i])) addIndexToRangeList(&m_removedItemRanges, i); else - temp << m_currentJob.keyRoleResultsCache[i]; + temp << currentJob->keyRoleResultsCache[i]; } for (int i=0; i<keyRoleResults.count(); i++) { @@ -379,11 +369,11 @@ void QDeclarativeXmlQuery::doSubQueryJob() } } } - m_currentJob.keyRoleResultsCache = keyRoleResults; + currentJob->keyRoleResultsCache = keyRoleResults; // Get the new values for each role. //### we might be able to condense even further (query for everything in one go) - const QStringList &queries = m_currentJob.roleQueries; + const QStringList &queries = currentJob->roleQueries; for (int i = 0; i < queries.size(); ++i) { QList<QVariant> resultList; if (!queries[i].isEmpty()) { @@ -397,7 +387,7 @@ void QDeclarativeXmlQuery::doSubQueryJob() item = resultItems.next(); } } else { - emit error(m_currentJob.roleQueryErrorId.at(i), queries[i]); + emit error(currentJob->roleQueryErrorId.at(i), queries[i]); } } //### should warn here if things have gone wrong. diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index f89706c..00dccbe 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -28,7 +28,10 @@ HEADERS += \ image/qpixmapdata_p.h \ image/qpixmapdatafactory_p.h \ image/qpixmapfilter_p.h \ - image/qimagepixmapcleanuphooks_p.h + image/qimagepixmapcleanuphooks_p.h \ + image/qvolatileimage_p.h \ + image/qvolatileimagedata_p.h \ + image/qnativeimagehandleprovider_p.h SOURCES += \ image/qbitmap.cpp \ @@ -51,7 +54,8 @@ SOURCES += \ image/qmovie.cpp \ image/qpixmap_raster.cpp \ image/qnativeimage.cpp \ - image/qimagepixmapcleanuphooks.cpp + image/qimagepixmapcleanuphooks.cpp \ + image/qvolatileimage.cpp win32 { SOURCES += image/qpixmap_win.cpp @@ -72,6 +76,13 @@ else:symbian { SOURCES += image/qpixmap_s60.cpp } +!symbian|contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2) { + SOURCES += image/qvolatileimagedata.cpp +} +else { + SOURCES += image/qvolatileimagedata_symbian.cpp +} + # Built-in image format support HEADERS += \ image/qbmphandler_p.h \ diff --git a/src/gui/image/qnativeimagehandleprovider_p.h b/src/gui/image/qnativeimagehandleprovider_p.h new file mode 100644 index 0000000..4e6ed38 --- /dev/null +++ b/src/gui/image/qnativeimagehandleprovider_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNATIVEIMAGEHANDLEPROVIDER_P_H +#define QNATIVEIMAGEHANDLEPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qstring.h> + +QT_BEGIN_NAMESPACE + +class QNativeImageHandleProvider +{ +public: + virtual void get(void **handle, QString *type) = 0; + virtual void release(void *handle, const QString &type) = 0; +}; + +QT_END_NAMESPACE + +#endif // QNATIVEIMAGEHANDLEPROVIDER_P_H diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 0aefafb..1a83318 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1997,7 +1997,7 @@ void QPixmap::detach() } if (data->is_cached && data->ref == 1) - QImagePixmapCleanupHooks::executePixmapDataModificationHooks(pd); + QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data()); #if defined(Q_WS_MAC) QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 368600f..5e0ffa8 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -380,6 +380,9 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace) { QImage::Format format; + if (flags & Qt::NoFormatConversion) + format = sourceImage.format(); + else #ifdef Q_WS_QWS if (pixelType() == BitmapType) { format = QImage::Format_Mono; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 7699344..0d0d417 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -71,7 +71,9 @@ public: #if defined(Q_OS_SYMBIAN) enum NativeType { FbsBitmap, - SgImage + SgImage, + VolatileImage, + NativeImageHandleProvider }; #endif enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass, diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp new file mode 100644 index 0000000..098e9a1 --- /dev/null +++ b/src/gui/image/qvolatileimage.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimage_p.h" +#include "qvolatileimagedata_p.h" +#include <QtGui/private/qpaintengine_raster_p.h> +#include <QtGui/private/qpixmapdata_p.h> + +QT_BEGIN_NAMESPACE + +class QVolatileImagePaintEnginePrivate : public QRasterPaintEnginePrivate +{ +public: + QVolatileImagePaintEnginePrivate() { } + QVolatileImage *img; +}; + +class QVolatileImagePaintEngine : public QRasterPaintEngine +{ + Q_DECLARE_PRIVATE(QVolatileImagePaintEngine) + +public: + QVolatileImagePaintEngine(QPaintDevice *device, QVolatileImage *img); + bool begin(QPaintDevice *device); + bool end(); + void drawPixmap(const QPointF &p, const QPixmap &pm); + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); +}; + +QVolatileImage::QVolatileImage() + : d(new QVolatileImageData) +{ +} + +QVolatileImage::QVolatileImage(int w, int h, QImage::Format format) + : d(new QVolatileImageData(w, h, format)) +{ +} + +QVolatileImage::QVolatileImage(const QImage &sourceImage) + : d(new QVolatileImageData(sourceImage)) +{ +} + +QVolatileImage::QVolatileImage(void *nativeImage, void *nativeMask) + : d(new QVolatileImageData(nativeImage, nativeMask)) +{ +} + +// Need non-inline, non-autogenerated copy ctor, dtor, op= to keep the +// fwd declared QSharedData working. + +QVolatileImage::QVolatileImage(const QVolatileImage &other) + : d(other.d) +{ +} + +QVolatileImage::~QVolatileImage() +{ +} + +QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs) +{ + d = rhs.d; + return *this; +} + +bool QVolatileImage::isNull() const +{ + return d->image.isNull(); +} + +QImage::Format QVolatileImage::format() const +{ + return d->image.format(); +} + +int QVolatileImage::width() const +{ + return d->image.width(); +} + +int QVolatileImage::height() const +{ + return d->image.height(); +} + +int QVolatileImage::bytesPerLine() const +{ + return d->image.bytesPerLine(); +} + +int QVolatileImage::byteCount() const +{ + return d->image.byteCount(); +} + +int QVolatileImage::depth() const +{ + return d->image.depth(); +} + +bool QVolatileImage::hasAlphaChannel() const +{ + return d->image.hasAlphaChannel(); +} + +void QVolatileImage::beginDataAccess() const +{ + d->beginDataAccess(); +} + +void QVolatileImage::endDataAccess(bool readOnly) const +{ + d->endDataAccess(readOnly); +} + +/*! + Access to pixel data via bits() or constBits() should be guarded by + begin/endDataAccess(). + */ +uchar *QVolatileImage::bits() +{ + return d->image.bits(); +} + +const uchar *QVolatileImage::constBits() const +{ + return d->image.constBits(); +} + +bool QVolatileImage::ensureFormat(QImage::Format format) +{ + return d->ensureFormat(format); +} + +/*! + This will always perform a copy of the pixel data. + */ +QImage QVolatileImage::toImage() const +{ + d->beginDataAccess(); + QImage newImage = d->image.copy(); // no sharing allowed + d->endDataAccess(true); + return newImage; +} + +/*! + Returns a reference to the image that is potentially using some native + buffer internally. Access to the image's pixel data should be guarded by + begin/endDataAccess(). Use it when there is a need for QImage APIs not provided + by this class. The returned QImage must never be shared or assigned to. + */ +QImage &QVolatileImage::imageRef() // non-const, in order to cause a detach +{ + d->ensureImage(); + return d->image; +} + +void *QVolatileImage::duplicateNativeImage() const +{ + return d->duplicateNativeImage(); +} + +void QVolatileImage::setAlphaChannel(const QPixmap &alphaChannel) +{ + ensureFormat(QImage::Format_ARGB32_Premultiplied); + beginDataAccess(); + imageRef().setAlphaChannel(alphaChannel.toImage()); + endDataAccess(); + d->ensureImage(); +} + +void QVolatileImage::fill(uint pixelValue) +{ + beginDataAccess(); + imageRef().fill(pixelValue); + endDataAccess(); + d->ensureImage(); +} + +void QVolatileImage::copyFrom(QVolatileImage *source, const QRect &rect) +{ + if (source->isNull()) { + return; + } + QRect r = rect; + if (rect.isNull()) { + r = QRect(0, 0, source->width(), source->height()); + } + source->beginDataAccess(); + QImage &srcImgRef(source->imageRef()); + int srcbpl = srcImgRef.bytesPerLine(); + int srcbpp = srcImgRef.depth() / 8; + const uchar *sptr = srcImgRef.constBits() + r.y() * srcbpl; + beginDataAccess(); + QImage &dstImgRef(imageRef()); + int dstbpl = dstImgRef.bytesPerLine(); + uchar *dptr = dstImgRef.bits(); + for (int y = 0; y < r.height(); ++y) { + qMemCopy(dptr, sptr + r.x() * srcbpp, r.width() * srcbpp); + sptr += srcbpl; + dptr += dstbpl; + } + endDataAccess(); + source->endDataAccess(true); +} + +/*! + To be called from the PixmapData's paintEngine(). + */ +QPaintEngine *QVolatileImage::paintEngine() +{ + if (!d->pengine) { + d->pengine = new QVolatileImagePaintEngine(&imageRef(), this); + } + return d->pengine; +} + +QVolatileImagePaintEngine::QVolatileImagePaintEngine(QPaintDevice *device, + QVolatileImage *img) + : QRasterPaintEngine(*(new QVolatileImagePaintEnginePrivate), device) +{ + Q_D(QVolatileImagePaintEngine); + d->img = img; +} + +bool QVolatileImagePaintEngine::begin(QPaintDevice *device) +{ + Q_D(QVolatileImagePaintEngine); + d->img->beginDataAccess(); + return QRasterPaintEngine::begin(device); +} + +bool QVolatileImagePaintEngine::end() +{ + Q_D(QVolatileImagePaintEngine); + bool ret = QRasterPaintEngine::end(); + d->img->endDataAccess(); + return ret; +} + +// For non-RasterClass pixmaps drawPixmap() would call toImage() which is slow in +// our case. Therefore drawPixmap() is rerouted to drawImage(). + +void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) +{ +#ifdef Q_OS_SYMBIAN + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(p, img->imageRef()); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(p, pm); + } +#else + QRasterPaintEngine::drawPixmap(p, pm); +#endif +} + +void QVolatileImagePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ +#ifdef Q_OS_SYMBIAN + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(r, img->imageRef(), sr); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(r, pm, sr); + } +#else + QRasterPaintEngine::drawPixmap(r, pm, sr); +#endif +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h new file mode 100644 index 0000000..fc5d6b1 --- /dev/null +++ b/src/gui/image/qvolatileimage_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVOLATILEIMAGE_P_H +#define QVOLATILEIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qimage.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QVolatileImageData; + +class Q_GUI_EXPORT QVolatileImage +{ +public: + QVolatileImage(); + QVolatileImage(int w, int h, QImage::Format format); + explicit QVolatileImage(const QImage &sourceImage); + explicit QVolatileImage(void *nativeImage, void *nativeMask = 0); + QVolatileImage(const QVolatileImage &other); + ~QVolatileImage(); + QVolatileImage &operator=(const QVolatileImage &rhs); + + bool isNull() const; + QImage::Format format() const; + int width() const; + int height() const; + int bytesPerLine() const; + int byteCount() const; + int depth() const; + bool hasAlphaChannel() const; + void beginDataAccess() const; + void endDataAccess(bool readOnly = false) const; + uchar *bits(); + const uchar *constBits() const; + bool ensureFormat(QImage::Format format); + QImage toImage() const; + QImage &imageRef(); + QPaintEngine *paintEngine(); + void setAlphaChannel(const QPixmap &alphaChannel); + void fill(uint pixelValue); + void *duplicateNativeImage() const; + void copyFrom(QVolatileImage *source, const QRect &rect); + +private: + QSharedDataPointer<QVolatileImageData> d; +}; + +QT_END_NAMESPACE + +#endif // QVOLATILEIMAGE_P_H diff --git a/src/gui/image/qvolatileimagedata.cpp b/src/gui/image/qvolatileimagedata.cpp new file mode 100644 index 0000000..51b5995 --- /dev/null +++ b/src/gui/image/qvolatileimagedata.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimagedata_p.h" +#include <QtGui/qpaintengine.h> + +QT_BEGIN_NAMESPACE + +QVolatileImageData::QVolatileImageData() + : pengine(0) +{ +} + +QVolatileImageData::QVolatileImageData(int w, int h, QImage::Format format) + : pengine(0) +{ + image = QImage(w, h, format); +} + +QVolatileImageData::QVolatileImageData(const QImage &sourceImage) + : pengine(0) +{ + image = sourceImage; +} + +QVolatileImageData::QVolatileImageData(void *, void *) + : pengine(0) +{ + // Not supported. +} + +QVolatileImageData::QVolatileImageData(const QVolatileImageData &other) +{ + image = other.image; + // The detach is not mandatory here but we do it nonetheless in order to + // keep the behavior consistent with other platforms. + image.detach(); + pengine = 0; +} + +QVolatileImageData::~QVolatileImageData() +{ + delete pengine; +} + +void QVolatileImageData::beginDataAccess() const +{ + // nothing to do here +} + +void QVolatileImageData::endDataAccess(bool readOnly) const +{ + Q_UNUSED(readOnly); + // nothing to do here +} + +bool QVolatileImageData::ensureFormat(QImage::Format format) +{ + if (image.format() != format) { + image = image.convertToFormat(format); + } + return true; +} + +void *QVolatileImageData::duplicateNativeImage() const +{ + return 0; +} + +void QVolatileImageData::ensureImage() +{ + // nothing to do here +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimagedata_p.h b/src/gui/image/qvolatileimagedata_p.h new file mode 100644 index 0000000..dab1685 --- /dev/null +++ b/src/gui/image/qvolatileimagedata_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVOLATILEIMAGEDATA_P_H +#define QVOLATILEIMAGEDATA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qimage.h> +#include <QtCore/qshareddata.h> + +#ifdef Q_OS_SYMBIAN +class CFbsBitmap; +#endif + +QT_BEGIN_NAMESPACE + +class QVolatileImageData : public QSharedData +{ +public: + QVolatileImageData(); + QVolatileImageData(int w, int h, QImage::Format format); + QVolatileImageData(const QImage &sourceImage); + QVolatileImageData(void *nativeImage, void *nativeMask); + QVolatileImageData(const QVolatileImageData &other); + ~QVolatileImageData(); + + void beginDataAccess() const; + void endDataAccess(bool readOnly = false) const; + bool ensureFormat(QImage::Format format); + void *duplicateNativeImage() const; + void ensureImage(); + +#ifdef Q_OS_SYMBIAN + void updateImage(); + void initWithBitmap(CFbsBitmap *source); + void applyMask(CFbsBitmap *mask); + void ensureBitmap(); + void release(); + QVolatileImageData *next; + QVolatileImageData *prev; + CFbsBitmap *bitmap; +#endif + QImage image; + QPaintEngine *pengine; +}; + +QT_END_NAMESPACE + +#endif // QVOLATILEIMAGEDATA_P_H diff --git a/src/gui/image/qvolatileimagedata_symbian.cpp b/src/gui/image/qvolatileimagedata_symbian.cpp new file mode 100644 index 0000000..474d0ef --- /dev/null +++ b/src/gui/image/qvolatileimagedata_symbian.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** 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 QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvolatileimagedata_p.h" +#include <fbs.h> +#include <QtGui/private/qt_s60_p.h> +#include <QtGui/qpaintengine.h> +#include <QtGui/private/qimage_p.h> + +QT_BEGIN_NAMESPACE + +static CFbsBitmap *rasterizeBitmap(CFbsBitmap *bitmap, TDisplayMode newMode) +{ + if (!bitmap) { + return 0; + } + QScopedPointer<CFbsBitmap> newBitmap(new CFbsBitmap); + if (newBitmap->Create(bitmap->SizeInPixels(), newMode) != KErrNone) { + qWarning("QVolatileImage: Failed to create new bitmap"); + return 0; + } + CFbsBitmapDevice *bitmapDevice = 0; + CFbsBitGc *bitmapGc = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(newBitmap.data())); + QScopedPointer<CFbsBitmapDevice> bitmapDevicePtr(bitmapDevice); + QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); + bitmapGc->Activate(bitmapDevice); + bitmapGc->BitBlt(TPoint(), bitmap); + delete bitmapGc; + return newBitmap.take(); +} + +static inline TDisplayMode format2TDisplayMode(QImage::Format format) +{ + TDisplayMode mode; + switch (format) { + case QImage::Format_MonoLSB: + mode = EGray2; + break; + case QImage::Format_Indexed8: + mode = EColor256; + break; + case QImage::Format_RGB444: + mode = EColor4K; + break; + case QImage::Format_RGB16: + mode = EColor64K; + break; + case QImage::Format_RGB888: + mode = EColor16M; + break; + case QImage::Format_RGB32: + mode = EColor16MU; + break; + case QImage::Format_ARGB32: + mode = EColor16MA; + break; + case QImage::Format_ARGB32_Premultiplied: + mode = Q_SYMBIAN_ECOLOR16MAP; + break; + default: + mode = ENone; + break; + } + return mode; +} + +static CFbsBitmap *imageToBitmap(const QImage &image) +{ + if (image.isNull()) { + return 0; + } + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Create(TSize(image.width(), image.height()), + format2TDisplayMode(image.format())) == KErrNone) { + bitmap->BeginDataAccess(); + uchar *dptr = reinterpret_cast<uchar *>(bitmap->DataAddress()); + int bmpLineLen = bitmap->DataStride(); + int imgLineLen = image.bytesPerLine(); + if (bmpLineLen == imgLineLen) { + qMemCopy(dptr, image.constBits(), image.byteCount()); + } else { + int len = qMin(bmpLineLen, imgLineLen); + const uchar *sptr = image.constBits(); + for (int y = 0; y < image.height(); ++y) { + qMemCopy(dptr, sptr, len); + dptr += bmpLineLen; + sptr += imgLineLen; + } + } + bitmap->EndDataAccess(); + } else { + qWarning("QVolatileImage: Failed to create source bitmap"); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static CFbsBitmap *copyData(const QVolatileImageData &source) +{ + source.beginDataAccess(); + CFbsBitmap *bmp = imageToBitmap(source.image); + source.endDataAccess(); + return bmp; +} + +static CFbsBitmap *convertData(const QVolatileImageData &source, QImage::Format newFormat) +{ + source.beginDataAccess(); + QImage img = source.image.convertToFormat(newFormat); + CFbsBitmap *bmp = imageToBitmap(img); + source.endDataAccess(); + return bmp; +} + +static CFbsBitmap *duplicateBitmap(const CFbsBitmap &sourceBitmap) +{ + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Duplicate(sourceBitmap.Handle()) != KErrNone) { + qWarning("QVolatileImage: Failed to duplicate source bitmap"); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static CFbsBitmap *createBitmap(int w, int h, QImage::Format format) +{ + CFbsBitmap *bitmap = new CFbsBitmap; + if (bitmap->Create(TSize(w, h), format2TDisplayMode(format)) != KErrNone) { + qWarning("QVolatileImage: Failed to create source bitmap %d,%d (%d)", w, h, format); + delete bitmap; + bitmap = 0; + } + return bitmap; +} + +static inline bool bitmapNeedsCopy(CFbsBitmap *bitmap) +{ + bool needsCopy = bitmap->IsCompressedInRAM(); +#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE + needsCopy |= (bitmap->ExtendedBitmapType() != KNullUid); +#endif + return needsCopy; +} + +static bool cleanup_function_registered = false; +static QVolatileImageData *firstImageData = 0; + +static void cleanup() +{ + if (RFbsSession::GetSession()) { + QVolatileImageData *imageData = firstImageData; + while (imageData) { + imageData->release(); + imageData = imageData->next; + } + } +} + +static void ensureCleanup() +{ + // Destroy all underlying bitmaps in a post routine to prevent panics. + // This is a must because CFbsBitmap destructor needs the fbs session, + // that was used to create the bitmap, to be open still. + if (!cleanup_function_registered) { + qAddPostRoutine(cleanup); + cleanup_function_registered = true; + } +} + +static void registerImageData(QVolatileImageData *imageData) +{ + ensureCleanup(); + imageData->next = firstImageData; + if (firstImageData) { + firstImageData->prev = imageData; + } + firstImageData = imageData; +} + +static void unregisterImageData(QVolatileImageData *imageData) +{ + if (imageData->prev) { + imageData->prev->next = imageData->next; + } else { + firstImageData = imageData->next; + } + if (imageData->next) { + imageData->next->prev = imageData->prev; + } +} + +QVolatileImageData::QVolatileImageData() + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); +} + +QVolatileImageData::QVolatileImageData(int w, int h, QImage::Format format) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + bitmap = createBitmap(w, h, format); + updateImage(); +} + +QVolatileImageData::QVolatileImageData(const QImage &sourceImage) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + image = sourceImage; + // The following is not mandatory, but we do it here to have a bitmap + // created always in order to reduce local heap usage. + ensureBitmap(); +} + +QVolatileImageData::QVolatileImageData(void *nativeImage, void *nativeMask) + : next(0), prev(0), bitmap(0), pengine(0) +{ + registerImageData(this); + if (nativeImage) { + CFbsBitmap *source = static_cast<CFbsBitmap *>(nativeImage); + CFbsBitmap *mask = static_cast<CFbsBitmap *>(nativeMask); + initWithBitmap(source); + if (mask) { + applyMask(mask); + } + } +} + +QVolatileImageData::QVolatileImageData(const QVolatileImageData &other) +{ + bitmap = 0; + pengine = 0; + next = prev = 0; + registerImageData(this); + if (!other.image.isNull()) { + bitmap = copyData(other); + updateImage(); + } +} + +QVolatileImageData::~QVolatileImageData() +{ + release(); + unregisterImageData(this); +} + +void QVolatileImageData::release() +{ + delete bitmap; + bitmap = 0; + delete pengine; + pengine = 0; +} + +void QVolatileImageData::beginDataAccess() const +{ + if (bitmap) { + bitmap->BeginDataAccess(); + } +} + +void QVolatileImageData::endDataAccess(bool readOnly) const +{ + if (bitmap) { + bitmap->EndDataAccess(readOnly); + } +} + +bool QVolatileImageData::ensureFormat(QImage::Format format) +{ + if (image.isNull()) { + return false; + } + if (image.format() != format) { + CFbsBitmap *newBitmap = convertData(*this, format); + if (newBitmap && newBitmap != bitmap) { + delete bitmap; + bitmap = newBitmap; + updateImage(); + } else { + return false; + } + } + return true; +} + +void *QVolatileImageData::duplicateNativeImage() const +{ + const_cast<QVolatileImageData *>(this)->ensureBitmap(); + if (bitmap) { + if (bitmap->DisplayMode() == EColor16M) { + // slow path: needs rgb swapping + beginDataAccess(); + QImage tmp = image.rgbSwapped(); + endDataAccess(true); + return imageToBitmap(tmp); + } else if (bitmap->DisplayMode() == EGray2) { + // slow path: needs inverting pixels + beginDataAccess(); + QImage tmp = image.copy(); + endDataAccess(true); + tmp.invertPixels(); + return imageToBitmap(tmp); + } else { + // fast path: just duplicate the bitmap + return duplicateBitmap(*bitmap); + } + } + return 0; +} + +void QVolatileImageData::updateImage() +{ + if (bitmap) { + TSize size = bitmap->SizeInPixels(); + beginDataAccess(); + // Use existing buffer, no copy. The data address never changes so it + // is enough to do this whenever we have a new CFbsBitmap. N.B. never + // use const uchar* here, that would create a read-only image data which + // would make a copy in detach() even when refcount is 1. + image = QImage(reinterpret_cast<uchar *>(bitmap->DataAddress()), + size.iWidth, size.iHeight, bitmap->DataStride(), + qt_TDisplayMode2Format(bitmap->DisplayMode())); + endDataAccess(true); + } else { + image = QImage(); + } +} + +void QVolatileImageData::initWithBitmap(CFbsBitmap *source) +{ + bool needsCopy = bitmapNeedsCopy(source); + if (source->DisplayMode() == EColor16M) { + // EColor16M is BGR + CFbsBitmap *unswappedBmp = source; + if (needsCopy) { + unswappedBmp = rasterizeBitmap(source, source->DisplayMode()); + } + unswappedBmp->BeginDataAccess(); + TSize sourceSize = unswappedBmp->SizeInPixels(); + QImage img((uchar *) unswappedBmp->DataAddress(), + sourceSize.iWidth, sourceSize.iHeight, unswappedBmp->DataStride(), + qt_TDisplayMode2Format(unswappedBmp->DisplayMode())); + img = img.rgbSwapped(); + unswappedBmp->EndDataAccess(true); + bitmap = imageToBitmap(img); + if (needsCopy) { + delete unswappedBmp; + } + } else if (needsCopy) { + // Rasterize extended and compressed bitmaps. + bitmap = rasterizeBitmap(source, EColor16MAP); + } else { + // Efficient path: no pixel data copying. Just duplicate. This of course + // means the original bitmap's data may get modified, but that's fine + // and is in accordance with the QPixmap::fromSymbianCFbsBitmap() docs. + bitmap = duplicateBitmap(*source); + } + updateImage(); + if (bitmap && bitmap->DisplayMode() == EGray2) { + // Symbian thinks set pixels are white/transparent, Qt thinks they are + // foreground/solid. Invert mono bitmaps so that masks work correctly. + beginDataAccess(); + image.invertPixels(); + endDataAccess(); + } +} + +void QVolatileImageData::applyMask(CFbsBitmap *mask) +{ + ensureFormat(QImage::Format_ARGB32_Premultiplied); + bool destroyMask = false; + if (bitmapNeedsCopy(mask)) { + mask = rasterizeBitmap(mask, EColor16MU); + if (!mask) { + return; + } + destroyMask = true; + } + mask->BeginDataAccess(); + TSize maskSize = mask->SizeInPixels(); + QImage maskImg((const uchar *) mask->DataAddress(), maskSize.iWidth, maskSize.iHeight, + mask->DataStride(), qt_TDisplayMode2Format(mask->DisplayMode())); + if (mask->DisplayMode() == EGray2) { + maskImg = maskImg.copy(); + maskImg.invertPixels(); + } + beginDataAccess(); + image.setAlphaChannel(maskImg); + endDataAccess(); + mask->EndDataAccess(true); + ensureImage(); + if (destroyMask) { + delete mask; + } +} + +void QVolatileImageData::ensureImage() +{ + if (bitmap && !image.isNull()) { + QImageData *imaged = image.data_ptr(); + if (imaged->ref != 1 || imaged->ro_data) { + // This is bad, the imagedata got shared somehow. Detach, in order to + // have the next check fail and thus have 'image' recreated. + beginDataAccess(); + image.detach(); + endDataAccess(true); + } + } + if (bitmap && image.constBits() != reinterpret_cast<const uchar *>(bitmap->DataAddress())) { + // Should not ever get here. If we do it means that either 'image' has + // been replaced with a copy (e.g. because some QImage API assigned a + // new, regular QImage to *this) or the bitmap's data address changed + // unexpectedly. + qWarning("QVolatileImageData: Ptr mismatch"); + // Recover by recreating the image so that it uses the bitmap as its buffer. + updateImage(); + } +} + +void QVolatileImageData::ensureBitmap() +{ + if (!bitmap && !image.isNull()) { + bitmap = imageToBitmap(image); + updateImage(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index a02b3ff..76cd813 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -882,7 +882,7 @@ static bool read_xpm_body( QByteArray buf(200, 0); int i; - if (cpp > 15) + if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 8c8ffd4..de3577f 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -93,6 +93,9 @@ public: TCoeInputCapabilities inputCapabilities(); + void resetSplitViewWidget(bool keepInputWidget = false); + void ensureFocusWidgetVisible(QWidget *widget); + protected: void timerEvent(QTimerEvent *timerEvent); @@ -104,9 +107,11 @@ private: void queueInputCapabilitiesChanged(); bool needsInputPanel(); void commitTemporaryPreeditString(); + bool isWidgetVisible(QWidget *widget, int offset = 0); private Q_SLOTS: void ensureInputCapabilitiesChanged(); + void translateInputWidget(); // From MCoeFepAwareTextEditor public: @@ -155,9 +160,15 @@ private: QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; + int m_splitViewResizeBy; + Qt::WindowStates m_splitViewPreviousWindowStates; + QRectF m_transformation; + friend class tst_QInputContext; }; +Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable); + QT_END_NAMESPACE #endif // QT_NO_IM diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 1bef64d..cd4e2fd 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -48,6 +48,8 @@ #include <qgraphicsscene.h> #include <qgraphicswidget.h> #include <qsymbianevent.h> +#include <qlayout.h> +#include <qdesktopwidget.h> #include <private/qcore_symbian_p.h> #include <fepitfr.h> @@ -67,8 +69,16 @@ // that support text selection. #define QT_EAknEditorFlagSelectionVisible 0x100000 +// EAknEditorFlagEnablePartialScreen is only valid from Sym^3 onwards. +#define QT_EAknEditorFlagEnablePartialScreen 0x200000 + QT_BEGIN_NAMESPACE +Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable) +{ + S60->partial_keyboard = enable; +} + QCoeFepInputContext::QCoeFepInputContext(QObject *parent) : QInputContext(parent), m_fepState(q_check_ptr(new CAknEdwinState)), // CBase derived object needs check on new @@ -80,13 +90,19 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_inlinePosition(0), m_formatRetriever(0), m_pointerHandler(0), - m_hasTempPreeditString(false) + m_hasTempPreeditString(false), + m_splitViewResizeBy(0), + m_splitViewPreviousWindowStates(Qt::WindowNoState) { m_fepState->SetObjectProvider(this); - if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) - m_fepState->SetFlags(EAknEditorFlagDefault | QT_EAknEditorFlagSelectionVisible); - else - m_fepState->SetFlags(EAknEditorFlagDefault); + int defaultFlags = EAknEditorFlagDefault; + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) { + if (S60->partial_keyboard) { + defaultFlags |= QT_EAknEditorFlagEnablePartialScreen; + } + defaultFlags |= QT_EAknEditorFlagSelectionVisible; + } + m_fepState->SetFlags(defaultFlags); m_fepState->SetDefaultInputMode( EAknEditorTextInputMode ); m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetDefaultCase( EAknEditorTextCase ); @@ -210,6 +226,21 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) return false; switch (event->type()) { + case QEvent::MouseButtonPress: + // Alphanumeric keypad doesn't like it when we click and text is still getting displayed + // It ignores the mouse event, so we need to commit and send a selection event (which will get triggered + // after the commit) + if (!m_preeditString.isEmpty()) { + commitCurrentString(false); + + int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); + + QList<QInputMethodEvent::Attribute> selectAttributes; + selectAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos, 0, QVariant()); + QInputMethodEvent selectEvent(QLatin1String(""), selectAttributes); + sendEvent(selectEvent); + } + break; case QEvent::KeyPress: commitTemporaryPreeditString(); // fall through intended @@ -299,6 +330,26 @@ bool QCoeFepInputContext::symbianFilterEvent(QWidget *keyWidget, const QSymbianE // This should also happen for commands. reset(); + // We need to translate the window content when window becomes available. Changing the window while it is + // not yet ready with OpenVg graphicssystem results in operations silently failing. + + if (event->windowServerEvent() && event->windowServerEvent()->Type() == EEventWindowVisibilityChanged) { + if (S60->splitViewLastWidget) { + QGraphicsView *gv = qobject_cast<QGraphicsView*>(S60->splitViewLastWidget); + const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); + TUint visibleFlags = event->windowServerEvent()->VisibilityChanged()->iFlags; + if (!alwaysResize) { + if (visibleFlags & TWsVisibilityChangedEvent::EPartiallyVisible) { + if (!isWidgetVisible(S60->splitViewLastWidget)) { + ensureFocusWidgetVisible(S60->splitViewLastWidget); + } + } else if (visibleFlags & TWsVisibilityChangedEvent::ENotVisible) { + resetSplitViewWidget(true); + } + } + } + } + return false; } @@ -343,6 +394,174 @@ TCoeInputCapabilities QCoeFepInputContext::inputCapabilities() return TCoeInputCapabilities(m_textCapabilities, this, 0); } +void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) +{ + QGraphicsView *gv = qobject_cast<QGraphicsView*>(S60->splitViewLastWidget); + + if (!gv) { + return; + } + + QSymbianControl *symControl = static_cast<QSymbianControl*>(S60->splitViewLastWidget->effectiveWinId()); + symControl->CancelLongTapTimer(); + + const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); + QWidget *windowToMove = gv ? gv : symControl->widget(); + if (!S60->splitViewLastWidget->isWindow()) + windowToMove = S60->splitViewLastWidget->window(); + + bool userResize = S60->splitViewLastWidget->testAttribute(Qt::WA_Resized); + bool userMove = windowToMove->testAttribute(Qt::WA_Moved); + + if (gv) + windowToMove->setUpdatesEnabled(false); + + if (gv && !alwaysResize) { + disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + if (gv && gv->scene()) { + QGraphicsItem *rootItem; + foreach (QGraphicsItem *item, gv->scene()->items()) { + if (!item->parentItem()) { + rootItem = item; + break; + } + } + if (rootItem) + rootItem->resetTransform(); + } + } + + // Resizing might have led to widget losing its original windowstate. + // Restore previous window state. + + if (m_splitViewPreviousWindowStates != windowToMove->windowState()) + windowToMove->setWindowState(m_splitViewPreviousWindowStates); + + if (m_splitViewResizeBy) + S60->splitViewLastWidget->updateGeometry(); + if (gv) + windowToMove->setUpdatesEnabled(true); + + S60->splitViewLastWidget->setAttribute(Qt::WA_Resized, userResize); //not a user resize + windowToMove->setAttribute(Qt::WA_Moved, userMove); //not a user move + + m_splitViewResizeBy = 0; + if (!keepInputWidget) { + m_splitViewPreviousWindowStates = Qt::WindowNoState; + S60->splitViewLastWidget = 0; + } +} + +// Checks if a given widget is visible in the splitview rect. The offset +// parameter can be used to validate if moving widget upwards or downwards +// by the offset would make a difference for the visibility. + +bool QCoeFepInputContext::isWidgetVisible(QWidget *widget, int offset) +{ + bool visible = false; + if (widget) { + QRect splitViewRect = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); + QWidget *window = QApplication::activeWindow(); + QGraphicsView *gv = qobject_cast<QGraphicsView*>(widget); + if (gv && window) { + if (QGraphicsScene *scene = gv->scene()) { + if (QGraphicsItem *focusItem = scene->focusItem()) { + QPoint cursorPos = window->mapToGlobal(focusItem->cursor().pos()); + cursorPos.setY(cursorPos.y() + offset); + if (splitViewRect.contains(cursorPos)) { + visible = true; + } + } + } + } + } + return visible; +} + +// Ensure that the input widget is visible in the splitview rect. + +void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) +{ + // Native side opening and closing its virtual keyboard when it changes the keyboard layout, + // has an adverse impact on long tap timer. Cancel the timer when splitview opens to avoid this. + QSymbianControl *symControl = static_cast<QSymbianControl*>(widget->effectiveWinId()); + symControl->CancelLongTapTimer(); + + // Graphicsviews that have vertical scrollbars should always be resized to the splitview area. + // Graphicsviews without scrollbars should be translated. + + QGraphicsView *gv = qobject_cast<QGraphicsView*>(widget); + if (!gv) + return; + + const bool alwaysResize = (gv && gv->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff); + const bool moveWithinVisibleArea = (S60->splitViewLastWidget != 0); + + QWidget *windowToMove = gv ? gv : symControl->widget(); + if (!windowToMove->isWindow()) + windowToMove = windowToMove->window(); + if (!windowToMove) { + return; + } + + // When opening the keyboard (not moving within the splitview area), save the original + // window state. In some cases, ensuring input widget visibility might lead to window + // states getting changed. + + if (!moveWithinVisibleArea) { + S60->splitViewLastWidget = widget; + m_splitViewPreviousWindowStates = windowToMove->windowState(); + } + + int windowTop = widget->window()->pos().y(); + + const bool userResize = widget->testAttribute(Qt::WA_Resized); + const bool userMove = windowToMove->testAttribute(Qt::WA_Moved); + + QRect splitViewRect = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); + + if (gv) { + + // When resizing a window widget, it will lose its maximized window state. + // Native applications hide statuspane in splitview state, so lets move to + // fullscreen mode. This makes available area slightly bigger, which helps usability + // and greatly reduces event passing in orientation switch cases, + // as the statuspane size is not changing. + + if (!(windowToMove->windowState() & Qt::WindowFullScreen)) { + widget->setWindowState( + (windowToMove->windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowFullScreen); + } + + if (alwaysResize) { + windowToMove->setUpdatesEnabled(false); + if (!moveWithinVisibleArea) + m_splitViewResizeBy = widget->height(); + + windowTop = widget->geometry().top(); + widget->resize(widget->width(), splitViewRect.height() - windowTop); + + if (gv && gv->scene()) { + const QRectF microFocusRect = gv->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF(); + gv->ensureVisible(microFocusRect); + } + windowToMove->setUpdatesEnabled(true); + } else { + if (!moveWithinVisibleArea) { + // Check if the widget contains cursorPositionChanged signal and connect to it. + const char *signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())).constData(); + int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal + 1); + if (index != -1) + connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + } + translateInputWidget(); + } + } + + widget->setAttribute(Qt::WA_Resized, userResize); //not a user resize + windowToMove->setAttribute(Qt::WA_Moved, userMove); //not a user move +} + static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat, bool validStyleColor) { QTextCharFormat qFormat; @@ -474,10 +693,12 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetPermittedCases(flags); ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate); - if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) - flags = QT_EAknEditorFlagSelectionVisible; - else - flags = 0; + flags = 0; + if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) { + if (S60->partial_keyboard) + flags |= QT_EAknEditorFlagEnablePartialScreen; + flags |= QT_EAknEditorFlagSelectionVisible; + } if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly) || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) { flags |= EAknEditorFlagFixedCase; @@ -604,6 +825,47 @@ void QCoeFepInputContext::ensureInputCapabilitiesChanged() m_pendingInputCapabilitiesChanged = false; } +void QCoeFepInputContext::translateInputWidget() +{ + QGraphicsView *gv = qobject_cast<QGraphicsView *>(S60->splitViewLastWidget); + QRect splitViewRect = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); + + QRectF cursor = gv->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF(); + QPolygon cursorP = gv->mapFromScene(cursor); + QRectF vkbRect = QRectF(splitViewRect.bottomLeft(), qApp->desktop()->rect().bottomRight()); + if (cursor.isEmpty() || vkbRect.isEmpty()) + return; + + // Fetch root item (i.e. graphicsitem with no parent) + QGraphicsItem *rootItem; + foreach (QGraphicsItem *item, gv->scene()->items()) { + if (!item->parentItem()) { + rootItem = item; + break; + } + } + if (!rootItem) + return; + + m_transformation = (rootItem->transform().isTranslating()) ? QRectF(0,0, gv->width(), rootItem->transform().dy()) : QRectF(); + + // Do nothing if the cursor is visible in the splitview area. + if (splitViewRect.contains(cursorP.boundingRect())) + return; + + // New Y position should be ideally at the center of the splitview area. + // If that would expose unpainted canvas, limit the tranformation to the visible scene bottom. + + const qreal maxY = gv->sceneRect().bottom() - splitViewRect.bottom() + m_transformation.height(); + qreal dy = -(qMin(maxY, (cursor.bottom() - vkbRect.top() / 2))); + + // Do not allow transform above screen top. + if (m_transformation.height() + dy > 0) + return; + + rootItem->setTransform(QTransform::fromTranslate(0, dy), true); +} + void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/, MFepInlineTextFormatRetriever& aInlineTextFormatRetriever, diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index e54cbd2..9f89bf5 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -227,7 +227,7 @@ public: void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end); - void clear_mapping(); + void _q_clearMapping(); void sort(); bool update_source_sort_column(); @@ -281,7 +281,7 @@ typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap; void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() { QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); - clear_mapping(); + _q_clearMapping(); } void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent) @@ -293,7 +293,7 @@ void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source } } -void QSortFilterProxyModelPrivate::clear_mapping() +void QSortFilterProxyModelPrivate::_q_clearMapping() { // store the persistent indexes QModelIndexPairList source_indexes = store_persistent_indexes(); @@ -1223,7 +1223,7 @@ void QSortFilterProxyModelPrivate::_q_sourceReset() { Q_Q(QSortFilterProxyModel); invalidatePersistentIndexes(); - clear_mapping(); + _q_clearMapping(); // All internal structures are deleted in clear() q->endResetModel(); update_source_sort_column(); @@ -1519,6 +1519,7 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent) d->filter_column = 0; d->filter_role = Qt::DisplayRole; d->dynamic_sortfilter = false; + connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping())); } /*! @@ -1620,7 +1621,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); - d->clear_mapping(); + d->_q_clearMapping(); endResetModel(); if (d->update_source_sort_column() && d->dynamic_sortfilter) d->sort(); @@ -2311,7 +2312,7 @@ void QSortFilterProxyModel::clear() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } @@ -2326,7 +2327,7 @@ void QSortFilterProxyModel::invalidate() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } diff --git a/src/gui/itemviews/qsortfilterproxymodel.h b/src/gui/itemviews/qsortfilterproxymodel.h index 09fd20f..afeaa69 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.h +++ b/src/gui/itemviews/qsortfilterproxymodel.h @@ -189,6 +189,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_clearMapping()) }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 6bddb19..6e43c8b 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -87,7 +87,7 @@ #include <hal.h> #include <hal_data.h> -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS #include <graphics/wstfxconst.h> #endif @@ -96,6 +96,10 @@ QT_BEGIN_NAMESPACE // Goom Events through Window Server static const int KGoomMemoryLowEvent = 0x10282DBF; static const int KGoomMemoryGoodEvent = 0x20026790; +// Split view open/close events from AVKON +static const int KSplitViewOpenEvent = 0x2001E2C0; +static const int KSplitViewCloseEvent = 0x2001E2C1; + #if defined(QT_DEBUG) static bool appNoGrab = false; // Grabbing enabled @@ -401,6 +405,7 @@ QSymbianControl::QSymbianControl(QWidget *w) , m_longTapDetector(0) , m_ignoreFocusChanged(0) , m_symbianPopupIsOpen(0) + , m_inExternalScreenOverride(false) { } @@ -408,9 +413,11 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) { if (!desktop) { - if (isWindowOwning || !qwidget->parentWidget()) - CreateWindowL(S60->windowGroup()); - else + if (isWindowOwning || !qwidget->parentWidget() + || qwidget->parentWidget()->windowType() == Qt::Desktop) { + RWindowGroup &wg(S60->windowGroup(qwidget)); + CreateWindowL(wg); + } else { /** * TODO: in order to avoid creating windows for all ancestors of * this widget up to the root window, the parameter passed to @@ -420,6 +427,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) * is created for a widget between this one and the root window. */ CreateWindowL(qwidget->parentWidget()->winId()); + } // Necessary in order to be able to track the activation status of // the control's window @@ -432,7 +440,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) DrawableWindow()->SetPointerGrab(ETrue); } -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS if (OwnsWindow()) { TTfxWindowPurpose windowPurpose(ETfxPurposeNone); switch (qwidget->windowType()) { @@ -452,7 +460,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) windowPurpose = ETfxPurposeSplashScreenWindow; break; default: - windowPurpose = (isWindowOwning || !qwidget->parentWidget()) + windowPurpose = (isWindowOwning || !qwidget->parentWidget() || qwidget->parentWidget()->windowType() == Qt::Desktop) ? ETfxPurposeWindow : ETfxPurposeChildWindow; break; } @@ -983,14 +991,15 @@ TKeyResponse QSymbianControl::handleVirtualMouse(const TKeyEvent& keyEvent,TEven } } //clip to screen size (window server allows a sprite hotspot to be outside the screen) + int screenNumber = S60->screenNumberForWidget(qwidget); if (x < 0) x = 0; - else if (x >= S60->screenWidthInPixels) - x = S60->screenWidthInPixels - 1; + else if (x >= S60->screenWidthInPixelsForScreen[screenNumber]) + x = S60->screenWidthInPixelsForScreen[screenNumber] - 1; if (y < 0) y = 0; - else if (y >= S60->screenHeightInPixels) - y = S60->screenHeightInPixels - 1; + else if (y >= S60->screenHeightInPixelsForScreen[screenNumber]) + y = S60->screenHeightInPixelsForScreen[screenNumber] - 1; TPoint epos(x, y); TPoint cpos = epos - PositionRelativeToScreen(); fakeEvent.iPosition = cpos; @@ -1167,6 +1176,18 @@ void QSymbianControl::SizeChanged() QSize newSize(Size().iWidth, Size().iHeight); if (oldSize != newSize) { + const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; + const int screenNumber = S60->screenNumberForWidget(qwidget); + if (!m_inExternalScreenOverride && isFullscreen && screenNumber > 0) { + int screenWidth = S60->screenWidthInPixelsForScreen[screenNumber]; + int screenHeight = S60->screenHeightInPixelsForScreen[screenNumber]; + TSize screenSize(screenWidth, screenHeight); + if (screenWidth > 0 && screenHeight > 0 && screenSize != Size()) { + m_inExternalScreenOverride = true; + SetExtent(TPoint(0, 0), screenSize); + return; + } + } QRect cr = qwidget->geometry(); cr.setSize(newSize); qwidget->data->crect = cr; @@ -1189,6 +1210,8 @@ void QSymbianControl::SizeChanged() } } + m_inExternalScreenOverride = false; + // CCoeControl::SetExtent calls SizeChanged, but does not call // PositionChanged, so we call it here to ensure that the widget's // position is updated. @@ -1224,6 +1247,11 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) if (m_ignoreFocusChanged || (qwidget->windowType() & Qt::WindowType_Mask) == Qt::Desktop) return; +#ifdef Q_WS_S60 + if (S60->splitViewLastWidget) + return; +#endif + // Popups never get focused, but still receive the FocusChanged when they are hidden. if (QApplicationPrivate::popupWidgets != 0 || (qwidget->windowType() & Qt::Popup) == Qt::Popup) @@ -1302,9 +1330,56 @@ void QSymbianControl::handleClientAreaChange() } } +bool QSymbianControl::isSplitViewWidget(QWidget *widget) { + bool returnValue = true; + //Ignore events sent to non-active windows, not visible widgets and not parents of input widget. + if (!qwidget->isActiveWindow() + || !qwidget->isVisible() + || !qwidget->isAncestorOf(widget)) { + + returnValue = false; + } + return returnValue; +} + void QSymbianControl::HandleResourceChange(int resourceType) { switch (resourceType) { + case KSplitViewCloseEvent: //intentional fall-through + case KSplitViewOpenEvent: { +#if !defined(QT_NO_IM) && defined(Q_WS_S60) + + //Fetch widget getting the text input + QWidget *widget = QWidget::keyboardGrabber(); + if (!widget) { + if (QApplicationPrivate::popupWidgets) { + widget = QApplication::activePopupWidget()->focusWidget(); + if (!widget) { + widget = QApplication::activePopupWidget(); + } + } else { + widget = QApplicationPrivate::focus_widget; + if (!widget) { + widget = qwidget; + } + } + } + if (widget) { + QCoeFepInputContext *ic = qobject_cast<QCoeFepInputContext *>(widget->inputContext()); + if (!ic) { + ic = qobject_cast<QCoeFepInputContext *>(qApp->inputContext()); + } + if (ic && isSplitViewWidget(widget)) { + if (resourceType == KSplitViewCloseEvent) { + ic->resetSplitViewWidget(); + } else { + ic->ensureFocusWidgetVisible(widget); + } + } + } +#endif // !defined(QT_NO_IM) && defined(Q_WS_S60) + } + break; case KInternalStatusPaneChange: handleClientAreaChange(); if (IsFocused() && IsVisible()) { @@ -1586,7 +1661,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont); -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); #endif @@ -1686,7 +1761,7 @@ bool QApplicationPrivate::modalState() void QApplicationPrivate::enterModal_sys(QWidget *widget) { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter); #endif if (widget) { @@ -1704,7 +1779,7 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget) void QApplicationPrivate::leaveModal_sys(QWidget *widget) { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit); #endif if (widget) { @@ -1979,7 +2054,10 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent return 1; } break; - case EEventScreenDeviceChanged: + case EEventScreenDeviceChanged: // fallthrough +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + case EEventDisplayChanged: +#endif if (callSymbianEventFilters(symbianEvent)) return 1; if (S60) @@ -2385,7 +2463,7 @@ void QApplication::restoreOverrideCursor() void QApplicationPrivate::_q_aboutToQuit() { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS +#ifdef Q_SYMBIAN_TRANSITION_EFFECTS // Send the shutdown tfx command S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); #endif diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 9c110fd..6254061 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -89,6 +89,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if (QApplicationPrivate::isBlockedByModal(widget)) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); @@ -100,6 +102,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if ([self isSheet]) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp index 3653ae2..c3963f4 100644 --- a/src/gui/kernel/qdesktopwidget_s60.cpp +++ b/src/gui/kernel/qdesktopwidget_s60.cpp @@ -44,36 +44,67 @@ #include "qwidget_p.h" #include "qt_s60_p.h" #include <w32std.h> - -#include "hal.h" -#include "hal_data.h" +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) +#include <graphics/displaycontrol.h> +#endif QT_BEGIN_NAMESPACE -class QDesktopWidgetPrivate : public QWidgetPrivate +extern int qt_symbian_create_desktop_on_screen; + +class QSingleDesktopWidget : public QWidget +{ +public: + QSingleDesktopWidget(); + ~QSingleDesktopWidget(); +}; + +QSingleDesktopWidget::QSingleDesktopWidget() + : QWidget(0, Qt::Desktop) +{ +} + +QSingleDesktopWidget::~QSingleDesktopWidget() { + const QObjectList &childList = children(); + for (int i = childList.size(); i > 0 ;) { + --i; + childList.at(i)->setParent(0); + } +} +class QDesktopWidgetPrivate : public QWidgetPrivate +{ public: QDesktopWidgetPrivate(); ~QDesktopWidgetPrivate(); - static void init(QDesktopWidget *that); static void cleanup(); + static void init_sys(); static int screenCount; static int primaryScreen; static QVector<QRect> *rects; static QVector<QRect> *workrects; + static QVector<QWidget *> *screens; static int refcount; + +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + static MDisplayControl *displayControl; +#endif }; int QDesktopWidgetPrivate::screenCount = 1; int QDesktopWidgetPrivate::primaryScreen = 0; QVector<QRect> *QDesktopWidgetPrivate::rects = 0; QVector<QRect> *QDesktopWidgetPrivate::workrects = 0; +QVector<QWidget *> *QDesktopWidgetPrivate::screens = 0; int QDesktopWidgetPrivate::refcount = 0; +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) +MDisplayControl *QDesktopWidgetPrivate::displayControl = 0; +#endif QDesktopWidgetPrivate::QDesktopWidgetPrivate() { @@ -88,25 +119,55 @@ QDesktopWidgetPrivate::~QDesktopWidgetPrivate() void QDesktopWidgetPrivate::init(QDesktopWidget *that) { - Q_UNUSED(that); -// int screenCount=0; - - // ### TODO: Implement proper multi-display support - QDesktopWidgetPrivate::screenCount = 1; -// if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone) -// QDesktopWidgetPrivate::screenCount = screenCount; -// else -// QDesktopWidgetPrivate::screenCount = 0; + // Note that on S^3 devices the screen count retrieved via RWsSession + // will always be 2 but the width and height for screen number 1 will + // be 0 as long as TV-out is not connected. + // + // On the other hand a valid size for screen 1 will be reported even + // after the cable is disconnected. In order to overcome this, we use + // MDisplayControl::NumberOfResolutions() to check if the display is + // valid or not. + + screenCount = S60->screenCount(); +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + if (displayControl) { + if (displayControl->NumberOfResolutions() < 1) + screenCount = 1; + } +#endif + if (screenCount < 1) { + qWarning("No screen available"); + screenCount = 1; + } rects = new QVector<QRect>(); workrects = new QVector<QRect>(); - - rects->resize(QDesktopWidgetPrivate::screenCount); - workrects->resize(QDesktopWidgetPrivate::screenCount); - - (*rects)[0].setRect(0, 0, S60->screenWidthInPixels, S60->screenHeightInPixels); - QRect wr = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); - (*workrects)[0].setRect(wr.x(), wr.y(), wr.width(), wr.height()); + screens = new QVector<QWidget *>(); + + rects->resize(screenCount); + workrects->resize(screenCount); + screens->resize(screenCount); + + for (int i = 0; i < screenCount; ++i) { + // All screens will have a position of (0, 0) as there is no true virtual desktop + // or pointer event support for multiple screens on Symbian. + QRect r(0, 0, + S60->screenWidthInPixelsForScreen[i], S60->screenHeightInPixelsForScreen[i]); + // Stop here if empty and ignore this screen. + if (r.isEmpty()) { + screenCount = i; + break; + } + (*rects)[i] = r; + QRect wr; + if (i == 0) + wr = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); + else + wr = rects->at(i); + (*workrects)[i].setRect(wr.x(), wr.y(), wr.width(), wr.height()); + (*screens)[i] = 0; + } + (*screens)[0] = that; } void QDesktopWidgetPrivate::cleanup() @@ -115,6 +176,27 @@ void QDesktopWidgetPrivate::cleanup() rects = 0; delete workrects; workrects = 0; + if (screens) { + // First item is the QDesktopWidget so skip it. + for (int i = 1; i < screens->count(); ++i) + delete screens->at(i); + } + delete screens; + screens = 0; +} + +void QDesktopWidgetPrivate::init_sys() +{ +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + CWsScreenDevice *dev = S60->screenDevice(1); + if (dev) { + displayControl = static_cast<MDisplayControl *>( + dev->GetInterface(MDisplayControl::ETypeId)); + if (displayControl) { + displayControl->EnableDisplayChangeEvents(ETrue); + } + } +#endif } @@ -122,6 +204,7 @@ QDesktopWidget::QDesktopWidget() : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) { setObjectName(QLatin1String("desktop")); + QDesktopWidgetPrivate::init_sys(); QDesktopWidgetPrivate::init(this); } @@ -131,7 +214,7 @@ QDesktopWidget::~QDesktopWidget() bool QDesktopWidget::isVirtualDesktop() const { - return true; + return false; } int QDesktopWidget::primaryScreen() const @@ -145,9 +228,23 @@ int QDesktopWidget::numScreens() const return QDesktopWidgetPrivate::screenCount; } -QWidget *QDesktopWidget::screen(int /* screen */) +static inline QWidget *newSingleDesktopWidget(int screen) { - return this; + qt_symbian_create_desktop_on_screen = screen; + QWidget *w = new QSingleDesktopWidget; + qt_symbian_create_desktop_on_screen = -1; + return w; +} + +QWidget *QDesktopWidget::screen(int screen) +{ + Q_D(QDesktopWidget); + if (screen < 0 || screen >= d->screenCount) + screen = d->primaryScreen; + if (!d->screens->at(screen) + || d->screens->at(screen)->windowType() != Qt::Desktop) + (*d->screens)[screen] = newSingleDesktopWidget(screen); + return (*d->screens)[screen]; } const QRect QDesktopWidget::availableGeometry(int screen) const @@ -168,14 +265,19 @@ const QRect QDesktopWidget::screenGeometry(int screen) const return d->rects->at(screen); } -int QDesktopWidget::screenNumber(const QWidget * /* widget */) const +int QDesktopWidget::screenNumber(const QWidget *widget) const { - return QDesktopWidgetPrivate::primaryScreen; + Q_D(const QDesktopWidget); + return widget + ? S60->screenNumberForWidget(widget) + : d->primaryScreen; } -int QDesktopWidget::screenNumber(const QPoint & /* point */) const +int QDesktopWidget::screenNumber(const QPoint &point) const { - return QDesktopWidgetPrivate::primaryScreen; + Q_UNUSED(point); + Q_D(const QDesktopWidget); + return d->primaryScreen; } void QDesktopWidget::resizeEvent(QResizeEvent *) @@ -203,6 +305,10 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) if (oldrect != newrect) emit workAreaResized(j); } + + if (oldscreencount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } } QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 40697bf..3bb27c3 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -64,6 +64,7 @@ #include "qapplication.h" #include "qelapsedtimer.h" #include "QtCore/qthreadstorage.h" +#include "qwidget_p.h" #include <w32std.h> #include <coecntrl.h> #include <eikenv.h> @@ -84,6 +85,8 @@ QT_BEGIN_NAMESPACE // system events seems to start with 0x10 const TInt KInternalStatusPaneChange = 0x50000000; +static const int qt_symbian_max_screens = 4; + //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) @@ -142,7 +145,10 @@ public: int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; int orientationSet : 1; + int partial_keyboard : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type + QPointer<QWidget> splitViewLastWidget; + static CEikButtonGroupContainer *cba; enum ScanCodeState { @@ -154,8 +160,14 @@ public: static inline void updateScreenSize(); inline RWsSession& wsSession(); + static inline int screenCount(); static inline RWindowGroup& windowGroup(); + static inline RWindowGroup& windowGroup(const QWidget *widget); + static inline RWindowGroup& windowGroup(int screenNumber); inline CWsScreenDevice* screenDevice(); + inline CWsScreenDevice* screenDevice(const QWidget *widget); + inline CWsScreenDevice* screenDevice(int screenNumber); + static inline int screenNumberForWidget(const QWidget *widget); static inline CCoeAppUi* appUi(); static inline CEikMenuBar* menuBar(); #ifdef Q_WS_S60 @@ -172,6 +184,11 @@ public: #ifdef Q_OS_SYMBIAN TTrapHandler *s60InstalledTrapHandler; #endif + + int screenWidthInPixelsForScreen[qt_symbian_max_screens]; + int screenHeightInPixelsForScreen[qt_symbian_max_screens]; + int screenWidthInTwipsForScreen[qt_symbian_max_screens]; + int screenHeightInTwipsForScreen[qt_symbian_max_screens]; }; Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); @@ -252,6 +269,7 @@ private: #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); #endif + bool isSplitViewWidget(QWidget *widget); public: void handleClientAreaChange(); @@ -270,6 +288,8 @@ private: // Fader object used to fade everything except this menu and the CBA. TAknPopupFader popupFader; #endif + + bool m_inExternalScreenOverride : 1; }; inline QS60Data::QS60Data() @@ -297,6 +317,7 @@ inline QS60Data::QS60Data() avkonComponentsSupportTransparency(0), menuBeingConstructed(0), orientationSet(0), + partial_keyboard(0), s60ApplicationFactory(0) #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) @@ -320,6 +341,17 @@ inline void QS60Data::updateScreenSize() S60->defaultDpiY = S60->screenHeightInPixels / inches; inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch; S60->defaultDpiX = S60->screenWidthInPixels / inches; + + int screens = S60->screenCount(); + for (int i = 0; i < screens; ++i) { + CWsScreenDevice *dev = S60->screenDevice(i); + mode = dev->CurrentScreenMode(); + dev->GetScreenModeSizeAndRotation(mode, params); + S60->screenWidthInPixelsForScreen[i] = params.iPixelSize.iWidth; + S60->screenHeightInPixelsForScreen[i] = params.iPixelSize.iHeight; + S60->screenWidthInTwipsForScreen[i] = params.iTwipsSize.iWidth; + S60->screenHeightInTwipsForScreen[i] = params.iTwipsSize.iHeight; + } } inline RWsSession& QS60Data::wsSession() @@ -330,11 +362,38 @@ inline RWsSession& QS60Data::wsSession() return tls.localData()->wsSession; } +inline int QS60Data::screenCount() +{ +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + CCoeEnv *env = CCoeEnv::Static(); + if (env) { + return qMin(env->WsSession().NumberOfScreens(), qt_symbian_max_screens); + } +#endif + return 1; +} + inline RWindowGroup& QS60Data::windowGroup() { return CCoeEnv::Static()->RootWin(); } +inline RWindowGroup& QS60Data::windowGroup(const QWidget *widget) +{ + return windowGroup(screenNumberForWidget(widget)); +} + +inline RWindowGroup& QS60Data::windowGroup(int screenNumber) +{ +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + RWindowGroup *wg = CCoeEnv::Static()->RootWin(screenNumber); + return wg ? *wg : windowGroup(); +#else + Q_UNUSED(screenNumber); + return windowGroup(); +#endif +} + inline CWsScreenDevice* QS60Data::screenDevice() { if(!tls.hasLocalData()) { @@ -343,6 +402,36 @@ inline CWsScreenDevice* QS60Data::screenDevice() return tls.localData()->screenDevice; } +inline CWsScreenDevice* QS60Data::screenDevice(const QWidget *widget) +{ + return screenDevice(screenNumberForWidget(widget)); +} + +inline CWsScreenDevice* QS60Data::screenDevice(int screenNumber) +{ +#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) + CCoeEnv *env = CCoeEnv::Static(); + if (env) { + CWsScreenDevice *dev = env->ScreenDevice(screenNumber); + return dev ? dev : screenDevice(); + } else { + return screenDevice(); + } +#else + return screenDevice(); +#endif +} + +inline int QS60Data::screenNumberForWidget(const QWidget *widget) +{ + if (!widget) + return 0; + const QWidget *w = widget; + while (w->parentWidget()) + w = w->parentWidget(); + return qt_widget_private(const_cast<QWidget *>(w))->symbianScreenNumber; +} + inline CCoeAppUi* QS60Data::appUi() { return CCoeEnv::Static()-> AppUi(); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7065e85..1786e65 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -304,6 +304,8 @@ QWidgetPrivate::QWidgetPrivate(int version) , hasAlienChildren(0) , window_event(0) , qd_hd(0) +#elif defined(Q_OS_SYMBIAN) + , symbianScreenNumber(0) #endif { if (!qApp) { @@ -1284,6 +1286,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) // programmer specified desktop widget xinfo = desktopWidget->d_func()->xinfo; } +#elif defined(Q_OS_SYMBIAN) + if (desktopWidget) { + symbianScreenNumber = qt_widget_private(desktopWidget)->symbianScreenNumber; + } #else Q_UNUSED(desktopWidget); #endif diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 9f6ba6f..5235dc4 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -877,6 +877,7 @@ public: #elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN static QWidget *mouseGrabber; static QWidget *keyboardGrabber; + int symbianScreenNumber; // only valid for desktop widget and top-levels void s60UpdateIsOpaque(); void reparentChildren(); void registerTouchWindow(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index af9ae47..be212fb 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -84,6 +84,8 @@ QWidget *QWidgetPrivate::mouseGrabber = 0; QWidget *QWidgetPrivate::keyboardGrabber = 0; CEikButtonGroupContainer *QS60Data::cba = 0; +int qt_symbian_create_desktop_on_screen = -1; + static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) { if ( a.count() != b.count()) @@ -349,12 +351,18 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de int sh = clientRect.Height(); if (desktop) { - TSize screenSize = S60->screenDevice()->SizeInPixels(); + symbianScreenNumber = qMax(qt_symbian_create_desktop_on_screen, 0); + TSize screenSize = S60->screenDevice(symbianScreenNumber)->SizeInPixels(); data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight); q->setAttribute(Qt::WA_DontShowOnScreen); } else if (topLevel && !q->testAttribute(Qt::WA_Resized)){ int width = sw; int height = sh; + if (symbianScreenNumber > 0) { + TSize screenSize = S60->screenDevice(symbianScreenNumber)->SizeInPixels(); + width = screenSize.iWidth; + height = screenSize.iHeight; + } if (extra) { width = qMax(qMin(width, extra->maxw), extra->minw); height = qMax(qMin(height, extra->maxh), extra->minh); @@ -640,7 +648,7 @@ void QWidgetPrivate::raise_sys() // If toplevel widget, raise app to foreground if (q->isWindow()) - S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), 0); + S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup(q).Identifier(), 0); } } @@ -652,7 +660,7 @@ void QWidgetPrivate::lower_sys() if (q->internalWinId()) { // If toplevel widget, lower app to background if (q->isWindow()) - S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), -1); + S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup(q).Identifier(), -1); else q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1); } @@ -722,6 +730,11 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) { Q_Q(QWidget); + if (parent && parent->windowType() == Qt::Desktop) { + symbianScreenNumber = qt_widget_private(parent)->symbianScreenNumber; + parent = 0; + } + bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) @@ -1037,7 +1050,7 @@ int QWidget::metric(PaintDeviceMetric m) const } else if (m == PdmHeight) { val = data->crect.height(); } else { - CWsScreenDevice *scr = S60->screenDevice(); + CWsScreenDevice *scr = S60->screenDevice(this); switch(m) { case PdmDpiX: case PdmPhysicalDpiX: @@ -1207,7 +1220,16 @@ void QWidget::setWindowState(Qt::WindowStates newstate) const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { setAttribute(Qt::WA_OutsideWSRange, false); - window->SetExtentToWholeScreen(); + if (d->symbianScreenNumber > 0) { + int w = S60->screenWidthInPixelsForScreen[d->symbianScreenNumber]; + int h = S60->screenHeightInPixelsForScreen[d->symbianScreenNumber]; + if (w <= 0 || h <= 0) + window->SetExtentToWholeScreen(); + else + window->SetExtent(TPoint(0, 0), TSize(w, h)); + } else { + window->SetExtentToWholeScreen(); + } } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) { setAttribute(Qt::WA_OutsideWSRange, false); TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 83c58c4..4fcff1d 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -1117,6 +1117,11 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg return; } + // If there's no partial update support we always need + // to do a full repaint before flushing + if (!windowSurface->hasPartialUpdateSupport()) + fullUpdatePending = true; + // Nothing to repaint. if (!isDirty()) { qt_flush(exposedWidget, exposedRegion, windowSurface, tlw, tlwOffset); diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 770d947..5112019 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -84,4 +84,9 @@ QPixmapData *QGraphicsSystem::createPixmapData(QPixmapData *origin) return createPixmapData(origin->pixelType()); } +void QGraphicsSystem::releaseCachedResources() +{ + // Do nothing here +} + QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index 76e9a8e..80e8959 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -72,6 +72,8 @@ public: //### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed // to have a graphics system. static QPixmapData *createDefaultPixmapData(QPixmapData::PixelType type); + + virtual void releaseCachedResources(); }; QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 0294c4b..5841d40 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -285,6 +285,7 @@ void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion ®ion, void QRuntimeWindowSurface::setGeometry(const QRect &rect) { + QWindowSurface::setGeometry(rect); m_windowSurface->setGeometry(rect); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 682731a..ba618ea 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3706,6 +3706,13 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line, const bool squareCap = (pen.capStyle() == Qt::SquareCap); const QVector<qreal> pattern = pen.dashPattern(); + qreal patternLength = 0; + for (int i = 0; i < pattern.size(); ++i) + patternLength += pattern.at(i); + + if (patternLength <= 0) + return; + qreal length = line.length(); Q_ASSERT(length > 0); while (length > 0) { diff --git a/src/gui/painting/qpaintengine_s60.cpp b/src/gui/painting/qpaintengine_s60.cpp index 1bc7799..ca303be 100644 --- a/src/gui/painting/qpaintengine_s60.cpp +++ b/src/gui/painting/qpaintengine_s60.cpp @@ -41,6 +41,7 @@ #include <private/qpaintengine_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qt_s60_p.h> +#include <private/qvolatileimage_p.h> QT_BEGIN_NAMESPACE @@ -90,7 +91,15 @@ void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) QRasterPaintEngine::drawPixmap(p, pm); srcData->endDataAccess(); } else { - QRasterPaintEngine::drawPixmap(p, pm); + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(p, img->imageRef()); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(p, pm); + } } } @@ -102,7 +111,15 @@ void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRect QRasterPaintEngine::drawPixmap(r, pm, sr); srcData->endDataAccess(); } else { - QRasterPaintEngine::drawPixmap(r, pm, sr); + void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); + if (nativeData) { + QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); + img->beginDataAccess(); + QRasterPaintEngine::drawImage(r, img->imageRef(), sr); + img->endDataAccess(true); + } else { + QRasterPaintEngine::drawPixmap(r, pm, sr); + } } } diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index eadb8ff..2a0de3c 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -404,6 +404,7 @@ static QEvent *cloneEvent(QEvent *e) we2->setButtons(we->buttons()); we2->setModifiers(we->modifiers()); we2->setOrientation(we->orientation()); + we2->setDelta(we->delta()); return we2; } #endif diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 605872e..600c631 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -47,6 +47,7 @@ #include "private/qt_s60_p.h" #include "private/qpixmap_s60_p.h" #include "private/qcore_symbian_p.h" +#include "private/qvolatileimage_p.h" #include "qapplication.h" #include "qsettings.h" @@ -637,9 +638,22 @@ QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask if (error) return QPixmap(); - QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(icon); - if (mask) - pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); + QPixmap pixmap; + QScopedPointer<QPixmapData> pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + bool nativeMaskSupported = (pd->toNativeType(QPixmapData::VolatileImage) != 0); + if (mask && nativeMaskSupported) { + // Efficient path, less copying and conversion. + QVolatileImage img(icon, mask); + pd->fromNativeType(&img, QPixmapData::VolatileImage); + pixmap = QPixmap(pd.take()); + } else { + // Potentially more expensive path. + pd->fromNativeType(icon, QPixmapData::FbsBitmap); + pixmap = QPixmap(pd.take()); + if (mask) { + pixmap.setAlphaChannel(QPixmap::fromSymbianCFbsBitmap(mask)); + } + } if ((flags & QS60StylePrivate::SF_PointEast) || (flags & QS60StylePrivate::SF_PointSouth) || @@ -795,6 +809,8 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size); MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + static const TDisplayMode displayMode = S60->supportsPremultipliedAlpha ? Q_SYMBIAN_ECOLOR16MAP : EColor16MA; + static const TInt drawParam = S60->supportsPremultipliedAlpha ? KAknsDrawParamDefault : KAknsDrawParamRGBOnly; QPixmap result; @@ -833,7 +849,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( // QS60WindowSurface::unlockBitmapHeap(); CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen CleanupStack::PushL(background); - User::LeaveIfError(background->Create(targetSize, EColor16MA)); + User::LeaveIfError(background->Create(targetSize, displayMode)); CFbsBitmapDevice *dev = CFbsBitmapDevice::NewL(background); CleanupStack::PushL(dev); @@ -854,7 +870,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( *gc, TPoint(), targetSize, - KAknsDrawParamDefault | KAknsDrawParamRGBOnly); + drawParam); if (drawn) result = fromFbsBitmap(background, NULL, flags, targetSize); diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 1c21f91..42b9402 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE +static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); + /***************************************************************************** QFontEngine debug facilities *****************************************************************************/ @@ -467,6 +469,9 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) glyph_metrics_t ret; CGGlyph g = glyph; CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1); + if (synthesisFlags & QFontEngine::SynthesizedItalic) { + rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW; + } ret.width = QFixed::fromReal(rect.size.width); ret.height = QFixed::fromReal(rect.size.height); ret.x = QFixed::fromReal(rect.origin.x); @@ -558,7 +563,7 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -646,7 +651,7 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); for (int i = 0; i < nGlyphs; ++i) { @@ -681,7 +686,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -1625,7 +1630,7 @@ QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful) CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -1718,7 +1723,7 @@ void QFontEngineMac::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index e380b37..f5da079 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -284,7 +284,7 @@ bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); emit q->microFocusChanged(); - } else if (ignoreNavigationEvents && isNavigationEvent) { + } else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) { return false; } @@ -932,15 +932,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::MouseMove: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonRelease: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonDblClick: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::InputMethod: d->inputMethodEvent(static_cast<QInputMethodEvent *>(e)); @@ -1000,15 +1003,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::GraphicsSceneMouseMove: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseRelease: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseDoubleClick: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneContextMenu: { QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e); @@ -1017,7 +1023,8 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte case QEvent::GraphicsSceneHoverMove: { QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e); - d->mouseMoveEvent(Qt::NoButton, matrix.map(ev->pos())); + d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, + ev->screenPos()); break; } case QEvent::GraphicsSceneDragEnter: { @@ -1487,6 +1494,11 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { anchorOnMousePress = q->anchorAt(pos); @@ -1529,22 +1541,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - if (ctx) { - QMouseEvent ev(QEvent::MouseButtonPress, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos - cursor.position(), &ev); - } - if (!layout->preeditAreaText().isEmpty()) { - e->ignore(); - return; - } - } -#endif - if (modifiers == Qt::ShiftModifier) { + if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { selectedWordOnDoubleClick = cursor; selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); @@ -1589,10 +1586,16 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con hadSelectionOnMousePress = cursor.hasSelection(); } -void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &mousePos) +void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { QString anchor = q->anchorAt(mousePos); if (anchor != highlightedAnchor) { @@ -1622,12 +1625,6 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF } const qreal mouseX = qreal(mousePos.x()); -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); if (newCursorPos == -1) return; @@ -1641,7 +1638,7 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(newCursorPos, mouseX); - else + else if (interactionFlags & Qt::TextSelectableByMouse) setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextEditable) { @@ -1652,8 +1649,10 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); #ifndef QT_NO_IM - if (QInputContext *ic = inputContext()) { - ic->update(); + if (contextWidget) { + if (QInputContext *ic = inputContext()) { + ic->update(); + } } #endif //QT_NO_IM } else { @@ -1665,10 +1664,16 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF repaintOldAndNewSelection(oldSelection); } -void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { + return; + } + const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -1726,19 +1731,21 @@ void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPoint } } -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (button != Qt::LeftButton || !(interactionFlags & Qt::TextSelectableByMouse)) { e->ignore(); return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; @@ -1767,6 +1774,45 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto } } +bool QTextControlPrivate::sendMouseEventToInputContext( + QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) +{ +#if !defined(QT_NO_IM) + Q_Q(QTextControl); + + QTextLayout *layout = cursor.block().layout(); + if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { + QInputContext *ctx = inputContext(); + int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); + + if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { + cursorPos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + if (ctx) { + QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, + button, buttons, modifiers); + ctx->mouseHandler(cursorPos, &ev); + e->setAccepted(ev.isAccepted()); + } + if (!layout->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); + Q_UNUSED(eventType); + Q_UNUSED(button); + Q_UNUSED(pos); + Q_UNUSED(modifiers); + Q_UNUSED(buttons); + Q_UNUSED(globalPos); +#endif + return false; +} + void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) { #ifdef QT_NO_CONTEXTMENU diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index ecd13ea..94670e2 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -135,9 +135,23 @@ public: Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos); - void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos); - void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos); - void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos); + void mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + bool sendMouseEventToInputContext(QEvent *e, QEvent::Type eventType, Qt::MouseButton button, + const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); void contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget); void focusEvent(QFocusEvent *e); #ifdef QT_KEYPAD_NAVIGATION diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp index ce42241..c34bdb3 100644 --- a/src/gui/text/qtextengine_mac.cpp +++ b/src/gui/text/qtextengine_mac.cpp @@ -604,8 +604,9 @@ void QTextEngine::shapeTextMac(int item) const bool stringToCMapFailed = false; if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) { ensureSpace(num_glyphs); - stringToCMapFailed = fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, - attributes()); + g = availableGlyphs(&si); + stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, + attributes()); } if (!stringToCMapFailed) { diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index c7a3913..bffc2b5 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -420,7 +420,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string if (event->replacementStart() <= 0) - c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); + c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); @@ -456,6 +456,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) #ifndef QT_NO_IM setPreeditArea(m_cursor, event->preeditString()); #endif //QT_NO_IM + const int oldPreeditCursor = m_preeditCursor; m_preeditCursor = event->preeditString().length(); m_hideCursor = false; QList<QTextLayout::FormatRange> formats; @@ -479,6 +480,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) updateDisplayText(/*force*/ true); if (cursorPositionChanged) emitCursorPositionChanged(); + else if (m_preeditCursor != oldPreeditCursor) + emit updateMicroFocus(); if (isGettingInput) finishChange(priorState); } diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bfe50fe..3c505c8 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -425,6 +425,7 @@ Q_SIGNALS: void textEdited(const QString &); void resetInputContext(); + void updateMicroFocus(); void accepted(); void editingFinished(); diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index d3af9e1..7435691 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -967,7 +967,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() ++lineNumber; } if (lineNumber < layoutLineCount) - visibleFromBottom += (layoutLineCount - lineNumber - 1); + visibleFromBottom += (layoutLineCount - lineNumber); break; } diff --git a/src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp b/src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp index d5726c1..9fe01bf 100644 --- a/src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp +++ b/src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp @@ -365,7 +365,7 @@ void QDeclarativeFolderListModel::refresh() { d->folderIndex = QModelIndex(); if (d->count) { - emit beginRemoveRows(QModelIndex(), 0, d->count); + emit beginRemoveRows(QModelIndex(), 0, d->count-1); d->count = 0; emit endRemoveRows(); } diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp index 1b6e723..c2a2e98 100644 --- a/src/imports/gestures/qdeclarativegesturearea.cpp +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -89,6 +89,10 @@ public: \warning Elements in the Qt.labs module are not guaranteed to remain compatible in future versions. + \warning GestureArea is an experimental element whose development has + been discontinued. PinchArea is available in QtQuick 1.1 and handles + two finger gesture input. + \note This element is only functional on devices with touch input. \qml diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index ea7cd9f..5db7099 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -436,8 +436,8 @@ void QAudioOutputPrivate::writePaddingData() unsigned char *ptr = const_cast<unsigned char*>(outputBuffer.Ptr()); Mem::FillZ(ptr, paddingBytes); outputBuffer.SetLength(outputBuffer.Length() + paddingBytes); + Q_ASSERT(m_bytesPadding >= paddingBytes); m_bytesPadding -= paddingBytes; - Q_ASSERT(m_bytesPadding >= 0); if (m_pullMode && m_source->atEnd()) lastBufferFilled(); diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 70ea5c2..c2a6925 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -359,7 +359,7 @@ void QNetworkCookie::setValue(const QByteArray &value) } // ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend -static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &position) +static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &position, bool isNameValue) { // format is one of: // (1) token @@ -394,13 +394,22 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) // qdtext = <any TEXT except <">> // quoted-pair = "\" CHAR + + // If its NAME=VALUE, retain the value as is + // refer to ttp://bugreports.qt.nokia.com/browse/QTBUG-17746 + if (isNameValue) + second += '"'; ++i; while (i < length) { register char c = text.at(i); if (c == '"') { // end of quoted text + if (isNameValue) + second += '"'; break; } else if (c == '\\') { + if (isNameValue) + second += '\\'; ++i; if (i >= length) // broken line @@ -476,10 +485,12 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const result = d->name; result += '='; - if (d->value.contains(';') || + if ((d->value.contains(';') || d->value.contains(',') || d->value.contains(' ') || - d->value.contains('"')) { + d->value.contains('"')) && + (!d->value.startsWith('"') && + !d->value.endsWith('"'))) { result += '"'; QByteArray value = d->value; @@ -947,7 +958,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt QNetworkCookie cookie; // The first part is always the "NAME=VALUE" part - QPair<QByteArray,QByteArray> field = nextField(cookieString, position); + QPair<QByteArray,QByteArray> field = nextField(cookieString, position, true); if (field.first.isEmpty() || field.second.isNull()) // parsing error break; @@ -965,7 +976,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt case ';': // new field in the cookie - field = nextField(cookieString, position); + field = nextField(cookieString, position, false); field.first = field.first.toLower(); // everything but the NAME=VALUE is case-insensitive if (field.first == "expires") { diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 89f7d44..7eec24e 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -529,8 +529,9 @@ QSslConfiguration QNetworkRequest::sslConfiguration() const /*! Sets this network request's SSL configuration to be \a config. The settings that apply are the private key, the local certificate, - the SSL protocol (SSLv2, SSLv3, TLSv1 where applicable) and the - ciphers that the SSL backend is allowed to use. + the SSL protocol (SSLv2, SSLv3, TLSv1 where applicable), the CA + certificates and the ciphers that the SSL backend is allowed to + use. By default, no SSL configuration is set, which allows the backends to choose freely what configuration is best for them. diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index 0e3c519..dc4e4f7 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -57,16 +57,17 @@ QT_BEGIN_NAMESPACE { \ delete this_##NAME.pointer; \ this_##NAME.pointer = 0; \ - this_##NAME.destroyed = true; \ } \ static TYPE *NAME() \ { \ - if (!this_##NAME.pointer && !this_##NAME.destroyed) { \ + if (!this_##NAME.pointer) { \ TYPE *x = new TYPE; \ if (!this_##NAME.pointer.testAndSetOrdered(0, x)) \ delete x; \ - else \ + else { \ qAddPostRoutine(NAME##_cleanup); \ + this_##NAME.pointer->updateConfigurations(); \ + } \ } \ return this_##NAME.pointer; \ } @@ -75,15 +76,7 @@ Q_GLOBAL_STATIC_QAPP_DESTRUCTION(QNetworkConfigurationManagerPrivate, connManage QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() { - static bool initialized = false; - - QNetworkConfigurationManagerPrivate *m = connManager(); - if (!initialized) { - initialized = true; - m->updateConfigurations(); - } - - return m; + return connManager(); } /*! diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index e107c62..ee28e64 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -141,13 +141,12 @@ private: #ifndef QT_MOBILITY_BEARER QT_END_NAMESPACE +Q_DECLARE_METATYPE(QNetworkSession::State) +Q_DECLARE_METATYPE(QNetworkSession::SessionError) #else QTM_END_NAMESPACE #endif -Q_DECLARE_METATYPE(QNetworkSession::State) -Q_DECLARE_METATYPE(QNetworkSession::SessionError) - QT_END_HEADER #endif // QT_NO_BEARERMANAGEMENT diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index 51b3a32..28ca173 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 7d21bd3..84e14ff 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -780,6 +780,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates() systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der)); } } + CFRelease(cfCerts); } else { // no detailed error handling here diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp index 82b66f5..a9e2248 100644 --- a/src/opengl/qgl_symbian.cpp +++ b/src/opengl/qgl_symbian.cpp @@ -44,12 +44,14 @@ #include <coemain.h> #include <coecntrl.h> #include <w32std.h> +#include <private/qt_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qimagepixmapcleanuphooks_p.h> #include <private/qgl_p.h> #include <private/qpaintengine_opengl_p.h> #include <private/qwidget_p.h> // to access QWExtra #include "qgl_egl_p.h" +#include "qpixmapdata_gl_p.h" #include "qcolormap.h" #include <QDebug> @@ -358,5 +360,117 @@ void QGLWidgetPrivate::recreateEglSurface() eglSurfaceWindowId = currentId; } +/* + * Symbian specific QGLPixmapData functions + */ + +static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) +{ + CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + if (!copy) + return 0; + + if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { + delete copy; + copy = 0; + + return 0; + } + + CFbsBitmapDevice* bitmapDevice = 0; + CFbsBitGc *bitmapGc = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy)); + QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); + bitmapGc->Activate(bitmapDevice); + + bitmapGc->BitBlt(TPoint(), bitmap); + + delete bitmapGc; + delete bitmapDevice; + + return copy; +} + +void QGLPixmapData::fromNativeType(void* pixmap, NativeType type) +{ + if (type == QPixmapData::FbsBitmap) { + CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); + + bool deleteSourceBitmap = false; +#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE + + // Rasterize extended bitmaps + + TUid extendedBitmapType = bitmap->ExtendedBitmapType(); + if (extendedBitmapType != KNullUid) { + bitmap = createBlitCopy(bitmap); + deleteSourceBitmap = true; + } +#endif + + if (bitmap->IsCompressedInRAM()) { + bitmap = createBlitCopy(bitmap); + deleteSourceBitmap = true; + } + + TDisplayMode displayMode = bitmap->DisplayMode(); + QImage::Format format = qt_TDisplayMode2Format(displayMode); + + TSize size = bitmap->SizeInPixels(); + int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode); + + bitmap->BeginDataAccess(); + uchar *bytes = (uchar*)bitmap->DataAddress(); + QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); + img = img.copy(); + bitmap->EndDataAccess(); + + if (displayMode == EGray2) { + //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid + //So invert mono bitmaps so that masks work correctly. + img.invertPixels(); + } else if (displayMode == EColor16M) { + img = img.rgbSwapped(); // EColor16M is BGR + } + + fromImage(img, Qt::AutoColor); + + if (deleteSourceBitmap) + delete bitmap; + } +} + +void* QGLPixmapData::toNativeType(NativeType type) +{ + if (type == QPixmapData::FbsBitmap) { + CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + + if (bitmap) { + QImage image = toImage(); + + TDisplayMode displayMode(EColor16MU); + if (image.format()==QImage::Format_ARGB32_Premultiplied) + displayMode = EColor16MAP; + + if (bitmap->Create(TSize(image.width(), image.height()), + displayMode) == KErrNone) { + const uchar *sptr = const_cast<const QImage&>(image).bits(); + bitmap->BeginDataAccess(); + + uchar *dptr = (uchar*)bitmap->DataAddress(); + Mem::Copy(dptr, sptr, image.byteCount()); + + bitmap->EndDataAccess(); + } else { + delete bitmap; + bitmap = 0; + } + } + + return reinterpret_cast<void*>(bitmap); + } + return 0; +} + QT_END_NAMESPACE diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 43e80c1..70427d5 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -55,10 +55,11 @@ #include <qdesktopwidget.h> #include <qfile.h> #include <qimagereader.h> +#include <qbuffer.h> QT_BEGIN_NAMESPACE -extern QGLWidget* qt_gl_share_widget(); +Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); /*! \class QGLFramebufferObjectPool @@ -369,40 +370,18 @@ void QGLPixmapData::ensureCreated() const void QGLPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags flags) { - if (image.size() == QSize(w, h)) - setSerialNumber(++qt_gl_pixmap_serial); - resize(image.width(), image.height()); - - if (pixelType() == BitmapType) { - m_source = image.convertToFormat(QImage::Format_MonoLSB); - - } else { - QImage::Format format = QImage::Format_RGB32; - if (qApp->desktop()->depth() == 16) - format = QImage::Format_RGB16; - - if (image.hasAlphaChannel() - && ((flags & Qt::NoOpaqueDetection) - || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) - format = QImage::Format_ARGB32_Premultiplied;; - - m_source = image.convertToFormat(format); - } - - m_dirty = true; - m_hasFillColor = false; + QImage img = image; + createPixmapForImage(img, flags, false); +} - m_hasAlpha = m_source.hasAlphaChannel(); - w = image.width(); - h = image.height(); - is_null = (w <= 0 || h <= 0); - d = m_source.depth(); +void QGLPixmapData::fromImageReader(QImageReader *imageReader, + Qt::ImageConversionFlags flags) +{ + QImage image = imageReader->read(); + if (image.isNull()) + return; - if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_texture.id); - m_texture.id = 0; - } + createPixmapForImage(image, flags, true); } bool QGLPixmapData::fromFile(const QString &filename, const char *format, @@ -411,31 +390,37 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format, if (pixelType() == QPixmapData::BitmapType) return QPixmapData::fromFile(filename, format, flags); QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) - return false; - QByteArray data = file.peek(64); - bool alpha; - if (m_texture.canBindCompressedTexture - (data.constData(), data.size(), format, &alpha)) { - resize(0, 0); - data = file.readAll(); - file.close(); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QSize size = m_texture.bindCompressedTexture - (data.constData(), data.size(), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QImage(); - m_dirty = isValid(); - return true; + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.peek(64); + bool alpha; + if (m_texture.canBindCompressedTexture + (data.constData(), data.size(), format, &alpha)) { + resize(0, 0); + data = file.readAll(); + file.close(); + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QSize size = m_texture.bindCompressedTexture + (data.constData(), data.size(), format); + if (!size.isEmpty()) { + w = size.width(); + h = size.height(); + is_null = false; + d = 32; + m_hasAlpha = alpha; + m_source = QImage(); + m_dirty = isValid(); + return true; + } + return false; } - return false; } - fromImage(QImageReader(&file, format).read(), flags); + + QImage image = QImageReader(filename, format).read(); + if (image.isNull()) + return false; + + createPixmapForImage(image, flags, true); + return !isNull(); } @@ -459,7 +444,67 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, return true; } } - return QPixmapData::fromData(buffer, len, format, flags); + + QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); + QBuffer b(&a); + b.open(QIODevice::ReadOnly); + QImage image = QImageReader(&b, format).read(); + if (image.isNull()) + return false; + + createPixmapForImage(image, flags, true); + + return !isNull(); +} + +/*! + out-of-place conversion (inPlace == false) will always detach() + */ +void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) +{ + if (image.size() == QSize(w, h)) + setSerialNumber(++qt_gl_pixmap_serial); + + resize(image.width(), image.height()); + + if (pixelType() == BitmapType) { + m_source = image.convertToFormat(QImage::Format_MonoLSB); + + } else { + QImage::Format format = QImage::Format_RGB32; + if (qApp->desktop()->depth() == 16) + format = QImage::Format_RGB16; + + if (image.hasAlphaChannel() + && ((flags & Qt::NoOpaqueDetection) + || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) + format = QImage::Format_ARGB32_Premultiplied;; + + if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { + m_source = image; + } else { + m_source = image.convertToFormat(format); + + // convertToFormat won't detach the image if format stays the same. + if (image.format() == format) + m_source.detach(); + } + } + + m_dirty = true; + m_hasFillColor = false; + + m_hasAlpha = m_source.hasAlphaChannel(); + w = image.width(); + h = image.height(); + is_null = (w <= 0 || h <= 0); + d = m_source.depth(); + + if (m_texture.id) { + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; + } } bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 5545d3c..a4066fd 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -107,6 +107,8 @@ public: // Re-implemented from QPixmapData: void resize(int width, int height); void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + void fromImageReader(QImageReader *imageReader, + Qt::ImageConversionFlags flags); bool fromFile(const QString &filename, const char *format, Qt::ImageConversionFlags flags); bool fromData(const uchar *buffer, uint len, const char *format, @@ -127,6 +129,11 @@ public: GLuint bind(bool copyBack = true) const; QGLTexture *texture() const; +#if defined(Q_OS_SYMBIAN) + void* toNativeType(NativeType type); + void fromNativeType(void* pixmap, NativeType type); +#endif + private: bool isValid() const; @@ -149,6 +156,8 @@ private: QImage fillImage(const QColor &color) const; + void createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace); + mutable QGLFramebufferObject *m_renderFbo; mutable QPaintEngine *m_engine; mutable QGLContext *m_ctx; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index aad12d7..0bffbda 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -776,32 +776,60 @@ void QGLWindowSurface::updateGeometry() { return; d_ptr->geometry_updated = false; - QRect rect = geometry(); - hijackWindow(window()); - QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); + bool hijack(true); + QWidgetPrivate *wd = window()->d_func(); + if (wd->extraData() && wd->extraData()->glContext) + hijack = false; // we already have gl context for widget + + if (hijack) + hijackWindow(window()); + + QGLContext *ctx = reinterpret_cast<QGLContext *>(wd->extraData()->glContext); #ifdef Q_WS_MAC ctx->updatePaintDevice(); #endif - const GLenum target = GL_TEXTURE_2D; + QSize surfSize = geometry().size(); - if (rect.width() <= 0 || rect.height() <= 0) + if (surfSize.width() <= 0 || surfSize.height() <= 0) return; - if (d_ptr->size == rect.size()) + if (d_ptr->size == surfSize) return; - d_ptr->size = rect.size(); + d_ptr->size = surfSize; + +#ifdef Q_OS_SYMBIAN + if (!hijack) { // Symbian needs to recreate EGL surface when native window size changes + if (ctx->d_func()->eglSurface != EGL_NO_SURFACE) { + eglDestroySurface(ctx->d_func()->eglContext->display(), + ctx->d_func()->eglSurface); + } + + ctx->d_func()->eglSurface = QEgl::createSurface(ctx->device(), + ctx->d_func()->eglContext->config()); + +#if !defined(QGL_NO_PRESERVED_SWAP) + eglGetError(); // Clear error state first. + eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + if (eglGetError() != EGL_SUCCESS) { + qWarning("QGLWindowSurface: could not restore preserved swap behaviour"); + } +#endif + } +#endif if (d_ptr->ctx) { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif return; } + const GLenum target = GL_TEXTURE_2D; if (d_ptr->destructive_swap_buffers && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject) && (d_ptr->fbo || !d_ptr->tried_fbo) @@ -820,10 +848,10 @@ void QGLWindowSurface::updateGeometry() { if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) format.setSamples(8); - d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + d_ptr->fbo = new QGLFramebufferObject(surfSize, format); if (d_ptr->fbo->isValid()) { - qDebug() << "Created Window Surface FBO" << rect.size() + qDebug() << "Created Window Surface FBO" << surfSize << "with samples" << d_ptr->fbo->format().samples(); return; } else { @@ -844,7 +872,7 @@ void QGLWindowSurface::updateGeometry() { delete d_ptr->pb; - d_ptr->pb = new QGLPixelBuffer(rect.width(), rect.height(), + d_ptr->pb = new QGLPixelBuffer(surfSize.width(), surfSize.height(), QGLFormat(QGL::SampleBuffers | QGL::StencilBuffer | QGL::DepthBuffer), qt_gl_share_widget()); @@ -854,7 +882,7 @@ void QGLWindowSurface::updateGeometry() { glGenTextures(1, &d_ptr->pb_tex_id); glBindTexture(target, d_ptr->pb_tex_id); - glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -878,7 +906,7 @@ void QGLWindowSurface::updateGeometry() { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;; diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index a15f0c3..f0f198f 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -2201,6 +2201,12 @@ void QVGPaintEngine::updateScissor() #if defined(QVG_SCISSOR_CLIP) // Using the scissor to do clipping, so combine the systemClip // with the current painting clipRegion. + + if (d->maskValid) { + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + } + QVGPainterState *s = state(); if (s->clipEnabled) { if (region.isEmpty()) @@ -2250,8 +2256,33 @@ void QVGPaintEngine::updateScissor() QVector<QRect> rects = region.rects(); int count = rects.count(); - if (count > d->maxScissorRects) - count = d->maxScissorRects; + if (count > d->maxScissorRects) { +#if !defined(QVG_SCISSOR_CLIP) + count = d->maxScissorRects; +#else + // Use masking + int width = paintDevice()->width(); + int height = paintDevice()->height(); + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, + 0, 0, width, height); + for (int i = 0; i < rects.size(); ++i) { + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, + rects[i].x(), height - rects[i].y() - rects[i].height(), + rects[i].width(), rects[i].height()); + } + + vgSeti(VG_SCISSORING, VG_FALSE); + vgSeti(VG_MASKING, VG_TRUE); + d->maskValid = true; + d->maskIsSet = false; + d->scissorMask = false; + d->scissorActive = false; + d->scissorDirty = false; + d->scissorRegion = region; + return; +#endif + } + QVarLengthArray<VGint> params(count * 4); int height = paintDevice()->height(); for (int i = 0; i < count; ++i) { @@ -3103,9 +3134,13 @@ void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF if (pm.size().width() <= screenSize.width() && pm.size().height() <= screenSize.height()) vgpd->failedToAlloc = false; - } - drawImage(r, *(pd->buffer()), sr, Qt::AutoColor); + vgpd->source.beginDataAccess(); + drawImage(r, vgpd->source.imageRef(), sr, Qt::AutoColor); + vgpd->source.endDataAccess(true); + } else { + drawImage(r, *(pd->buffer()), sr, Qt::AutoColor); + } } void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) @@ -3131,9 +3166,13 @@ void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) if (pm.size().width() <= screenSize.width() && pm.size().height() <= screenSize.height()) vgpd->failedToAlloc = false; - } - drawImage(pos, *(pd->buffer())); + vgpd->source.beginDataAccess(); + drawImage(pos, vgpd->source.imageRef()); + vgpd->source.endDataAccess(); + } else { + drawImage(pos, *(pd->buffer())); + } } void QVGPaintEngine::drawImage diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 85583cc..1e9103b 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -class QFixedPoint; +struct QFixedPoint; class QVGPaintEnginePrivate; class QPixmapData; class QVGEGLWindowSurfacePrivate; diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index 732b484..3f67c79 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -50,6 +50,7 @@ #include <QBuffer> #include <QImageReader> #include <QtGui/private/qimage_p.h> +#include <QtGui/private/qnativeimagehandleprovider_p.h> QT_BEGIN_NAMESPACE @@ -66,11 +67,15 @@ QVGPixmapData::QVGPixmapData(PixelType type) inImagePool = false; inLRU = false; failedToAlloc = false; +#if defined(Q_OS_SYMBIAN) + nativeImageHandleProvider = 0; + nativeImageHandle = 0; +#endif #if !defined(QT_NO_EGL) context = 0; qt_vg_register_pixmap(this); #endif - setSerialNumber(++qt_vg_pixmap_serial); + updateSerial(); } QVGPixmapData::~QVGPixmapData() @@ -98,6 +103,10 @@ void QVGPixmapData::destroyImages() vgImage = VG_INVALID_HANDLE; vgImageOpacity = VG_INVALID_HANDLE; inImagePool = false; + +#if defined(Q_OS_SYMBIAN) + releaseNativeImageHandle(); +#endif } void QVGPixmapData::destroyImageAndContext() @@ -105,6 +114,8 @@ void QVGPixmapData::destroyImageAndContext() if (vgImage != VG_INVALID_HANDLE) { // We need to have a context current to destroy the image. #if !defined(QT_NO_EGL) + if (!context) + context = qt_vg_create_context(0, QInternal::Pixmap); if (context->isCurrent()) { destroyImages(); } else { @@ -118,6 +129,10 @@ void QVGPixmapData::destroyImageAndContext() #else destroyImages(); #endif + } else { +#if defined(Q_OS_SYMBIAN) + releaseNativeImageHandle(); +#endif } #if !defined(QT_NO_EGL) if (context) { @@ -138,25 +153,31 @@ bool QVGPixmapData::isValid() const return (w > 0 && h > 0); } +void QVGPixmapData::updateSerial() +{ + setSerialNumber(++qt_vg_pixmap_serial); +} + void QVGPixmapData::resize(int wid, int ht) { - if (w == wid && h == ht) + if (w == wid && h == ht) { + updateSerial(); return; + } w = wid; h = ht; d = 32; // We always use ARGB_Premultiplied for VG pixmaps. is_null = (w <= 0 || h <= 0); - source = QImage(); + source = QVolatileImage(); recreate = true; - setSerialNumber(++qt_vg_pixmap_serial); + updateSerial(); } -void QVGPixmapData::fromImage - (const QImage &image, Qt::ImageConversionFlags flags) +void QVGPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags flags) { - if(image.isNull()) + if (image.isNull()) return; QImage img = image; @@ -200,33 +221,34 @@ bool QVGPixmapData::fromData(const uchar *buffer, uint len, const char *format, return !isNull(); } -/*! - out-of-place conversion (inPlace == false) will always detach() - */ -void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) +QImage::Format QVGPixmapData::idealFormat(QImage *image, Qt::ImageConversionFlags flags) const { - if (image.size() == QSize(w, h)) - setSerialNumber(++qt_vg_pixmap_serial); - else - resize(image.width(), image.height()); - QImage::Format format = sourceFormat(); - int d = image.depth(); - if (d == 1 || d == 16 || d == 24 || (d == 32 && !image.hasAlphaChannel())) + int d = image->depth(); + if (d == 1 || d == 16 || d == 24 || (d == 32 && !image->hasAlphaChannel())) format = QImage::Format_RGB32; - else if (!(flags & Qt::NoOpaqueDetection) && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) + else if (!(flags & Qt::NoOpaqueDetection) && image->data_ptr()->checkForAlphaPixels()) format = sourceFormat(); else - format = image.hasAlphaChannel() ? sourceFormat() : QImage::Format_RGB32; + format = image->hasAlphaChannel() ? sourceFormat() : QImage::Format_RGB32; + return format; +} + +void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) +{ + resize(image.width(), image.height()); + + QImage::Format format = idealFormat(&image, flags); if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { - source = image; + source = QVolatileImage(image); } else { - source = image.convertToFormat(format); - - // convertToFormat won't detach the image if format stays the same. - if (image.format() == format) - source.detach(); + QImage convertedImage = image.convertToFormat(format); + // convertToFormat won't detach the image if format stays the + // same. Detaching is needed to prevent issues with painting + // onto this QPixmap later on. + convertedImage.detach(); + source = QVolatileImage(convertedImage); } recreate = true; @@ -236,27 +258,23 @@ void QVGPixmapData::fill(const QColor &color) { if (!isValid()) return; - - if (source.isNull()) - source = QImage(w, h, sourceFormat()); - + forceToImage(); if (source.depth() == 1) { // Pick the best approximate color in the image's colortable. int gray = qGray(color.rgba()); - if (qAbs(qGray(source.color(0)) - gray) < qAbs(qGray(source.color(1)) - gray)) + if (qAbs(qGray(source.imageRef().color(0)) - gray) + < qAbs(qGray(source.imageRef().color(1)) - gray)) source.fill(0); else source.fill(1); } else { source.fill(PREMUL(color.rgba())); } - - // Re-upload the image to VG the next time toVGImage() is called. - recreate = true; } bool QVGPixmapData::hasAlphaChannel() const { + ensureReadback(true); if (!source.isNull()) return source.hasAlphaChannel(); else @@ -265,27 +283,52 @@ bool QVGPixmapData::hasAlphaChannel() const void QVGPixmapData::setAlphaChannel(const QPixmap &alphaChannel) { + if (!isValid()) + return; forceToImage(); - source.setAlphaChannel(alphaChannel.toImage()); + source.setAlphaChannel(alphaChannel); } QImage QVGPixmapData::toImage() const { if (!isValid()) return QImage(); - + ensureReadback(true); if (source.isNull()) { - source = QImage(w, h, sourceFormat()); + source = QVolatileImage(w, h, sourceFormat()); recreate = true; } + return source.toImage(); +} - return source; +void QVGPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + // toImage() is potentially expensive with QVolatileImage so provide a + // more efficient implementation of copy() that does not rely on it. + if (!data) { + return; + } + if (data->classId() != OpenVGClass) { + fromImage(data->toImage(rect), Qt::NoOpaqueDetection); + return; + } + const QVGPixmapData *pd = static_cast<const QVGPixmapData *>(data); + QRect r = rect; + if (r.isNull() || r.contains(QRect(0, 0, pd->w, pd->h))) { + r = QRect(0, 0, pd->w, pd->h); + } + resize(r.width(), r.height()); + recreate = true; + if (!pd->source.isNull()) { + source = QVolatileImage(r.width(), r.height(), pd->source.format()); + source.copyFrom(&pd->source, r); + } } QImage *QVGPixmapData::buffer() { - forceToImage(); - return &source; + // Cannot be safely implemented and QVGPixmapData is not (must not be) RasterClass anyway. + return 0; } QPaintEngine* QVGPixmapData::paintEngine() const @@ -313,6 +356,12 @@ VGImage QVGPixmapData::toVGImage() else if (recreate) cachedOpacity = -1.0f; // Force opacity image to be refreshed later. +#if defined(Q_OS_SYMBIAN) + if (recreate && nativeImageHandleProvider && !nativeImageHandle) { + createFromNativeImageHandleProvider(); + } +#endif + if (vgImage == VG_INVALID_HANDLE) { vgImage = QVGImagePool::instance()->createImageForPixmap (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this); @@ -329,10 +378,12 @@ VGImage QVGPixmapData::toVGImage() } if (!source.isNull() && recreate) { + source.beginDataAccess(); vgImageSubData (vgImage, source.constBits(), source.bytesPerLine(), qt_vg_image_to_vg_format(source.format()), 0, 0, w, h); + source.endDataAccess(true); } recreate = false; @@ -395,9 +446,16 @@ void QVGPixmapData::detachImageFromPool() void QVGPixmapData::hibernate() { - // If the image was imported (e.g, from an SgImage under Symbian), - // then we cannot copy it back to main memory for storage. - if (vgImage != VG_INVALID_HANDLE && source.isNull()) + // If the image was imported (e.g, from an SgImage under Symbian), then + // skip the hibernation, there is no sense in copying it back to main + // memory because the data is most likely shared between several processes. + bool skipHibernate = (vgImage != VG_INVALID_HANDLE && source.isNull()); +#if defined(Q_OS_SYMBIAN) + // However we have to proceed normally if the image was retrieved via + // a handle provider. + skipHibernate &= !nativeImageHandleProvider; +#endif + if (skipHibernate) return; forceToImage(); @@ -442,18 +500,47 @@ int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const } } -// Force the pixmap data to be in QImage format. +// Ensures that the pixmap is backed by some valid data and forces the data to +// be re-uploaded to the VGImage when toVGImage() is called next time. void QVGPixmapData::forceToImage() { if (!isValid()) return; + ensureReadback(false); + if (source.isNull()) - source = QImage(w, h, sourceFormat()); + source = QVolatileImage(w, h, sourceFormat()); recreate = true; } +void QVGPixmapData::ensureReadback(bool readOnly) const +{ + if (vgImage != VG_INVALID_HANDLE && source.isNull()) { + source = QVolatileImage(w, h, sourceFormat()); + source.beginDataAccess(); + vgGetImageSubData(vgImage, source.bits(), source.bytesPerLine(), + qt_vg_image_to_vg_format(source.format()), + 0, 0, w, h); + source.endDataAccess(); + if (readOnly) { + recreate = false; + } else { + // Once we did a readback, the original VGImage must be destroyed + // because it may be shared (e.g. created via SgImage) and a subsequent + // upload of the image data may produce unexpected results. + const_cast<QVGPixmapData *>(this)->destroyImages(); +#if defined(Q_OS_SYMBIAN) + // There is now an own copy of the data so drop the handle provider, + // otherwise toVGImage() would request the handle again, which is wrong. + nativeImageHandleProvider = 0; +#endif + recreate = true; + } + } +} + QImage::Format QVGPixmapData::sourceFormat() const { return QImage::Format_ARGB32_Premultiplied; diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h index 58e69db..15ff889 100644 --- a/src/openvg/qpixmapdata_vg_p.h +++ b/src/openvg/qpixmapdata_vg_p.h @@ -54,7 +54,8 @@ // #include <QtGui/private/qpixmap_raster_p.h> -#include <private/qvg_p.h> +#include <QtGui/private/qvolatileimage_p.h> +#include "qvg_p.h" #if defined(Q_OS_SYMBIAN) class RSGImage; @@ -75,6 +76,8 @@ void qt_vg_unregister_pixmap(QVGPixmapData *pd); void qt_vg_hibernate_pixmaps(QVGSharedContext *context); #endif +class QNativeImageHandleProvider; + class Q_OPENVG_EXPORT QVGPixmapData : public QPixmapData { public: @@ -99,6 +102,7 @@ public: bool hasAlphaChannel() const; void setAlphaChannel(const QPixmap &alphaChannel); QImage toImage() const; + void copy(const QPixmapData *data, const QRect &rect); QImage *buffer(); QPaintEngine* paintEngine() const; @@ -124,11 +128,21 @@ public: // VGImage objects to reuse storage. virtual void reclaimImages(); + // If vgImage is valid but source is null, copies pixel data from GPU back + // into main memory and destroys vgImage. For a normal pixmap this function + // does nothing, however if the pixmap was created directly from a VGImage + // (e.g. via SgImage on Symbian) then by doing the readback this ensures + // that QImage-based functions can operate too. + virtual void ensureReadback(bool readOnly) const; + QSize size() const { return QSize(w, h); } #if defined(Q_OS_SYMBIAN) void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); + bool initFromNativeImageHandle(void *handle, const QString &type); + void createFromNativeImageHandleProvider(); + void releaseNativeImageHandle(); #endif protected: @@ -161,15 +175,23 @@ protected: VGImage vgImage; VGImage vgImageOpacity; qreal cachedOpacity; - mutable QImage source; + mutable QVolatileImage source; mutable bool recreate; bool inImagePool; #if !defined(QT_NO_EGL) mutable QEglContext *context; #endif +#if defined(Q_OS_SYMBIAN) + mutable QNativeImageHandleProvider *nativeImageHandleProvider; + void *nativeImageHandle; + QString nativeImageType; +#endif + void forceToImage(); QImage::Format sourceFormat() const; + QImage::Format idealFormat(QImage *image, Qt::ImageConversionFlags flags) const; + void updateSerial(); void destroyImageAndContext(); void destroyImages(); diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 2ea38c1..5eb64bd 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -41,10 +41,10 @@ #include "qpixmapdata_vg_p.h" #include "qvgfontglyphcache_p.h" +#include <QtGui/private/qnativeimagehandleprovider_p.h> #include <private/qt_s60_p.h> #include <fbs.h> -#include <bitdev.h> #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE # include <sgresource/sgimage.h> @@ -75,33 +75,6 @@ VGImage QVG::vgCreateEGLImageTargetKHR(VGeglImageKHR eglImage) extern int qt_vg_pixmap_serial; -static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) -{ - CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); - if(!copy) - return 0; - - if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { - delete copy; - copy = 0; - - return 0; - } - - CFbsBitmapDevice* bitmapDevice = 0; - CFbsBitGc *bitmapGc = 0; - QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy)); - QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); - bitmapGc->Activate(bitmapDevice); - - bitmapGc->BitBlt(TPoint(), bitmap); - - delete bitmapGc; - delete bitmapDevice; - - return copy; -} - #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE static VGImage sgImageToVGImage(QEglContext *context, const RSgImage &sgImage) { @@ -136,7 +109,45 @@ void QVGPixmapData::cleanup() { is_null = w = h = 0; recreate = false; - source = QImage(); + source = QVolatileImage(); +} + +bool QVGPixmapData::initFromNativeImageHandle(void *handle, const QString &type) +{ + if (type == QLatin1String("RSgImage")) { + fromNativeType(handle, QPixmapData::SgImage); + return true; + } else if (type == QLatin1String("CFbsBitmap")) { + fromNativeType(handle, QPixmapData::FbsBitmap); + return true; + } + return false; +} + +void QVGPixmapData::createFromNativeImageHandleProvider() +{ + void *handle = 0; + QString type; + nativeImageHandleProvider->get(&handle, &type); + if (handle) { + if (initFromNativeImageHandle(handle, type)) { + nativeImageHandle = handle; + nativeImageType = type; + } else { + qWarning("QVGPixmapData: Unknown native image type '%s'", qPrintable(type)); + } + } else { + qWarning("QVGPixmapData: Native handle is null"); + } +} + +void QVGPixmapData::releaseNativeImageHandle() +{ + if (nativeImageHandleProvider && nativeImageHandle) { + nativeImageHandleProvider->release(nativeImageHandle, nativeImageType); + nativeImageHandle = 0; + nativeImageType = QString(); + } } void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) @@ -155,55 +166,33 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) } is_null = (w <= 0 || h <= 0); - source = QImage(); // vgGetImageSubData() some day? + source = QVolatileImage(); // readback will be done later, only when needed recreate = false; prevSize = QSize(w, h); - //setSerialNumber(++qt_vg_pixmap_serial); -#endif - } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); - - bool deleteSourceBitmap = false; -#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE - - // Rasterize extended bitmaps - - TUid extendedBitmapType = bitmap->ExtendedBitmapType(); - if (extendedBitmapType != KNullUid) { - bitmap = createBlitCopy(bitmap); - deleteSourceBitmap = true; - } + updateSerial(); #endif - - if (bitmap->IsCompressedInRAM()) { - bitmap = createBlitCopy(bitmap); - deleteSourceBitmap = true; - } - - TDisplayMode displayMode = bitmap->DisplayMode(); - QImage::Format format = qt_TDisplayMode2Format(displayMode); - - TSize size = bitmap->SizeInPixels(); - int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode); - - bitmap->BeginDataAccess(); - uchar *bytes = (uchar*)bitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); - img = img.copy(); - bitmap->EndDataAccess(); - - if(displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - img.invertPixels(); - } else if(displayMode == EColor16M) { - img = img.rgbSwapped(); // EColor16M is BGR - } - - fromImage(img, Qt::AutoColor); - - if(deleteSourceBitmap) - delete bitmap; + } else if (type == QPixmapData::FbsBitmap && pixmap) { + CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap); + QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight); + resize(size.width(), size.height()); + source = QVolatileImage(bitmap); // duplicates only, if possible + if (source.isNull()) + return; + // Here we may need to copy if the formats do not match. + // (e.g. for display modes other than EColor16MAP and EColor16MU) + source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor)); + recreate = true; + } else if (type == QPixmapData::VolatileImage && pixmap) { + QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); + resize(img->width(), img->height()); + source = *img; + source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor)); + recreate = true; + } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) { + destroyImages(); + nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap); + // Cannot defer the retrieval, we need at least the size right away. + createFromNativeImageHandleProvider(); } } @@ -270,26 +259,15 @@ void* QVGPixmapData::toNativeType(NativeType type) driver.Close(); return reinterpret_cast<void*>(sgImage.take()); #endif - } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); - - if (bitmap) { - if (bitmap->Create(TSize(source.width(), source.height()), - EColor16MAP) == KErrNone) { - const uchar *sptr = const_cast<const QImage&>(source).bits(); - bitmap->BeginDataAccess(); - - uchar *dptr = (uchar*)bitmap->DataAddress(); - Mem::Copy(dptr, sptr, source.byteCount()); - - bitmap->EndDataAccess(); - } else { - delete bitmap; - bitmap = 0; - } + } else if (type == QPixmapData::FbsBitmap && isValid()) { + ensureReadback(true); + if (source.isNull()) { + source = QVolatileImage(w, h, sourceFormat()); } - - return reinterpret_cast<void*>(bitmap); + // Just duplicate the bitmap handle, no data copying happens. + return source.duplicateNativeImage(); + } else if (type == QPixmapData::VolatileImage) { + return &source; } return 0; } diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index 9a105ec..ce12301 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -56,7 +56,7 @@ #include <QtCore/qvarlengtharray.h> #include <QtGui/private/qfontengine_p.h> -#include <qvg_p.h> +#include "qvg_p.h" QT_BEGIN_NAMESPACE diff --git a/src/openvg/qvgimagepool.cpp b/src/openvg/qvgimagepool.cpp index a2b1c4e..7a7ec78 100644 --- a/src/openvg/qvgimagepool.cpp +++ b/src/openvg/qvgimagepool.cpp @@ -175,8 +175,19 @@ bool QVGImagePool::reclaimSpace(VGImageFormat format, void QVGImagePool::hibernate() { - // Nothing to do here at the moment since the pool does not - // retain VGImage's after they have been released. + Q_D(QVGImagePool); + QVGPixmapData *pd = d->lruLast; + while (pd) { + QVGPixmapData *prevLRU = pd->prevLRU; + pd->inImagePool = false; + pd->inLRU = false; + pd->nextLRU = 0; + pd->prevLRU = 0; + pd->hibernate(); + pd = prevLRU; + } + d->lruFirst = 0; + d->lruLast = 0; } void QVGImagePool::moveToHeadOfLRU(QVGPixmapData *data) diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp index c6db869..866453f 100644 --- a/src/openvg/qwindowsurface_vgegl.cpp +++ b/src/openvg/qwindowsurface_vgegl.cpp @@ -267,10 +267,7 @@ static QEglContext *createContext(QPaintDevice *device) int redSize = configProps.value(EGL_RED_SIZE); if (redSize == EGL_DONT_CARE || redSize == 0) configProps.setPixelFormat(QImage::Format_ARGB32); // XXX -#ifndef QVG_SCISSOR_CLIP - // If we are using the mask to clip, then explicitly request a mask. configProps.setValue(EGL_ALPHA_MASK_SIZE, 1); -#endif #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT); @@ -771,6 +768,11 @@ bool QVGEGLWindowSurfaceDirect::scroll(QWidget *widget, const QRegion& area, int context->lazyDoneCurrent(); return true; } +#else + Q_UNUSED(widget); + Q_UNUSED(area); + Q_UNUSED(dx); + Q_UNUSED(dy); #endif return false; } diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index 30d6b50..6b37b38 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -213,6 +213,11 @@ void QNetworkManagerEngine::connectToId(const QString &id) dbusDevicePath = devicePath.path(); break; } + else if (device.deviceType() == DEVICE_TYPE_GSM && + connectionType == QLatin1String("gsm")) { + dbusDevicePath = devicePath.path(); + break; + } } const QString service = connection->connectionInterface()->service(); diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index fc480c2..f367c26 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -150,16 +150,15 @@ SymbianEngine::~SymbianEngine() iConnectionMonitor.CancelNotifications(); iConnectionMonitor.Close(); - -#ifdef SNAP_FUNCTIONALITY_AVAILABLE - iCmManager.Close(); -#endif - - // CCommsDatabase destructor uses cleanup stack. Since QNetworkConfigurationManager + + // CCommsDatabase destructor and RCmManager.Close() use cleanup stack. Since QNetworkConfigurationManager // is a global static, but the time we are here, E32Main() has been exited already and // the thread's default cleanup stack has been deleted. Without this line, a // 'E32USER-CBase 69' -panic will occur. CTrapCleanup* cleanup = CTrapCleanup::New(); +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iCmManager.Close(); +#endif delete ipCommsDB; delete cleanup; } @@ -829,6 +828,7 @@ void SymbianEngine::updateStatesToSnaps() discovered = true; } } + snapConfigLocker.unlock(); if (active) { changeConfigurationStateTo(ptr, QNetworkConfiguration::Active); } else if (discovered) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 50e0f5f..eaff74a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -245,10 +245,9 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti QDirectFBPointer<IDirectFBDataBuffer> dataBuffer(dataBufferPtr); IDirectFBImageProvider *providerPtr; - if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) { - DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result); + if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) return false; - } + QDirectFBPointer<IDirectFBImageProvider> provider(providerPtr); DFBImageDescription imageDescription; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 09cc465..ff15078 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1285,7 +1285,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); #elif (Q_DIRECTFB_VERSION >= 0x010000) IDirectFBSurface *layerSurface; - if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) { + if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) == DFB_OK) { result = layerSurface->GetSize(layerSurface, &w, &h); layerSurface->Release(layerSurface); } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index d0056a7..3d8cf50 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) - , sibling(0) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif @@ -75,7 +74,6 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) : QWSWindowSurface(widget), QDirectFBPaintDevice(scr) - , sibling(0) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif @@ -123,7 +121,7 @@ void QDirectFBWindowSurface::raise() IDirectFBWindow *QDirectFBWindowSurface::directFBWindow() const { - return (dfbWindow ? dfbWindow : (sibling ? sibling->dfbWindow : 0)); + return dfbWindow; } void QDirectFBWindowSurface::createWindow(const QRect &rect) @@ -287,17 +285,40 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) QByteArray QDirectFBWindowSurface::permanentState() const { - QByteArray state(sizeof(this), 0); - *reinterpret_cast<const QDirectFBWindowSurface**>(state.data()) = this; + QByteArray state(sizeof(SurfaceFlags) + sizeof(DFBWindowID), 0); + char *ptr = state.data(); + SurfaceFlags flags = surfaceFlags(); + memcpy(ptr, &flags, sizeof(SurfaceFlags)); + ptr += sizeof(SurfaceFlags); + DFBWindowID did = (DFBWindowID)(-1); + if (dfbWindow) + dfbWindow->GetID(dfbWindow, &did); + memcpy(ptr, &did, sizeof(DFBWindowID)); return state; } void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { - if (state.size() == sizeof(this)) { - sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData()); - Q_ASSERT(sibling); - setSurfaceFlags(sibling->surfaceFlags()); + const char *ptr = state.constData(); + IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer(); + SurfaceFlags flags; + memcpy(&flags, ptr, sizeof(SurfaceFlags)); + + setSurfaceFlags(flags); + ptr += sizeof(SurfaceFlags); + DFBWindowID id; + memcpy(&id, ptr, sizeof(DFBWindowID)); + if (dfbSurface) + dfbSurface->Release(dfbSurface); + if (id != (DFBWindowID)-1) { + IDirectFBWindow *dw; + layer->GetWindow(layer, id, &dw); + if (dw->GetSurface(dw, &dfbSurface) != DFB_OK) + dfbSurface = 0; + dw->Release(dw); + } + else { + dfbSurface = 0; } } @@ -406,8 +427,6 @@ void QDirectFBWindowSurface::endPaint(const QRegion &) IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const { - if (!dfbSurface && sibling && sibling->dfbSurface) - return sibling->dfbSurface; return dfbSurface; } @@ -415,11 +434,8 @@ IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const { Q_ASSERT(widget); - if (!dfbSurface) { - if (sibling && (!sibling->sibling || sibling->dfbSurface)) - return sibling->surfaceForWidget(widget, rect); + if (!dfbSurface) return 0; - } QWidget *win = window(); Q_ASSERT(win); if (rect) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index f683fc8..75d462b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -100,7 +100,6 @@ private: void updateIsOpaque(); void setOpaque(bool opaque); void releaseSurface(); - QDirectFBWindowSurface *sibling; #ifdef QT_DIRECTFB_WM void createWindow(const QRect &rect); diff --git a/src/plugins/graphicssystems/meego/dithering.cpp b/src/plugins/graphicssystems/meego/dithering.cpp index 91e3337..2561c22 100644 --- a/src/plugins/graphicssystems/meego/dithering.cpp +++ b/src/plugins/graphicssystems/meego/dithering.cpp @@ -39,15 +39,22 @@ ** ****************************************************************************/ -// This is an implementation of the 32bit => 16bit Floyd-Steinberg dithering. +// Implements two dithering methods: +// +// * convertRGBA32_to_RGB565 +// +// This is implemented using Ordered Bayer Dithering. The code has been adapted +// from QX11PixmapData::fromImage. This method was originally implemented using +// Floyd-Steinberg dithering but was later changed to Ordered Dithering because +// of the better quality of the results. +// +// * convertRGBA32_to_RGBA4444 +// +// This is implemented using Floyd-Steinberg dithering. +// // The alghorithm used here is not the fastest possible but it's prolly fast enough: // uses look-up tables, integer-only arthmetics and works in one pass on two lines // at a time. It's a high-quality dithering using 1/8 diffusion precission. -// Two functions here to look at: -// -// * convertRGBA32_to_RGB565 -// * convertRGBA32_to_RGBA4444 -// // Each channel (RGBA) is diffused independently and alpha is dithered too. #include <string.h> @@ -76,113 +83,63 @@ // Converts incoming RGB32 (QImage::Format_RGB32) to RGB565. Returns the newly allocated data. unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride) { + static bool thresholdMapInitialized = false; + static int thresholdMap[16][16]; + + if (!thresholdMapInitialized) { + int i; + int j; + int n; + + thresholdMap[0][0] = 0; + thresholdMap[1][0] = 2; + thresholdMap[0][1] = 3; + thresholdMap[1][1] = 1; + + for (n=2; n<16; n*=2) { + for (i=0; i<n; i++) { + for (j=0; j<n; j++) { + thresholdMap[i][j] *= 4; + thresholdMap[i+n][j] = thresholdMap[i][j] + 2; + thresholdMap[i][j+n] = thresholdMap[i][j] + 3; + thresholdMap[i+n][j+n] = thresholdMap[i][j] + 1; + } + } + } + + thresholdMapInitialized = true; + } + // Output line stride. Aligned to 4 bytes. int alignedWidth = width; if (alignedWidth % 2 > 0) alignedWidth++; // Will store output - unsigned short *out = (unsigned short *) malloc(alignedWidth * height * 2); - - // Lookup tables for the 8bit => 6bit and 8bit => 5bit conversion - unsigned char lookup_8bit_to_5bit[256]; - short lookup_8bit_to_5bit_diff[256]; - unsigned char lookup_8bit_to_6bit[256]; - short lookup_8bit_to_6bit_diff[256]; - - // Macros for the conversion using the lookup table. - #define CONVERT_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit[v]) - #define DIFF_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit_diff[v]) - - #define CONVERT_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit[v]) - #define DIFF_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit_diff[v]) - - int i; - int x, y, c; // Pixel we're processing. c is component number (0, 1, 2 for r, b, b) - short component[3]; // Stores the new components (r, g, b) for pixel produced during conversion - short diff; // The difference between the converted value and the original one. To be accumulated. - QVarLengthArray <short> accumulatorData(3 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. - short *accumulator[3]; // Helper for accessing the accumulator on a per-channel basis more easily. - accumulator[0] = accumulatorData.data(); - accumulator[1] = accumulatorData.data() + width; - accumulator[2] = accumulatorData.data() + (width * 2); - - // Produce the conversion lookup tables. - for (i = 0; i < 256; i++) { - lookup_8bit_to_5bit[i] = round(i / 8.0); - - // Before bitshifts: (i * 8) - (... * 8 * 8) - lookup_8bit_to_5bit_diff[i] = (i << 3) - (lookup_8bit_to_5bit[i] << 6); - if (lookup_8bit_to_5bit[i] > 31) - lookup_8bit_to_5bit[i] -= 1; - - lookup_8bit_to_6bit[i] = round(i / 4.0); - - // Before bitshifts: (i * 8) - (... * 4 * 8) - lookup_8bit_to_6bit_diff[i] = (i << 3) - (lookup_8bit_to_6bit[i] << 5); - if (lookup_8bit_to_6bit[i] > 63) - lookup_8bit_to_6bit[i] -= 1; - } + unsigned short *out = (unsigned short *)malloc (alignedWidth * height * 2); - // Clear the accumulators - memset(accumulator[0], 0, width * 4); - memset(accumulator[1], 0, width * 4); - memset(accumulator[2], 0, width * 4); + int x; + int y; + int threshold; // For each line... for (y = 0; y < height; y++) { - // For each accumulator, move the second line (index 1) to replace the first line (index 0). - // Clear the second line (index 1) - memcpy(accumulator[0], accumulator[0] + width, width * 2); - memset(accumulator[0] + width, 0, width * 2); - - memcpy(accumulator[1], accumulator[1] + width, width * 2); - memset(accumulator[1] + width, 0, width * 2); - - memcpy(accumulator[2], accumulator[2] + width, width * 2); - memset(accumulator[2] + width, 0, width * 2); - // For each column.... for (x = 0; x < width; x++) { - // For each component (r, g, b)... - for (c = 0; c < 3; c++) { + int r = GET_RGBA_COMPONENT(in, x, y, stride, 0); + int g = GET_RGBA_COMPONENT(in, x, y, stride, 1); + int b = GET_RGBA_COMPONENT(in, x, y, stride, 2); - // Get the 8bit value from the original image - component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); - - // Add the diffusion for this pixel we stored in the accumulator. - // >> 7 because the values in accumulator are stored * 128 - if (x != 0 && x != (width - 1)) { - if (accumulator[c][x] >> 7 != 0) - component[c] += rand() % accumulator[c][x] >> 7; - } - - // Make sure we're not over the boundaries. - CLAMP_256(component[c]); - - // For green component we use 6 bits. Otherwise 5 bits. - // Store the difference from converting 8bit => 6 bit and the orig pixel. - // Convert 8bit => 6(5) bit. - if (c == 1) { - diff = DIFF_8BIT_TO_6BIT(component[c]); - component[c] = CONVERT_8BIT_TO_6BIT(component[c]); - } else { - diff = DIFF_8BIT_TO_5BIT(component[c]); - component[c] = CONVERT_8BIT_TO_5BIT(component[c]); - } + threshold = thresholdMap[x%16][y%16]; - // Distribute the difference according to the matrix in the - // accumulation bufffer. - ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 3); - ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 3); - } + if (r <= (255-(1<<3)) && ((r<<5) & 255) > threshold) r += (1<<3); + if (g <= (255-(1<<2)) && ((g<<6) & 255) > threshold) g += (1<<2); + if (b <= (255-(1<<3)) && ((b<<5) & 255) > threshold) b += (1<<3); // Write the newly produced pixel - PUT_565(out, x, y, alignedWidth, component[2], component[1], component[0]); + PUT_565(out, x, y, alignedWidth, ((b >> 3) & 0x1f), ((g >> 2) & 0x3f), ((r >> 3) & 0x1f)); } } diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index a70d232..13eab7f 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -171,7 +171,7 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handl return QMeeGoGraphicsSystem::wrapPixmapData(pmd); } else { QRasterPixmapData *pmd = new QRasterPixmapData(QPixmapData::PixmapType); - pmd->fromImage(softImage, Qt::NoOpaqueDetection); + pmd->fromImage(softImage, Qt::NoFormatConversion); // Make sure that the image was not converted in any way if (pmd->buffer()->data_ptr()->data != @@ -335,3 +335,8 @@ void qt_meego_destroy_fence_sync(void* fs) { return QMeeGoGraphicsSystem::destroyFenceSync(fs); } + +void qt_meego_invalidate_live_surfaces(void) +{ + return QMeeGoLivePixmapData::invalidateSurfaces(); +} diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 323ce1f..27a4e7a 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -103,6 +103,7 @@ extern "C" { Q_DECL_EXPORT Qt::HANDLE qt_meego_live_texture_get_handle(QPixmap *pixmap); Q_DECL_EXPORT void* qt_meego_create_fence_sync(void); Q_DECL_EXPORT void qt_meego_destroy_fence_sync(void* fs); + Q_DECL_EXPORT void qt_meego_invalidate_live_surfaces(void); } #endif diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp index e4f1900..2a2a098 100644 --- a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp @@ -49,6 +49,8 @@ #include <private/qpixmap_x11_p.h> #include <stdio.h> +static QMeeGoLivePixmapDataList all_live_pixmaps; + static EGLint lock_attribs[] = { EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, @@ -118,21 +120,29 @@ QMeeGoLivePixmapData::QMeeGoLivePixmapData(int w, int h, QImage::Format format) backingX11Pixmap = new QPixmap(pmd); initializeThroughEGLImage(); + + pos = all_live_pixmaps.insert(all_live_pixmaps.begin(), this); } QMeeGoLivePixmapData::QMeeGoLivePixmapData(Qt::HANDLE h) : QGLPixmapData(QPixmapData::PixmapType) { backingX11Pixmap = new QPixmap(QPixmap::fromX11Pixmap(h)); initializeThroughEGLImage(); + + pos = all_live_pixmaps.insert(all_live_pixmaps.begin(), this); } QMeeGoLivePixmapData::~QMeeGoLivePixmapData() { delete backingX11Pixmap; + all_live_pixmaps.erase(pos); } void QMeeGoLivePixmapData::initializeThroughEGLImage() { + if (texture()->id != 0) + return; + QGLShareContextScope ctx(qt_gl_share_widget()->context()); QMeeGoExtensions::ensureInitialized(); @@ -245,6 +255,8 @@ bool QMeeGoLivePixmapData::scroll(int dx, int dy, const QRect &rect) EGLSurface QMeeGoLivePixmapData::getSurfaceForBackingPixmap() { + initializeThroughEGLImage(); + // This code is a crative remix of the stuff that can be found in the // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(backingX11Pixmap->data_ptr().data()); @@ -290,3 +302,12 @@ void QMeeGoLivePixmapData::destroySurfaceForPixmapData(QPixmapData* pmd) pixmapData->gl_surface = 0; } } + +void QMeeGoLivePixmapData::invalidateSurfaces() +{ + foreach (QMeeGoLivePixmapData *data, all_live_pixmaps) { + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(data->backingX11Pixmap->data_ptr().data()); + *data->texture() = QGLTexture(); + pixmapData->gl_surface = 0; + } +} diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h index 484028e..616b33c 100644 --- a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h @@ -42,9 +42,13 @@ #ifndef MLIVEPIXMAPDATA_H #define MLIVEPIXMAPDATA_H +#include <QLinkedList> #include <private/qpixmapdata_gl_p.h> #include "qmeegoextensions.h" +class QMeeGoLivePixmapData; +typedef QLinkedList<QMeeGoLivePixmapData *> QMeeGoLivePixmapDataList; + class QMeeGoLivePixmapData : public QGLPixmapData { public: @@ -66,6 +70,9 @@ public: QPixmap *backingX11Pixmap; QImage lockedImage; + QMeeGoLivePixmapDataList::Iterator pos; + + static void invalidateSurfaces(); }; #endif diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp index 0c107b5..1da58e1 100644 --- a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp +++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp @@ -42,6 +42,7 @@ #include "qgraphicssystem_vg_p.h" #include <QtOpenVG/private/qpixmapdata_vg_p.h> #include <QtOpenVG/private/qwindowsurface_vg_p.h> +#include <QtOpenVG/private/qvgimagepool_p.h> #if defined(Q_OS_SYMBIAN) && !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) #include <QtGui/private/qwidget_p.h> #endif @@ -77,4 +78,9 @@ QWindowSurface *QVGGraphicsSystem::createWindowSurface(QWidget *widget) const return new QVGWindowSurface(widget); } +void QVGGraphicsSystem::releaseCachedResources() +{ + QVGImagePool::instance()->hibernate(); +} + QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h index d1bce28..9c9b3e2 100644 --- a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h +++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h @@ -64,6 +64,8 @@ public: QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QWindowSurface *createWindowSurface(QWidget *widget) const; + + void releaseCachedResources(); }; QT_END_NAMESPACE diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 5aa26d3..701207d 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -559,6 +559,8 @@ QImage ICOReader::iconAt(int index) icoAttrib.ncolors = 0; else // # colors used icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits; + if (icoAttrib.ncolors > 256) //color table can't be more than 256 + return img; icoAttrib.w = iconEntry.bWidth; if (icoAttrib.w == 0) icoAttrib.w = header.biWidth; diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 7cbffe0..3de5fdf 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -1,6 +1,6 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.2 + VERSION=4.7.3 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/qbase.pri b/src/qbase.pri index 3a40928..babea56 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -4,7 +4,7 @@ INCLUDEPATH *= $$QMAKE_INCDIR_QT/$$TARGET #just for today to have some compat isEmpty(QT_ARCH):!isEmpty(ARCH):QT_ARCH=$$ARCH #another compat that will rot for change #215700 TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.2 + VERSION=4.7.3 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } @@ -190,7 +190,7 @@ symbian { # Partial upgrade SIS file vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index 7d0a83e..8b23b63 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -3,7 +3,7 @@ EXPORTS ?setStored@QMetaPropertyBuilder@@QAEX_N@Z @ 2 NONAME ABSENT ; void QMetaPropertyBuilder::setStored(bool) ?trUtf8@QDeclarativeExpression@@SA?AVQString@@PBD0H@Z @ 3 NONAME ; class QString QDeclarativeExpression::trUtf8(char const *, char const *, int) ?qt_metacast@QDeclarativeComponent@@UAEPAXPBD@Z @ 4 NONAME ; void * QDeclarativeComponent::qt_metacast(char const *) - ?name@QDeclarativeDebugService@@QBE?AVQString@@XZ @ 5 NONAME ABSENT ; class QString QDeclarativeDebugService::name(void) const + ?name@QDeclarativeDebugService@@QBE?AVQString@@XZ @ 5 NONAME ; class QString QDeclarativeDebugService::name(void) const ?debugId@QDeclarativeDebugObjectReference@@QBEHXZ @ 6 NONAME ABSENT ; int QDeclarativeDebugObjectReference::debugId(void) const ?addPluginPath@QDeclarativeEngine@@QAEXABVQString@@@Z @ 7 NONAME ; void QDeclarativeEngine::addPluginPath(class QString const &) ?name@QMetaPropertyBuilder@@QBE?AVQByteArray@@XZ @ 8 NONAME ABSENT ; class QByteArray QMetaPropertyBuilder::name(void) const @@ -11,7 +11,7 @@ EXPORTS ?propertyOffset@QDeclarativeOpenMetaObjectType@@QBEHXZ @ 10 NONAME ABSENT ; int QDeclarativeOpenMetaObjectType::propertyOffset(void) const ??0QDeclarativeText@@QAE@PAVQDeclarativeItem@@@Z @ 11 NONAME ABSENT ; QDeclarativeText::QDeclarativeText(class QDeclarativeItem *) ?propertyTypeName@QDeclarativeProperty@@QBEPBDXZ @ 12 NONAME ; char const * QDeclarativeProperty::propertyTypeName(void) const - ?getStaticMetaObject@QDeclarativeDebugService@@SAABUQMetaObject@@XZ @ 13 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugService::getStaticMetaObject(void) + ?getStaticMetaObject@QDeclarativeDebugService@@SAABUQMetaObject@@XZ @ 13 NONAME ; struct QMetaObject const & QDeclarativeDebugService::getStaticMetaObject(void) ?setLeft@QDeclarativeAnchors@@QAEXABVQDeclarativeAnchorLine@@@Z @ 14 NONAME ABSENT ; void QDeclarativeAnchors::setLeft(class QDeclarativeAnchorLine const &) ?qt_metacall@QDeclarativeExpression@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 15 NONAME ; int QDeclarativeExpression::qt_metacall(enum QMetaObject::Call, int, void * *) ?staticMetaObject@QDeclarativePen@@2UQMetaObject@@B @ 16 NONAME ABSENT ; struct QMetaObject const QDeclarativePen::staticMetaObject @@ -145,7 +145,7 @@ EXPORTS ?isConnected@QDeclarativeDebugClient@@QBE_NXZ @ 144 NONAME ABSENT ; bool QDeclarativeDebugClient::isConnected(void) const ?enabled@QDeclarativeBinding@@QBE_NXZ @ 145 NONAME ABSENT ; bool QDeclarativeBinding::enabled(void) const ?setSource@QDeclarativeView@@QAEXABVQUrl@@@Z @ 146 NONAME ; void QDeclarativeView::setSource(class QUrl const &) - ??_EQDeclarativeDebugService@@UAE@I@Z @ 147 NONAME ABSENT ; QDeclarativeDebugService::~QDeclarativeDebugService(unsigned int) + ??_EQDeclarativeDebugService@@UAE@I@Z @ 147 NONAME ; QDeclarativeDebugService::~QDeclarativeDebugService(unsigned int) ??0QDeclarativeDomDynamicProperty@@QAE@ABV0@@Z @ 148 NONAME ABSENT ; QDeclarativeDomDynamicProperty::QDeclarativeDomDynamicProperty(class QDeclarativeDomDynamicProperty const &) ?className@QDeclarativeDebugObjectReference@@QBE?AVQString@@XZ @ 149 NONAME ABSENT ; class QString QDeclarativeDebugObjectReference::className(void) const ?indexOfSlot@QMetaObjectBuilder@@QAEHABVQByteArray@@@Z @ 150 NONAME ABSENT ; int QMetaObjectBuilder::indexOfSlot(class QByteArray const &) @@ -294,7 +294,7 @@ EXPORTS ?attachedPropertiesType@QDeclarativeType@@QBEPBUQMetaObject@@XZ @ 293 NONAME ABSENT ; struct QMetaObject const * QDeclarativeType::attachedPropertiesType(void) const ?setName@QDeclarativeState@@QAEXABVQString@@@Z @ 294 NONAME ; void QDeclarativeState::setName(class QString const &) ?setReversed@QDeclarativeTransition@@QAEX_N@Z @ 295 NONAME ; void QDeclarativeTransition::setReversed(bool) - ?idForObject@QDeclarativeDebugService@@SAHPAVQObject@@@Z @ 296 NONAME ABSENT ; int QDeclarativeDebugService::idForObject(class QObject *) + ?idForObject@QDeclarativeDebugService@@SAHPAVQObject@@@Z @ 296 NONAME ; int QDeclarativeDebugService::idForObject(class QObject *) ?qt_metacall@QDeclarativeDebugWatch@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 297 NONAME ABSENT ; int QDeclarativeDebugWatch::qt_metacall(enum QMetaObject::Call, int, void * *) ?fromState@QDeclarativeTransition@@QBE?AVQString@@XZ @ 298 NONAME ; class QString QDeclarativeTransition::fromState(void) const ??1QDeclarativeExpression@@UAE@XZ @ 299 NONAME ; QDeclarativeExpression::~QDeclarativeExpression(void) @@ -332,7 +332,7 @@ EXPORTS ??0QDeclarativeCustomParserNode@@QAE@ABV0@@Z @ 331 NONAME ; QDeclarativeCustomParserNode::QDeclarativeCustomParserNode(class QDeclarativeCustomParserNode const &) ??1QDeclarativeImageProvider@@UAE@XZ @ 332 NONAME ; QDeclarativeImageProvider::~QDeclarativeImageProvider(void) ?sync@QDeclarativeListModel@@QAEXXZ @ 333 NONAME ABSENT ; void QDeclarativeListModel::sync(void) - ?objectForId@QDeclarativeDebugService@@SAPAVQObject@@H@Z @ 334 NONAME ABSENT ; class QObject * QDeclarativeDebugService::objectForId(int) + ?objectForId@QDeclarativeDebugService@@SAPAVQObject@@H@Z @ 334 NONAME ; class QObject * QDeclarativeDebugService::objectForId(int) ?hasFocus@QDeclarativeItem@@QBE_NXZ @ 335 NONAME ; bool QDeclarativeItem::hasFocus(void) const ??1QDeclarativeExtensionPlugin@@UAE@XZ @ 336 NONAME ; QDeclarativeExtensionPlugin::~QDeclarativeExtensionPlugin(void) ?qt_metacall@QDeclarativeBehavior@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 337 NONAME ABSENT ; int QDeclarativeBehavior::qt_metacall(enum QMetaObject::Call, int, void * *) @@ -482,7 +482,7 @@ EXPORTS ?pluginPathList@QDeclarativeEngine@@QBE?AVQStringList@@XZ @ 481 NONAME ; class QStringList QDeclarativeEngine::pluginPathList(void) const ?parentContext@QDeclarativeContext@@QBEPAV1@XZ @ 482 NONAME ; class QDeclarativeContext * QDeclarativeContext::parentContext(void) const ?leftMarginChanged@QDeclarativeAnchors@@IAEXXZ @ 483 NONAME ABSENT ; void QDeclarativeAnchors::leftMarginChanged(void) - ?staticMetaObject@QDeclarativeDebugService@@2UQMetaObject@@B @ 484 NONAME ABSENT ; struct QMetaObject const QDeclarativeDebugService::staticMetaObject + ?staticMetaObject@QDeclarativeDebugService@@2UQMetaObject@@B @ 484 NONAME ; struct QMetaObject const QDeclarativeDebugService::staticMetaObject ?topMargin@QDeclarativeAnchors@@QBEMXZ @ 485 NONAME ABSENT ; float QDeclarativeAnchors::topMargin(void) const ??0QDeclarativeDebugExpressionQuery@@AAE@PAVQObject@@@Z @ 486 NONAME ABSENT ; QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(class QObject *) ??0QPacket@@IAE@ABVQByteArray@@@Z @ 487 NONAME ; QPacket::QPacket(class QByteArray const &) @@ -559,7 +559,7 @@ EXPORTS ?metaObject@QDeclarativeEngine@@UBEPBUQMetaObject@@XZ @ 558 NONAME ; struct QMetaObject const * QDeclarativeEngine::metaObject(void) const ??_EQDeclarativeDebugContextReference@@QAE@I@Z @ 559 NONAME ABSENT ; QDeclarativeDebugContextReference::~QDeclarativeDebugContextReference(unsigned int) ?propertyWrite@QDeclarativeOpenMetaObject@@MAEXH@Z @ 560 NONAME ABSENT ; void QDeclarativeOpenMetaObject::propertyWrite(int) - ?qt_metacall@QDeclarativeDebugService@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 561 NONAME ABSENT ; int QDeclarativeDebugService::qt_metacall(enum QMetaObject::Call, int, void * *) + ?qt_metacall@QDeclarativeDebugService@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 561 NONAME ; int QDeclarativeDebugService::qt_metacall(enum QMetaObject::Call, int, void * *) ?setVerticalCenterOffset@QDeclarativeAnchors@@QAEXM@Z @ 562 NONAME ABSENT ; void QDeclarativeAnchors::setVerticalCenterOffset(float) ??1QDeclarativeDebugWatch@@UAE@XZ @ 563 NONAME ABSENT ; QDeclarativeDebugWatch::~QDeclarativeDebugWatch(void) ??1QPacketAutoSend@@UAE@XZ @ 564 NONAME ABSENT ; QPacketAutoSend::~QPacketAutoSend(void) @@ -641,7 +641,7 @@ EXPORTS ?d_func@QDeclarativeItem@@AAEPAVQDeclarativeItemPrivate@@XZ @ 640 NONAME ; class QDeclarativeItemPrivate * QDeclarativeItem::d_func(void) ?binding@QDeclarativeDomValueBinding@@QBE?AVQString@@XZ @ 641 NONAME ABSENT ; class QString QDeclarativeDomValueBinding::binding(void) const ?updateAutoState@QDeclarativeStateGroup@@AAE_NXZ @ 642 NONAME ; bool QDeclarativeStateGroup::updateAutoState(void) - ?tr@QDeclarativeDebugService@@SA?AVQString@@PBD0@Z @ 643 NONAME ABSENT ; class QString QDeclarativeDebugService::tr(char const *, char const *) + ?tr@QDeclarativeDebugService@@SA?AVQString@@PBD0@Z @ 643 NONAME ; class QString QDeclarativeDebugService::tr(char const *, char const *) ?tr@QDeclarativeComponent@@SA?AVQString@@PBD0H@Z @ 644 NONAME ; class QString QDeclarativeComponent::tr(char const *, char const *, int) ??1QDeclarativeProperty@@QAE@XZ @ 645 NONAME ; QDeclarativeProperty::~QDeclarativeProperty(void) ?fontChanged@QDeclarativeText@@IAEXABVQFont@@@Z @ 646 NONAME ABSENT ; void QDeclarativeText::fontChanged(class QFont const &) @@ -667,14 +667,14 @@ EXPORTS ?getStaticMetaObject@QDeclarativeListModel@@SAABUQMetaObject@@XZ @ 666 NONAME ABSENT ; struct QMetaObject const & QDeclarativeListModel::getStaticMetaObject(void) ?setStdCppSet@QMetaPropertyBuilder@@QAEX_N@Z @ 667 NONAME ABSENT ; void QMetaPropertyBuilder::setStdCppSet(bool) ??0QDeclarativeItemPrivate@@QAE@XZ @ 668 NONAME ; QDeclarativeItemPrivate::QDeclarativeItemPrivate(void) - ??0QDeclarativeDebugService@@QAE@ABVQString@@PAVQObject@@@Z @ 669 NONAME ABSENT ; QDeclarativeDebugService::QDeclarativeDebugService(class QString const &, class QObject *) + ??0QDeclarativeDebugService@@QAE@ABVQString@@PAVQObject@@@Z @ 669 NONAME ; QDeclarativeDebugService::QDeclarativeDebugService(class QString const &, class QObject *) ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@_N@Z @ 670 NONAME ABSENT ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, bool) ??_EQPacketAutoSend@@UAE@I@Z @ 671 NONAME ABSENT ; QPacketAutoSend::~QPacketAutoSend(unsigned int) ?saveValueType@QDeclarativePropertyPrivate@@SA?AVQByteArray@@PBUQMetaObject@@H0H@Z @ 672 NONAME ABSENT ; class QByteArray QDeclarativePropertyPrivate::saveValueType(struct QMetaObject const *, int, struct QMetaObject const *, int) ?resetHeight@QDeclarativeItem@@QAEXXZ @ 673 NONAME ; void QDeclarativeItem::resetHeight(void) ?setVAlign@QDeclarativeText@@QAEXW4VAlignment@1@@Z @ 674 NONAME ABSENT ; void QDeclarativeText::setVAlign(enum QDeclarativeText::VAlignment) - ??1QDeclarativeDebugService@@UAE@XZ @ 675 NONAME ABSENT ; QDeclarativeDebugService::~QDeclarativeDebugService(void) - ?trUtf8@QDeclarativeDebugService@@SA?AVQString@@PBD0H@Z @ 676 NONAME ABSENT ; class QString QDeclarativeDebugService::trUtf8(char const *, char const *, int) + ??1QDeclarativeDebugService@@UAE@XZ @ 675 NONAME ; QDeclarativeDebugService::~QDeclarativeDebugService(void) + ?trUtf8@QDeclarativeDebugService@@SA?AVQString@@PBD0H@Z @ 676 NONAME ; class QString QDeclarativeDebugService::trUtf8(char const *, char const *, int) ?elideMode@QDeclarativeText@@QBE?AW4TextElideMode@1@XZ @ 677 NONAME ABSENT ; enum QDeclarativeText::TextElideMode QDeclarativeText::elideMode(void) const ?baseUrl@QDeclarativeContext@@QBE?AVQUrl@@XZ @ 678 NONAME ; class QUrl QDeclarativeContext::baseUrl(void) const ?qt_metacall@QDeclarativeDebugRootContextQuery@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 679 NONAME ABSENT ; int QDeclarativeDebugRootContextQuery::qt_metacall(enum QMetaObject::Call, int, void * *) @@ -849,7 +849,7 @@ EXPORTS ??1QDeclarativeBehavior@@UAE@XZ @ 848 NONAME ABSENT ; QDeclarativeBehavior::~QDeclarativeBehavior(void) ?qmlInfo@@YA?AVQDeclarativeInfo@@PBVQObject@@@Z @ 849 NONAME ; class QDeclarativeInfo qmlInfo(class QObject const *) ?qt_metacall@QDeclarativeDebugClient@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 850 NONAME ABSENT ; int QDeclarativeDebugClient::qt_metacall(enum QMetaObject::Call, int, void * *) - ?d_func@QDeclarativeDebugService@@ABEPBVQDeclarativeDebugServicePrivate@@XZ @ 851 NONAME ABSENT ; class QDeclarativeDebugServicePrivate const * QDeclarativeDebugService::d_func(void) const + ?d_func@QDeclarativeDebugService@@ABEPBVQDeclarativeDebugServicePrivate@@XZ @ 851 NONAME ; class QDeclarativeDebugServicePrivate const * QDeclarativeDebugService::d_func(void) const ??1QDeclarativeDebugQuery@@UAE@XZ @ 852 NONAME ABSENT ; QDeclarativeDebugQuery::~QDeclarativeDebugQuery(void) ?data_append@QDeclarativeItemPrivate@@SAXPAV?$QDeclarativeListProperty@VQObject@@@@PAVQObject@@@Z @ 853 NONAME ; void QDeclarativeItemPrivate::data_append(class QDeclarativeListProperty<class QObject> *, class QObject *) ?tr@QDeclarativeState@@SA?AVQString@@PBD0@Z @ 854 NONAME ; class QString QDeclarativeState::tr(char const *, char const *) @@ -1120,7 +1120,7 @@ EXPORTS ?expression@QDeclarativeDebugExpressionQuery@@QBE?AVQVariant@@XZ @ 1119 NONAME ABSENT ; class QVariant QDeclarativeDebugExpressionQuery::expression(void) const ??4QDeclarativeDomList@@QAEAAV0@ABV0@@Z @ 1120 NONAME ABSENT ; class QDeclarativeDomList & QDeclarativeDomList::operator=(class QDeclarativeDomList const &) ?qt_metacall@QDeclarativeComponent@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1121 NONAME ; int QDeclarativeComponent::qt_metacall(enum QMetaObject::Call, int, void * *) - ?tr@QDeclarativeDebugService@@SA?AVQString@@PBD0H@Z @ 1122 NONAME ABSENT ; class QString QDeclarativeDebugService::tr(char const *, char const *, int) + ?tr@QDeclarativeDebugService@@SA?AVQString@@PBD0H@Z @ 1122 NONAME ; class QString QDeclarativeDebugService::tr(char const *, char const *, int) ?staticMetaObject@QDeclarativeEngine@@2UQMetaObject@@B @ 1123 NONAME ; struct QMetaObject const QDeclarativeEngine::staticMetaObject ?staticMetaObject@QDeclarativeStateOperation@@2UQMetaObject@@B @ 1124 NONAME ; struct QMetaObject const QDeclarativeStateOperation::staticMetaObject ?actions@QDeclarativeStateOperation@@UAE?AV?$QList@VQDeclarativeAction@@@@XZ @ 1125 NONAME ; class QList<class QDeclarativeAction> QDeclarativeStateOperation::actions(void) @@ -1145,7 +1145,7 @@ EXPORTS ?sourceFile@QDeclarativeExpression@@QBE?AVQString@@XZ @ 1144 NONAME ; class QString QDeclarativeExpression::sourceFile(void) const ??_EQDeclarativeAnchors@@UAE@I@Z @ 1145 NONAME ABSENT ; QDeclarativeAnchors::~QDeclarativeAnchors(unsigned int) ?removeNotifySignal@QMetaPropertyBuilder@@QAEXXZ @ 1146 NONAME ABSENT ; void QMetaPropertyBuilder::removeNotifySignal(void) - ?trUtf8@QDeclarativeDebugService@@SA?AVQString@@PBD0@Z @ 1147 NONAME ABSENT ; class QString QDeclarativeDebugService::trUtf8(char const *, char const *) + ?trUtf8@QDeclarativeDebugService@@SA?AVQString@@PBD0@Z @ 1147 NONAME ; class QString QDeclarativeDebugService::trUtf8(char const *, char const *) ?setImportPathList@QDeclarativeEngine@@QAEXABVQStringList@@@Z @ 1148 NONAME ; void QDeclarativeEngine::setImportPathList(class QStringList const &) ?enabledChanged@QDeclarativeDebugService@@MAEX_N@Z @ 1149 NONAME ABSENT ; void QDeclarativeDebugService::enabledChanged(bool) ?addWatch@QDeclarativeEngineDebug@@QAEPAVQDeclarativeDebugWatch@@ABVQDeclarativeDebugObjectReference@@PAVQObject@@@Z @ 1150 NONAME ABSENT ; class QDeclarativeDebugWatch * QDeclarativeEngineDebug::addWatch(class QDeclarativeDebugObjectReference const &, class QObject *) @@ -1176,7 +1176,7 @@ EXPORTS ?paint@QDeclarativeRectangle@@UAEXPAVQPainter@@PBVQStyleOptionGraphicsItem@@PAVQWidget@@@Z @ 1175 NONAME ABSENT ; void QDeclarativeRectangle::paint(class QPainter *, class QStyleOptionGraphicsItem const *, class QWidget *) ??6QDeclarativeState@@QAEAAV0@PAVQDeclarativeStateOperation@@@Z @ 1176 NONAME ; class QDeclarativeState & QDeclarativeState::operator<<(class QDeclarativeStateOperation *) ?destroy@QDeclarativeAbstractBinding@@UAEXXZ @ 1177 NONAME ABSENT ; void QDeclarativeAbstractBinding::destroy(void) - ?qt_metacast@QDeclarativeDebugService@@UAEPAXPBD@Z @ 1178 NONAME ABSENT ; void * QDeclarativeDebugService::qt_metacast(char const *) + ?qt_metacast@QDeclarativeDebugService@@UAEPAXPBD@Z @ 1178 NONAME ; void * QDeclarativeDebugService::qt_metacast(char const *) ?qt_metacast@QDeclarativeValueType@@UAEPAXPBD@Z @ 1179 NONAME ABSENT ; void * QDeclarativeValueType::qt_metacast(char const *) ?childAt@QDeclarativeItem@@QBEPAV1@MM@Z @ 1180 NONAME ; class QDeclarativeItem * QDeclarativeItem::childAt(float, float) const ?paintedWidth@QDeclarativeText@@QBEMXZ @ 1181 NONAME ABSENT ; float QDeclarativeText::paintedWidth(void) const @@ -1297,7 +1297,7 @@ EXPORTS ?value@QDeclarativeOpenMetaObject@@QBE?AVQVariant@@H@Z @ 1296 NONAME ABSENT ; class QVariant QDeclarativeOpenMetaObject::value(int) const ?tr@QDeclarativeDebugRootContextQuery@@SA?AVQString@@PBD0H@Z @ 1297 NONAME ABSENT ; class QString QDeclarativeDebugRootContextQuery::tr(char const *, char const *, int) ?setFromState@QDeclarativeTransition@@QAEXABVQString@@@Z @ 1298 NONAME ; void QDeclarativeTransition::setFromState(class QString const &) - ?metaObject@QDeclarativeDebugService@@UBEPBUQMetaObject@@XZ @ 1299 NONAME ABSENT ; struct QMetaObject const * QDeclarativeDebugService::metaObject(void) const + ?metaObject@QDeclarativeDebugService@@UBEPBUQMetaObject@@XZ @ 1299 NONAME ; struct QMetaObject const * QDeclarativeDebugService::metaObject(void) const ?state@QDeclarativeDebugQuery@@QBE?AW4State@1@XZ @ 1300 NONAME ABSENT ; enum QDeclarativeDebugQuery::State QDeclarativeDebugQuery::state(void) const ?setBottom@QDeclarativeScaleGrid@@QAEXH@Z @ 1301 NONAME ABSENT ; void QDeclarativeScaleGrid::setBottom(int) ?topMarginChanged@QDeclarativeAnchors@@IAEXXZ @ 1302 NONAME ABSENT ; void QDeclarativeAnchors::topMarginChanged(void) @@ -1305,7 +1305,7 @@ EXPORTS ?position@QDeclarativeDomObject@@QBEHXZ @ 1304 NONAME ABSENT ; int QDeclarativeDomObject::position(void) const ?update@QDeclarativeBinding@@UAEXV?$QFlags@W4WriteFlag@QDeclarativePropertyPrivate@@@@@Z @ 1305 NONAME ABSENT ; void QDeclarativeBinding::update(class QFlags<enum QDeclarativePropertyPrivate::WriteFlag>) ?tr@QDeclarativeBehavior@@SA?AVQString@@PBD0@Z @ 1306 NONAME ABSENT ; class QString QDeclarativeBehavior::tr(char const *, char const *) - ?isDebuggingEnabled@QDeclarativeDebugService@@SA_NXZ @ 1307 NONAME ABSENT ; bool QDeclarativeDebugService::isDebuggingEnabled(void) + ?isDebuggingEnabled@QDeclarativeDebugService@@SA_NXZ @ 1307 NONAME ; bool QDeclarativeDebugService::isDebuggingEnabled(void) ?tr@QDeclarativeText@@SA?AVQString@@PBD0H@Z @ 1308 NONAME ABSENT ; class QString QDeclarativeText::tr(char const *, char const *, int) ?reset@QDeclarativeProperty@@QBE_NXZ @ 1309 NONAME ; bool QDeclarativeProperty::reset(void) const ?objectDebugId@QDeclarativeDebugWatch@@QBEHXZ @ 1310 NONAME ABSENT ; int QDeclarativeDebugWatch::objectDebugId(void) const @@ -1344,7 +1344,7 @@ EXPORTS ?maximumPacketSize@QPacketProtocol@@QBEHXZ @ 1343 NONAME ; int QPacketProtocol::maximumPacketSize(void) const ??_EQDeclarativeDebuggerStatus@@UAE@I@Z @ 1344 NONAME ABSENT ; QDeclarativeDebuggerStatus::~QDeclarativeDebuggerStatus(unsigned int) ?error@QDeclarativeCustomParser@@IAEXABVQString@@@Z @ 1345 NONAME ; void QDeclarativeCustomParser::error(class QString const &) - ?messageReceived@QDeclarativeDebugService@@MAEXABVQByteArray@@@Z @ 1346 NONAME ABSENT ; void QDeclarativeDebugService::messageReceived(class QByteArray const &) + ?messageReceived@QDeclarativeDebugService@@MAEXABVQByteArray@@@Z @ 1346 NONAME ; void QDeclarativeDebugService::messageReceived(class QByteArray const &) ??0QDeclarativeParserStatus@@QAE@XZ @ 1347 NONAME ; QDeclarativeParserStatus::QDeclarativeParserStatus(void) ?isNumber@Variant@QDeclarativeParser@@QBE_NXZ @ 1348 NONAME ; bool QDeclarativeParser::Variant::isNumber(void) const ?getStaticMetaObject@QDeclarativeEngineDebug@@SAABUQMetaObject@@XZ @ 1349 NONAME ABSENT ; struct QMetaObject const & QDeclarativeEngineDebug::getStaticMetaObject(void) @@ -1475,7 +1475,7 @@ EXPORTS ?packetWritten@QPacketProtocol@@IAEXXZ @ 1474 NONAME ; void QPacketProtocol::packetWritten(void) ?getStaticMetaObject@QDeclarativeDebugObjectQuery@@SAABUQMetaObject@@XZ @ 1475 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugObjectQuery::getStaticMetaObject(void) ?isSignalProperty@QDeclarativeProperty@@QBE_NXZ @ 1476 NONAME ; bool QDeclarativeProperty::isSignalProperty(void) const - ?d_func@QDeclarativeDebugService@@AAEPAVQDeclarativeDebugServicePrivate@@XZ @ 1477 NONAME ABSENT ; class QDeclarativeDebugServicePrivate * QDeclarativeDebugService::d_func(void) + ?d_func@QDeclarativeDebugService@@AAEPAVQDeclarativeDebugServicePrivate@@XZ @ 1477 NONAME ; class QDeclarativeDebugServicePrivate * QDeclarativeDebugService::d_func(void) ?qmlTypeNames@QDeclarativeMetaType@@SA?AV?$QList@VQByteArray@@@@XZ @ 1478 NONAME ABSENT ; class QList<class QByteArray> QDeclarativeMetaType::qmlTypeNames(void) ?componentComplete@QDeclarativeItem@@MAEXXZ @ 1479 NONAME ; void QDeclarativeItem::componentComplete(void) ?creationContext@QDeclarativeComponent@@QBEPAVQDeclarativeContext@@XZ @ 1480 NONAME ; class QDeclarativeContext * QDeclarativeComponent::creationContext(void) const @@ -1575,7 +1575,7 @@ EXPORTS ?keyCount@QMetaEnumBuilder@@QBEHXZ @ 1574 NONAME ABSENT ; int QMetaEnumBuilder::keyCount(void) const ??1QDeclarativeDomProperty@@QAE@XZ @ 1575 NONAME ABSENT ; QDeclarativeDomProperty::~QDeclarativeDomProperty(void) ?url@QDeclarativePixmap@@QBEABVQUrl@@XZ @ 1576 NONAME ; class QUrl const & QDeclarativePixmap::url(void) const - ?sendMessage@QDeclarativeDebugService@@QAEXABVQByteArray@@@Z @ 1577 NONAME ABSENT ; void QDeclarativeDebugService::sendMessage(class QByteArray const &) + ?sendMessage@QDeclarativeDebugService@@QAEXABVQByteArray@@@Z @ 1577 NONAME ; void QDeclarativeDebugService::sendMessage(class QByteArray const &) ?context@QDeclarativeScriptString@@QBEPAVQDeclarativeContext@@XZ @ 1578 NONAME ; class QDeclarativeContext * QDeclarativeScriptString::context(void) const ?queryObject@QDeclarativeEngineDebug@@QAEPAVQDeclarativeDebugObjectQuery@@ABVQDeclarativeDebugObjectReference@@PAVQObject@@@Z @ 1579 NONAME ABSENT ; class QDeclarativeDebugObjectQuery * QDeclarativeEngineDebug::queryObject(class QDeclarativeDebugObjectReference const &, class QObject *) ?tr@QDeclarativePropertyMap@@SA?AVQString@@PBD0H@Z @ 1580 NONAME ; class QString QDeclarativePropertyMap::tr(char const *, char const *, int) @@ -1608,7 +1608,7 @@ EXPORTS ??_EQDeclarativeComponent@@UAE@I@Z @ 1607 NONAME ; QDeclarativeComponent::~QDeclarativeComponent(unsigned int) ?get@QDeclarativeItemPrivate@@SAPAV1@PAVQDeclarativeItem@@@Z @ 1608 NONAME ; class QDeclarativeItemPrivate * QDeclarativeItemPrivate::get(class QDeclarativeItem *) ?staticMetaObject@QDeclarativeView@@2UQMetaObject@@B @ 1609 NONAME ; struct QMetaObject const QDeclarativeView::staticMetaObject - ?objectToString@QDeclarativeDebugService@@SA?AVQString@@PAVQObject@@@Z @ 1610 NONAME ABSENT ; class QString QDeclarativeDebugService::objectToString(class QObject *) + ?objectToString@QDeclarativeDebugService@@SA?AVQString@@PAVQObject@@@Z @ 1610 NONAME ; class QString QDeclarativeDebugService::objectToString(class QObject *) ?defaultValue@QDeclarativeDomDynamicProperty@@QBE?AVQDeclarativeDomProperty@@XZ @ 1611 NONAME ABSENT ; class QDeclarativeDomProperty QDeclarativeDomDynamicProperty::defaultValue(void) const ?relatedMetaObject@QMetaObjectBuilder@@QBEPBUQMetaObject@@H@Z @ 1612 NONAME ABSENT ; struct QMetaObject const * QMetaObjectBuilder::relatedMetaObject(int) const ?addKey@QMetaEnumBuilder@@QAEHABVQByteArray@@H@Z @ 1613 NONAME ABSENT ; int QMetaEnumBuilder::addKey(class QByteArray const &, int) @@ -1633,7 +1633,7 @@ EXPORTS ?tr@QDeclarativeView@@SA?AVQString@@PBD0@Z @ 1632 NONAME ; class QString QDeclarativeView::tr(char const *, char const *) ?qt_metacall@QPacketProtocol@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1633 NONAME ; int QPacketProtocol::qt_metacall(enum QMetaObject::Call, int, void * *) ??0QDeclarativeItem@@QAE@PAV0@@Z @ 1634 NONAME ; QDeclarativeItem::QDeclarativeItem(class QDeclarativeItem *) - ?hasDebuggingClient@QDeclarativeDebugService@@SA_NXZ @ 1635 NONAME ABSENT ; bool QDeclarativeDebugService::hasDebuggingClient(void) + ?hasDebuggingClient@QDeclarativeDebugService@@SA_NXZ @ 1635 NONAME ; bool QDeclarativeDebugService::hasDebuggingClient(void) ?staticMetaObject@QDeclarativeContext@@2UQMetaObject@@B @ 1636 NONAME ; struct QMetaObject const QDeclarativeContext::staticMetaObject ?setContextForObject@QDeclarativeEngine@@SAXPAVQObject@@PAVQDeclarativeContext@@@Z @ 1637 NONAME ; void QDeclarativeEngine::setContextForObject(class QObject *, class QDeclarativeContext *) ?baselineOffsetChanged@QDeclarativeItem@@IAEXM@Z @ 1638 NONAME ; void QDeclarativeItem::baselineOffsetChanged(float) @@ -1733,7 +1733,7 @@ EXPORTS ?start@QDeclarativeTimer@@QAEXXZ @ 1732 NONAME ABSENT ; void QDeclarativeTimer::start(void) ?transition@QDeclarativeAbstractAnimation@@UAEXAAV?$QList@VQDeclarativeAction@@@@AAV?$QList@VQDeclarativeProperty@@@@W4TransitionDirection@1@@Z @ 1733 NONAME ABSENT ; void QDeclarativeAbstractAnimation::transition(class QList<class QDeclarativeAction> &, class QList<class QDeclarativeProperty> &, enum QDeclarativeAbstractAnimation::TransitionDirection) ?componentComplete@QDeclarativeAbstractAnimation@@UAEXXZ @ 1734 NONAME ABSENT ; void QDeclarativeAbstractAnimation::componentComplete(void) - ?statusChanged@QDeclarativeDebugService@@MAEXW4Status@1@@Z @ 1735 NONAME ABSENT ; void QDeclarativeDebugService::statusChanged(enum QDeclarativeDebugService::Status) + ?statusChanged@QDeclarativeDebugService@@MAEXW4Status@1@@Z @ 1735 NONAME ; void QDeclarativeDebugService::statusChanged(enum QDeclarativeDebugService::Status) ?runningChanged@QDeclarativeAbstractAnimation@@IAEX_N@Z @ 1736 NONAME ABSENT ; void QDeclarativeAbstractAnimation::runningChanged(bool) ?trUtf8@QDeclarativeAbstractAnimation@@SA?AVQString@@PBD0H@Z @ 1737 NONAME ABSENT ; class QString QDeclarativeAbstractAnimation::trUtf8(char const *, char const *, int) ??_EQDeclarativeBasePositioner@@UAE@I@Z @ 1738 NONAME ABSENT ; QDeclarativeBasePositioner::~QDeclarativeBasePositioner(unsigned int) @@ -1813,7 +1813,7 @@ EXPORTS ?setTarget@QDeclarativeAbstractAnimation@@EAEXABVQDeclarativeProperty@@@Z @ 1812 NONAME ABSENT ; void QDeclarativeAbstractAnimation::setTarget(class QDeclarativeProperty const &) ?alwaysRunToEnd@QDeclarativeAbstractAnimation@@QBE_NXZ @ 1813 NONAME ABSENT ; bool QDeclarativeAbstractAnimation::alwaysRunToEnd(void) const ?tr@QDeclarativeTimer@@SA?AVQString@@PBD0H@Z @ 1814 NONAME ABSENT ; class QString QDeclarativeTimer::tr(char const *, char const *, int) - ?status@QDeclarativeDebugService@@QBE?AW4Status@1@XZ @ 1815 NONAME ABSENT ; enum QDeclarativeDebugService::Status QDeclarativeDebugService::status(void) const + ?status@QDeclarativeDebugService@@QBE?AW4Status@1@XZ @ 1815 NONAME ; enum QDeclarativeDebugService::Status QDeclarativeDebugService::status(void) const ?intervalChanged@QDeclarativeTimer@@IAEXXZ @ 1816 NONAME ABSENT ; void QDeclarativeTimer::intervalChanged(void) ?isPaused@QDeclarativeAbstractAnimation@@QBE_NXZ @ 1817 NONAME ABSENT ; bool QDeclarativeAbstractAnimation::isPaused(void) const ?getStaticMetaObject@QDeclarativeAbstractAnimation@@SAABUQMetaObject@@XZ @ 1818 NONAME ABSENT ; struct QMetaObject const & QDeclarativeAbstractAnimation::getStaticMetaObject(void) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index adf2b3c..26a0761 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -12950,4 +12950,35 @@ EXPORTS ?dynamicPageCount@QTextDocumentLayout@@QBEHXZ @ 12949 NONAME ; int QTextDocumentLayout::dynamicPageCount(void) const ?setWordSelectionEnabled@QTextControl@@QAEX_N@Z @ 12950 NONAME ; void QTextControl::setWordSelectionEnabled(bool) ?isWordSelectionEnabled@QTextControl@@QBE_NXZ @ 12951 NONAME ; bool QTextControl::isWordSelectionEnabled(void) const + ?assignedInputContext@QWidgetPrivate@@QBEPAVQInputContext@@XZ @ 12952 NONAME ; class QInputContext * QWidgetPrivate::assignedInputContext(void) const + ?updateMicroFocus@QLineControl@@IAEXXZ @ 12953 NONAME ; void QLineControl::updateMicroFocus(void) + ?beginDataAccess@QVolatileImage@@QBEXXZ @ 12954 NONAME ; void QVolatileImage::beginDataAccess(void) const + ??1QVolatileImage@@QAE@XZ @ 12955 NONAME ; QVolatileImage::~QVolatileImage(void) + ??0QVolatileImage@@QAE@HHW4Format@QImage@@@Z @ 12956 NONAME ; QVolatileImage::QVolatileImage(int, int, enum QImage::Format) + ?ensureFormat@QVolatileImage@@QAE_NW4Format@QImage@@@Z @ 12957 NONAME ; bool QVolatileImage::ensureFormat(enum QImage::Format) + ?fill@QVolatileImage@@QAEXI@Z @ 12958 NONAME ; void QVolatileImage::fill(unsigned int) + ?isNull@QVolatileImage@@QBE_NXZ @ 12959 NONAME ; bool QVolatileImage::isNull(void) const + ?toImage@QVolatileImage@@QBE?AVQImage@@XZ @ 12960 NONAME ; class QImage QVolatileImage::toImage(void) const + ??0QVolatileImage@@QAE@ABVQImage@@@Z @ 12961 NONAME ; QVolatileImage::QVolatileImage(class QImage const &) + ?format@QVolatileImage@@QBE?AW4Format@QImage@@XZ @ 12962 NONAME ; enum QImage::Format QVolatileImage::format(void) const + ?endDataAccess@QVolatileImage@@QBEX_N@Z @ 12963 NONAME ; void QVolatileImage::endDataAccess(bool) const + ?constBits@QVolatileImage@@QBEPBEXZ @ 12964 NONAME ; unsigned char const * QVolatileImage::constBits(void) const + ?height@QVolatileImage@@QBEHXZ @ 12965 NONAME ; int QVolatileImage::height(void) const + ?duplicateNativeImage@QVolatileImage@@QBEPAXXZ @ 12966 NONAME ; void * QVolatileImage::duplicateNativeImage(void) const + ?bits@QVolatileImage@@QAEPAEXZ @ 12967 NONAME ; unsigned char * QVolatileImage::bits(void) + ?paintEngine@QVolatileImage@@QAEPAVQPaintEngine@@XZ @ 12968 NONAME ; class QPaintEngine * QVolatileImage::paintEngine(void) + ?bytesPerLine@QVolatileImage@@QBEHXZ @ 12969 NONAME ; int QVolatileImage::bytesPerLine(void) const + ?width@QVolatileImage@@QBEHXZ @ 12970 NONAME ; int QVolatileImage::width(void) const + ?copyFrom@QVolatileImage@@QAEXPAV1@ABVQRect@@@Z @ 12971 NONAME ; void QVolatileImage::copyFrom(class QVolatileImage *, class QRect const &) + ?imageRef@QVolatileImage@@QAEAAVQImage@@XZ @ 12972 NONAME ; class QImage & QVolatileImage::imageRef(void) + ??0QVolatileImage@@QAE@PAX0@Z @ 12973 NONAME ; QVolatileImage::QVolatileImage(void *, void *) + ??4QVolatileImage@@QAEAAV0@ABV0@@Z @ 12974 NONAME ; class QVolatileImage & QVolatileImage::operator=(class QVolatileImage const &) + ??0QVolatileImage@@QAE@XZ @ 12975 NONAME ; QVolatileImage::QVolatileImage(void) + ?hasAlphaChannel@QVolatileImage@@QBE_NXZ @ 12976 NONAME ; bool QVolatileImage::hasAlphaChannel(void) const + ?setAlphaChannel@QVolatileImage@@QAEXABVQPixmap@@@Z @ 12977 NONAME ; void QVolatileImage::setAlphaChannel(class QPixmap const &) + ?byteCount@QVolatileImage@@QBEHXZ @ 12978 NONAME ; int QVolatileImage::byteCount(void) const + ??0QVolatileImage@@QAE@ABV0@@Z @ 12979 NONAME ; QVolatileImage::QVolatileImage(class QVolatileImage const &) + ?depth@QVolatileImage@@QBEHXZ @ 12980 NONAME ; int QVolatileImage::depth(void) const + ?releaseCachedResources@QGraphicsSystem@@UAEXXZ @ 12981 NONAME ; void QGraphicsSystem::releaseCachedResources(void) + ?qt_s60_setPartialScreenInputMode@@YAX_N@Z @ 12982 NONAME ; void qt_s60_setPartialScreenInputMode(bool) diff --git a/src/s60installs/bwins/QtOpenGLu.def b/src/s60installs/bwins/QtOpenGLu.def index 620fcb9..3eb1512 100644 --- a/src/s60installs/bwins/QtOpenGLu.def +++ b/src/s60installs/bwins/QtOpenGLu.def @@ -703,4 +703,12 @@ EXPORTS ?maxTextureWidth@QGLTextureGlyphCache@@UBEHXZ @ 702 NONAME ; int QGLTextureGlyphCache::maxTextureWidth(void) const ?filterMode@QGLTextureGlyphCache@@QBE?AW4FilterMode@1@XZ @ 703 NONAME ; enum QGLTextureGlyphCache::FilterMode QGLTextureGlyphCache::filterMode(void) const ?setFilterMode@QGLTextureGlyphCache@@QAEXW4FilterMode@1@@Z @ 704 NONAME ; void QGLTextureGlyphCache::setFilterMode(enum QGLTextureGlyphCache::FilterMode) + ?toNativeType@QGLPixmapData@@UAEPAXW4NativeType@QPixmapData@@@Z @ 705 NONAME ; void * QGLPixmapData::toNativeType(enum QPixmapData::NativeType) + ?fromNativeType@QGLPixmapData@@UAEXPAXW4NativeType@QPixmapData@@@Z @ 706 NONAME ; void QGLPixmapData::fromNativeType(void *, enum QPixmapData::NativeType) + ?clear@QGLTextureGlyphCache@@QAEXXZ @ 707 NONAME ; void QGLTextureGlyphCache::clear(void) + ?context@QGLTextureGlyphCache@@QBEPAVQGLContext@@XZ @ 708 NONAME ; class QGLContext * QGLTextureGlyphCache::context(void) const + ?swapBehavior@QGLWindowSurface@@2W4SwapMode@1@A @ 709 NONAME ; enum QGLWindowSurface::SwapMode QGLWindowSurface::swapBehavior + ?createPixmapForImage@QGLPixmapData@@AAEXAAVQImage@@V?$QFlags@W4ImageConversionFlag@Qt@@@@_N@Z @ 710 NONAME ; void QGLPixmapData::createPixmapForImage(class QImage &, class QFlags<enum Qt::ImageConversionFlag>, bool) + ?fromImageReader@QGLPixmapData@@UAEXPAVQImageReader@@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 711 NONAME ; void QGLPixmapData::fromImageReader(class QImageReader *, class QFlags<enum Qt::ImageConversionFlag>) + ?setContext@QGLTextureGlyphCache@@QAEXPAVQGLContext@@@Z @ 712 NONAME ; void QGLTextureGlyphCache::setContext(class QGLContext *) diff --git a/src/s60installs/bwins/QtOpenVGu.def b/src/s60installs/bwins/QtOpenVGu.def index 87b9c7f..18f576b 100644 --- a/src/s60installs/bwins/QtOpenVGu.def +++ b/src/s60installs/bwins/QtOpenVGu.def @@ -176,4 +176,11 @@ EXPORTS ?fromData@QVGPixmapData@@UAE_NPBEIPBDV?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 175 NONAME ; bool QVGPixmapData::fromData(unsigned char const *, unsigned int, char const *, class QFlags<enum Qt::ImageConversionFlag>) ?fromImageReader@QVGPixmapData@@UAEXPAVQImageReader@@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 176 NONAME ; void QVGPixmapData::fromImageReader(class QImageReader *, class QFlags<enum Qt::ImageConversionFlag>) ?canVgWritePixels@QVGPaintEngine@@ABE_NABVQImage@@@Z @ 177 NONAME ; bool QVGPaintEngine::canVgWritePixels(class QImage const &) const + ?updateSerial@QVGPixmapData@@IAEXXZ @ 178 NONAME ; void QVGPixmapData::updateSerial(void) + ?copy@QVGPixmapData@@UAEXPBVQPixmapData@@ABVQRect@@@Z @ 179 NONAME ; void QVGPixmapData::copy(class QPixmapData const *, class QRect const &) + ?idealFormat@QVGPixmapData@@IBE?AW4Format@QImage@@PAV3@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 180 NONAME ; enum QImage::Format QVGPixmapData::idealFormat(class QImage *, class QFlags<enum Qt::ImageConversionFlag>) const + ?ensureReadback@QVGPixmapData@@UBEX_N@Z @ 181 NONAME ; void QVGPixmapData::ensureReadback(bool) const + ?initFromNativeImageHandle@QVGPixmapData@@QAE_NPAXABVQString@@@Z @ 182 NONAME ; bool QVGPixmapData::initFromNativeImageHandle(void *, class QString const &) + ?createFromNativeImageHandleProvider@QVGPixmapData@@QAEXXZ @ 183 NONAME ; void QVGPixmapData::createFromNativeImageHandleProvider(void) + ?releaseNativeImageHandle@QVGPixmapData@@QAEXXZ @ 184 NONAME ; void QVGPixmapData::releaseNativeImageHandle(void) diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index 95180d4..130e2d5 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -761,20 +761,20 @@ EXPORTS _ZN24QDeclarativeCustomParser5errorERK28QDeclarativeCustomParserNodeRK7QString @ 760 NONAME _ZN24QDeclarativeCustomParser5errorERK32QDeclarativeCustomParserPropertyRK7QString @ 761 NONAME _ZN24QDeclarativeCustomParser5errorERK7QString @ 762 NONAME - _ZN24QDeclarativeDebugService11idForObjectEP7QObject @ 763 NONAME ABSENT - _ZN24QDeclarativeDebugService11objectForIdEi @ 764 NONAME ABSENT - _ZN24QDeclarativeDebugService11qt_metacallEN11QMetaObject4CallEiPPv @ 765 NONAME ABSENT - _ZN24QDeclarativeDebugService11qt_metacastEPKc @ 766 NONAME ABSENT - _ZN24QDeclarativeDebugService11sendMessageERK10QByteArray @ 767 NONAME ABSENT + _ZN24QDeclarativeDebugService11idForObjectEP7QObject @ 763 NONAME + _ZN24QDeclarativeDebugService11objectForIdEi @ 764 NONAME + _ZN24QDeclarativeDebugService11qt_metacallEN11QMetaObject4CallEiPPv @ 765 NONAME + _ZN24QDeclarativeDebugService11qt_metacastEPKc @ 766 NONAME + _ZN24QDeclarativeDebugService11sendMessageERK10QByteArray @ 767 NONAME _ZN24QDeclarativeDebugService14enabledChangedEb @ 768 NONAME ABSENT - _ZN24QDeclarativeDebugService14objectToStringEP7QObject @ 769 NONAME ABSENT - _ZN24QDeclarativeDebugService15messageReceivedERK10QByteArray @ 770 NONAME ABSENT - _ZN24QDeclarativeDebugService16staticMetaObjectE @ 771 NONAME DATA 16 ABSENT - _ZN24QDeclarativeDebugService18hasDebuggingClientEv @ 772 NONAME ABSENT - _ZN24QDeclarativeDebugService18isDebuggingEnabledEv @ 773 NONAME ABSENT - _ZN24QDeclarativeDebugService19getStaticMetaObjectEv @ 774 NONAME ABSENT - _ZN24QDeclarativeDebugServiceC1ERK7QStringP7QObject @ 775 NONAME ABSENT - _ZN24QDeclarativeDebugServiceC2ERK7QStringP7QObject @ 776 NONAME ABSENT + _ZN24QDeclarativeDebugService14objectToStringEP7QObject @ 769 NONAME + _ZN24QDeclarativeDebugService15messageReceivedERK10QByteArray @ 770 NONAME + _ZN24QDeclarativeDebugService16staticMetaObjectE @ 771 NONAME DATA 16 + _ZN24QDeclarativeDebugService18hasDebuggingClientEv @ 772 NONAME + _ZN24QDeclarativeDebugService18isDebuggingEnabledEv @ 773 NONAME + _ZN24QDeclarativeDebugService19getStaticMetaObjectEv @ 774 NONAME + _ZN24QDeclarativeDebugServiceC1ERK7QStringP7QObject @ 775 NONAME + _ZN24QDeclarativeDebugServiceC2ERK7QStringP7QObject @ 776 NONAME _ZN24QDeclarativeDomComponentC1ERKS_ @ 777 NONAME ABSENT _ZN24QDeclarativeDomComponentC1Ev @ 778 NONAME ABSENT _ZN24QDeclarativeDomComponentC2ERKS_ @ 779 NONAME ABSENT @@ -1425,8 +1425,8 @@ EXPORTS _ZNK23QDeclarativePropertyMapixERK7QString @ 1424 NONAME _ZNK24QDeclarativeCustomParser11resolveTypeERK10QByteArray @ 1425 NONAME _ZNK24QDeclarativeCustomParser12evaluateEnumERK10QByteArray @ 1426 NONAME - _ZNK24QDeclarativeDebugService10metaObjectEv @ 1427 NONAME ABSENT - _ZNK24QDeclarativeDebugService4nameEv @ 1428 NONAME ABSENT + _ZNK24QDeclarativeDebugService10metaObjectEv @ 1427 NONAME + _ZNK24QDeclarativeDebugService4nameEv @ 1428 NONAME _ZNK24QDeclarativeDebugService9isEnabledEv @ 1429 NONAME ABSENT _ZNK24QDeclarativeDomComponent13componentRootEv @ 1430 NONAME ABSENT _ZNK24QDeclarativeScriptString11scopeObjectEv @ 1431 NONAME @@ -1554,7 +1554,7 @@ EXPORTS _ZTI23QDeclarativeItemPrivate @ 1553 NONAME _ZTI23QDeclarativePropertyMap @ 1554 NONAME _ZTI24QDeclarativeCustomParser @ 1555 NONAME - _ZTI24QDeclarativeDebugService @ 1556 NONAME ABSENT + _ZTI24QDeclarativeDebugService @ 1556 NONAME _ZTI24QDeclarativeParserStatus @ 1557 NONAME _ZTI25QDeclarativeImageProvider @ 1558 NONAME _ZTI26QDeclarativeDebuggerStatus @ 1559 NONAME ABSENT @@ -1604,7 +1604,7 @@ EXPORTS _ZTV23QDeclarativeItemPrivate @ 1603 NONAME _ZTV23QDeclarativePropertyMap @ 1604 NONAME _ZTV24QDeclarativeCustomParser @ 1605 NONAME - _ZTV24QDeclarativeDebugService @ 1606 NONAME ABSENT + _ZTV24QDeclarativeDebugService @ 1606 NONAME _ZTV24QDeclarativeParserStatus @ 1607 NONAME _ZTV25QDeclarativeImageProvider @ 1608 NONAME _ZTV26QDeclarativeDebuggerStatus @ 1609 NONAME ABSENT @@ -1777,10 +1777,10 @@ EXPORTS _ZN23QDeclarativeDebugClientD1Ev @ 1776 NONAME ABSENT _ZN23QDeclarativeDebugClientD2Ev @ 1777 NONAME ABSENT _ZN23QDeclarativeEngineDebug13statusChangedENS_6StatusE @ 1778 NONAME ABSENT - _ZN24QDeclarativeDebugService13statusChangedENS_6StatusE @ 1779 NONAME ABSENT - _ZN24QDeclarativeDebugServiceD0Ev @ 1780 NONAME ABSENT - _ZN24QDeclarativeDebugServiceD1Ev @ 1781 NONAME ABSENT - _ZN24QDeclarativeDebugServiceD2Ev @ 1782 NONAME ABSENT + _ZN24QDeclarativeDebugService13statusChangedENS_6StatusE @ 1779 NONAME + _ZN24QDeclarativeDebugServiceD0Ev @ 1780 NONAME + _ZN24QDeclarativeDebugServiceD1Ev @ 1781 NONAME + _ZN24QDeclarativeDebugServiceD2Ev @ 1782 NONAME _ZN26QDeclarativeBasePositioner10addChangedEv @ 1783 NONAME ABSENT _ZN26QDeclarativeBasePositioner10itemChangeEN13QGraphicsItem18GraphicsItemChangeERK8QVariant @ 1784 NONAME ABSENT _ZN26QDeclarativeBasePositioner10setSpacingEi @ 1785 NONAME ABSENT @@ -1851,7 +1851,7 @@ EXPORTS _ZNK17QDeclarativeTimer9isRunningEv @ 1850 NONAME ABSENT _ZNK23QDeclarativeDebugClient6statusEv @ 1851 NONAME ABSENT _ZNK23QDeclarativeEngineDebug6statusEv @ 1852 NONAME ABSENT - _ZNK24QDeclarativeDebugService6statusEv @ 1853 NONAME ABSENT + _ZNK24QDeclarativeDebugService6statusEv @ 1853 NONAME _ZNK26QDeclarativeBasePositioner10metaObjectEv @ 1854 NONAME ABSENT _ZNK26QDeclarativeBasePositioner3addEv @ 1855 NONAME ABSENT _ZNK26QDeclarativeBasePositioner4moveEv @ 1856 NONAME ABSENT diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 564f530..b6a24ab 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12145,4 +12145,41 @@ EXPORTS _ZTV19QTextDocumentLayout @ 12144 NONAME _ZN12QTextControl23setWordSelectionEnabledEb @ 12145 NONAME _ZNK12QTextControl22isWordSelectionEnabledEv @ 12146 NONAME + _ZN12QLineControl16updateMicroFocusEv @ 12147 NONAME + _ZNK14QWidgetPrivate20assignedInputContextEv @ 12148 NONAME + _ZN14QVolatileImage11paintEngineEv @ 12149 NONAME + _ZN14QVolatileImage12ensureFormatEN6QImage6FormatE @ 12150 NONAME + _ZN14QVolatileImage15setAlphaChannelERK7QPixmap @ 12151 NONAME + _ZN14QVolatileImage4bitsEv @ 12152 NONAME + _ZN14QVolatileImage4fillEj @ 12153 NONAME + _ZN14QVolatileImage8copyFromEPS_RK5QRect @ 12154 NONAME + _ZN14QVolatileImage8imageRefEv @ 12155 NONAME + _ZN14QVolatileImageC1EPvS0_ @ 12156 NONAME + _ZN14QVolatileImageC1ERK6QImage @ 12157 NONAME + _ZN14QVolatileImageC1ERKS_ @ 12158 NONAME + _ZN14QVolatileImageC1EiiN6QImage6FormatE @ 12159 NONAME + _ZN14QVolatileImageC1Ev @ 12160 NONAME + _ZN14QVolatileImageC2EPvS0_ @ 12161 NONAME + _ZN14QVolatileImageC2ERK6QImage @ 12162 NONAME + _ZN14QVolatileImageC2ERKS_ @ 12163 NONAME + _ZN14QVolatileImageC2EiiN6QImage6FormatE @ 12164 NONAME + _ZN14QVolatileImageC2Ev @ 12165 NONAME + _ZN14QVolatileImageD1Ev @ 12166 NONAME + _ZN14QVolatileImageD2Ev @ 12167 NONAME + _ZN14QVolatileImageaSERKS_ @ 12168 NONAME + _ZNK14QVolatileImage12bytesPerLineEv @ 12169 NONAME + _ZNK14QVolatileImage13endDataAccessEb @ 12170 NONAME + _ZNK14QVolatileImage15beginDataAccessEv @ 12171 NONAME + _ZNK14QVolatileImage15hasAlphaChannelEv @ 12172 NONAME + _ZNK14QVolatileImage20duplicateNativeImageEv @ 12173 NONAME + _ZNK14QVolatileImage5depthEv @ 12174 NONAME + _ZNK14QVolatileImage5widthEv @ 12175 NONAME + _ZNK14QVolatileImage6formatEv @ 12176 NONAME + _ZNK14QVolatileImage6heightEv @ 12177 NONAME + _ZNK14QVolatileImage6isNullEv @ 12178 NONAME + _ZNK14QVolatileImage7toImageEv @ 12179 NONAME + _ZNK14QVolatileImage9byteCountEv @ 12180 NONAME + _ZNK14QVolatileImage9constBitsEv @ 12181 NONAME + _ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12182 NONAME + _Z32qt_s60_setPartialScreenInputModeb @ 12183 NONAME diff --git a/src/s60installs/eabi/QtOpenGLu.def b/src/s60installs/eabi/QtOpenGLu.def index c92d99e..33d40fd 100644 --- a/src/s60installs/eabi/QtOpenGLu.def +++ b/src/s60installs/eabi/QtOpenGLu.def @@ -707,4 +707,11 @@ EXPORTS _ZNK20QGLTextureGlyphCache16maxTextureHeightEv @ 706 NONAME _ZThn8_NK20QGLTextureGlyphCache15maxTextureWidthEv @ 707 NONAME _ZThn8_NK20QGLTextureGlyphCache16maxTextureHeightEv @ 708 NONAME + _ZN13QGLPixmapData12toNativeTypeEN11QPixmapData10NativeTypeE @ 709 NONAME + _ZN13QGLPixmapData14fromNativeTypeEPvN11QPixmapData10NativeTypeE @ 710 NONAME + _ZN13QGLPixmapData15fromImageReaderEP12QImageReader6QFlagsIN2Qt19ImageConversionFlagEE @ 711 NONAME + _ZN13QGLPixmapData20createPixmapForImageER6QImage6QFlagsIN2Qt19ImageConversionFlagEEb @ 712 NONAME + _ZN16QGLWindowSurface12swapBehaviorE @ 713 NONAME DATA 4 + _ZN20QGLTextureGlyphCache10setContextEP10QGLContext @ 714 NONAME + _ZN20QGLTextureGlyphCache5clearEv @ 715 NONAME diff --git a/src/s60installs/eabi/QtOpenVGu.def b/src/s60installs/eabi/QtOpenVGu.def index e1828c1..25c53b8 100644 --- a/src/s60installs/eabi/QtOpenVGu.def +++ b/src/s60installs/eabi/QtOpenVGu.def @@ -206,4 +206,11 @@ EXPORTS _ZN13QVGPixmapData8fromDataEPKhjPKc6QFlagsIN2Qt19ImageConversionFlagEE @ 205 NONAME _ZN13QVGPixmapData8fromFileERK7QStringPKc6QFlagsIN2Qt19ImageConversionFlagEE @ 206 NONAME _ZNK14QVGPaintEngine16canVgWritePixelsERK6QImage @ 207 NONAME + _ZN13QVGPixmapData12updateSerialEv @ 208 NONAME + _ZN13QVGPixmapData4copyEPK11QPixmapDataRK5QRect @ 209 NONAME + _ZNK13QVGPixmapData11idealFormatEP6QImage6QFlagsIN2Qt19ImageConversionFlagEE @ 210 NONAME + _ZNK13QVGPixmapData14ensureReadbackEb @ 211 NONAME + _ZN13QVGPixmapData24releaseNativeImageHandleEv @ 212 NONAME + _ZN13QVGPixmapData25initFromNativeImageHandleEPvRK7QString @ 213 NONAME + _ZN13QVGPixmapData35createFromNativeImageHandleProviderEv @ 214 NONAME diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index c282b1e..1e5ce0f 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -11,23 +11,6 @@ symbian: { isEmpty(QT_LIBINFIX) { TARGET.UID3 = 0x2001E61C - - # Sqlite3 is expected to be already found on phone if infixed configuration is built. - # It is also expected that devices newer than those based on S60 5.0 all have sqlite3.dll. - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { - BLD_INF_RULES.prj_exports += \ - "sqlite3.sis /epoc32/data/qt/sis/sqlite3.sis" - symbian-abld|symbian-sbsv2 { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${EPOCROOT}epoc32/data/qt/sis/sqlite3.sis\", (0x2002af5f)" - } else { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${PWD}/sqlite3.sis\", (0x2002af5f)" - } - qtlibraries.pkg_postrules += sqlitedeployment - } } else { # Always use experimental UID for infixed configuration to avoid UID clash TARGET.UID3 = 0xE001E61C @@ -92,7 +75,7 @@ symbian: { vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 2468a46..5454df5 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -268,8 +268,14 @@ QScriptValue QScriptContext::argument(int index) const QScriptValue QScriptContext::callee() const { const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); - QScript::APIShim shim(QScript::scriptEngineFromExec(frame)); - return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->callee()); + QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(frame); + QScript::APIShim shim(eng); + if (frame->callee() == eng->originalGlobalObject()) { + // This is a pushContext()-created context; the callee is a lie. + Q_ASSERT(QScriptEnginePrivate::contextFlags(const_cast<JSC::CallFrame*>(frame)) & QScriptEnginePrivate::NativeContext); + return QScriptValue(); + } + return eng->scriptValueFromJSCValue(frame->callee()); } /*! diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index d3e5f2f..160058e 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -955,8 +955,11 @@ static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) } // namespace QScript QScriptEnginePrivate::QScriptEnginePrivate() - : registeredScriptValues(0), freeScriptValues(0), freeScriptValuesCount(0), - registeredScriptStrings(0), inEval(false) + : originalGlobalObjectProxy(0), currentFrame(0), + qobjectPrototype(0), qmetaobjectPrototype(0), variantPrototype(0), + activeAgent(0), agentLineNumber(-1), + registeredScriptValues(0), freeScriptValues(0), freeScriptValuesCount(0), + registeredScriptStrings(0), processEventsInterval(-1), inEval(false) { qMetaTypeId<QScriptValue>(); qMetaTypeId<QList<int> >(); @@ -1002,10 +1005,6 @@ QScriptEnginePrivate::QScriptEnginePrivate() currentFrame = exec; - originalGlobalObjectProxy = 0; - activeAgent = 0; - agentLineNumber = -1; - processEventsInterval = -1; cachedTranslationUrl = JSC::UString(); cachedTranslationContext = JSC::UString(); JSC::setCurrentIdentifierTable(oldTable); @@ -1253,10 +1252,12 @@ void QScriptEnginePrivate::mark(JSC::MarkStack& markStack) { Q_Q(QScriptEngine); - markStack.append(originalGlobalObject()); - markStack.append(globalObject()); - if (originalGlobalObjectProxy) - markStack.append(originalGlobalObjectProxy); + if (originalGlobalObject()) { + markStack.append(originalGlobalObject()); + markStack.append(globalObject()); + if (originalGlobalObjectProxy) + markStack.append(originalGlobalObjectProxy); + } if (qobjectPrototype) markStack.append(qobjectPrototype); @@ -1281,7 +1282,7 @@ void QScriptEnginePrivate::mark(JSC::MarkStack& markStack) } } - { + if (q) { QScriptContext *context = q->currentContext(); while (context) { @@ -2727,6 +2728,14 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV bool clearScopeChain) { JSC::JSValue thisObject = _thisObject; + if (!callee) { + // callee can't be zero, as this can cause JSC to crash during GC + // marking phase if the context's Arguments object has been created. + // Fake it by using the global object. Note that this is also handled + // in QScriptContext::callee(), as that function should still return + // an invalid value. + callee = originalGlobalObject(); + } if (calledAsConstructor) { //JSC doesn't create default created object for native functions. so we do it JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype); diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index ac57918..e289636 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -254,6 +254,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, int val) : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) { if (engine) { + QScript::APIShim shim(d_ptr->engine); JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); } else @@ -271,6 +272,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, uint val) : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) { if (engine) { + QScript::APIShim shim(d_ptr->engine); JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); } else @@ -288,6 +290,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) { if (engine) { + QScript::APIShim shim(d_ptr->engine); JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); } else @@ -305,6 +308,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) { if (engine) { + QScript::APIShim shim(d_ptr->engine); JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsString(exec, val)); } else { @@ -325,6 +329,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate(QScriptEnginePrivate::get(engine))) { if (engine) { + QScript::APIShim shim(d_ptr->engine); JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsString(exec, val)); } else { diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 4df1d63..bf7c0aa 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -657,7 +657,7 @@ bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values) return false; } - return d->exec(stmt, prepStatement, rec); + return d->exec(stmt, prepStatement, rec, QSqlRecord() /* no where values */); } /*! @@ -695,7 +695,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) } stmt.append(QLatin1Char(' ')).append(where); - return d->exec(stmt, prepStatement, whereValues); + return d->exec(stmt, prepStatement, QSqlRecord() /* no new values */, whereValues); } /*! diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index d2b96e6..f4f3811 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -75,7 +75,7 @@ public: QSqlRecord record(const QVector<QVariant> &values) const; bool exec(const QString &stmt, bool prepStatement, - const QSqlRecord &rec, const QSqlRecord &whereValues = QSqlRecord()); + const QSqlRecord &rec, const QSqlRecord &whereValues); virtual void revertCachedRow(int row); void revertInsertedRow(); bool setRecord(int row, const QSqlRecord &record); diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index 9a83a1a..ace17db 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -130,7 +130,7 @@ public: QBenchmarkGlobalData:current is created at the beginning of qExec() and cleared at the end. */ -class QBenchmarkGlobalData +class Q_TESTLIB_EXPORT QBenchmarkGlobalData { public: static QBenchmarkGlobalData *current; @@ -161,7 +161,7 @@ private: created at the beginning of qInvokeTestMethod() and cleared at the end. */ -class QBenchmarkTestMethodData +class Q_TESTLIB_EXPORT QBenchmarkTestMethodData { public: static QBenchmarkTestMethodData *current; diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 0ceb71d..97f069e 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -956,6 +956,10 @@ static bool isValidSlot(const QMetaMethod &sl) return true; } +Q_TESTLIB_EXPORT bool printAvailableFunctions = false; +Q_TESTLIB_EXPORT QStringList testFunctions; +Q_TESTLIB_EXPORT QStringList testTags; + static void qPrintTestSlots() { for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) { @@ -976,7 +980,7 @@ static int qToInt(char *str) return l; } -static void qParseArgs(int argc, char *argv[]) +Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) { lastTestFuncIdx = -1; @@ -1025,8 +1029,12 @@ static void qParseArgs(int argc, char *argv[]) "%s", argv[0], testOptions); exit(0); } else if (strcmp(argv[i], "-functions") == 0) { - qPrintTestSlots(); - exit(0); + if (qml) { + QTest::printAvailableFunctions = true; + } else { + qPrintTestSlots(); + exit(0); + } } else if(strcmp(argv[i], "-xunitxml") == 0){ QTestLog::setLogMode(QTestLog::XunitXML); } else if (strcmp(argv[i], "-xml") == 0) { @@ -1146,6 +1154,32 @@ static void qParseArgs(int argc, char *argv[]) } else if (argv[i][0] == '-') { printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); + } else if (qml) { + // We can't check the availability of test functions until + // we load the QML files. So just store the data for now. + int colon = -1; + int offset; + for(offset = 0; *(argv[i]+offset); ++offset) { + if (*(argv[i]+offset) == ':') { + if (*(argv[i]+offset+1) == ':') { + // "::" is used as a test name separator. + // e.g. "ClickTests::test_click:row1". + ++offset; + } else { + colon = offset; + break; + } + } + } + if (colon == -1) { + QTest::testFunctions += QString::fromLatin1(argv[i]); + QTest::testTags += QString(); + } else { + QTest::testFunctions += + QString::fromLatin1(argv[i], colon); + QTest::testTags += + QString::fromLatin1(argv[i] + colon + 1); + } } else { int colon = -1; char buf[512], *data=0; @@ -1695,7 +1729,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QTEST_ASSERT(metaObject); QTestResult::setCurrentTestObject(metaObject->className()); - qParseArgs(argc, argv); + qtest_qParseArgs(argc, argv, false); #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { const QStringList origAppArgs(QCoreApplication::arguments()); diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index 08c86d1..6648beb 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QBenchmarkResult; -class QTestLog +class Q_TESTLIB_EXPORT QTestLog { public: enum LogMode { Plain = 0, XML, LightXML, XunitXML }; diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h index 15523f5..7ff120a 100644 --- a/src/testlib/qtestresult_p.h +++ b/src/testlib/qtestresult_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE class QTestResultPrivate; class QTestData; -class QTestResult +class Q_TESTLIB_EXPORT QTestResult { public: enum TestLocation { NoWhere = 0, DataFunc = 1, InitFunc = 2, Func = 3, CleanupFunc = 4 }; diff --git a/src/testlib/qtesttable_p.h b/src/testlib/qtesttable_p.h index d085b57..f835506 100644 --- a/src/testlib/qtesttable_p.h +++ b/src/testlib/qtesttable_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE class QTestData; class QTestTablePrivate; -class QTestTable +class Q_TESTLIB_EXPORT QTestTable { public: QTestTable(); diff --git a/tests/auto/declarative/qdeclarativeanimations/data/Double.qml b/tests/auto/declarative/qdeclarativeanimations/data/Double.qml new file mode 100644 index 0000000..b247fce --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/Double.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 + +Rectangle { + id: container + property bool on: false + border.color: "#ffffff" + color: "green" + width: 50 + height: 50 + NumberAnimation on x { + objectName: "animation" + running: container.on; from: 0; to: 600; loops: Animation.Infinite; duration: 2000 + } +} diff --git a/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml b/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml new file mode 100644 index 0000000..f0fdf9c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +Rectangle { + width: 400; height: 400 + + Double { id: dub; on: parent.width < 800 } + Component.onCompleted: dub.on = false +} diff --git a/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml b/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml new file mode 100644 index 0000000..7dc29f9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml @@ -0,0 +1,18 @@ +import QtQuick 1.0 + +Rectangle { + id: rect + width: 200 + height: 200 + + property bool animating: true + property int value: 0 + + NumberAnimation { + target: rect + property: "value" + running: rect.animating + to: 100 + duration: 50 + } +} diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp index 6f71dec..e2a54c0 100644 --- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp +++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp @@ -85,6 +85,9 @@ private slots: void rotation(); void runningTrueBug(); void nonTransitionBug(); + void registrationBug(); + void doubleRegistrationBug(); + void alwaysRunToEndRestartBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -793,6 +796,54 @@ void tst_qdeclarativeanimations::nonTransitionBug() QCOMPARE(mover->x(), qreal(100)); } +//QTBUG-14042 +void tst_qdeclarativeanimations::registrationBug() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/registrationBug.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(c.create()); + QVERIFY(rect != 0); + QTRY_COMPARE(rect->property("value"), QVariant(int(100))); +} + +void tst_qdeclarativeanimations::doubleRegistrationBug() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/doubleRegistrationBug.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(c.create()); + QVERIFY(rect != 0); + + QDeclarativeAbstractAnimation *anim = rect->findChild<QDeclarativeAbstractAnimation*>("animation"); + QVERIFY(anim != 0); + QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Stopped); +} + +//QTBUG-16736 +void tst_qdeclarativeanimations::alwaysRunToEndRestartBug() +{ + QDeclarativeRectangle rect; + QDeclarativePropertyAnimation animation; + animation.setTarget(&rect); + animation.setProperty("x"); + animation.setTo(200); + animation.setDuration(1000); + animation.setLoops(-1); + animation.setAlwaysRunToEnd(true); + QVERIFY(animation.loops() == -1); + QVERIFY(animation.alwaysRunToEnd() == true); + animation.start(); + animation.stop(); + animation.start(); + animation.stop(); + QTest::qWait(500); + QVERIFY(rect.x() != qreal(200)); + QTest::qWait(800); + QTIMED_COMPARE(rect.x(), qreal(200)); + QCOMPARE(static_cast<QDeclarativeAbstractAnimation*>(&animation)->qtAnimation()->state(), QAbstractAnimation::Stopped); +} + QTEST_MAIN(tst_qdeclarativeanimations) #include "tst_qdeclarativeanimations.moc" diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index 917b8d8..d01463e 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -166,8 +166,8 @@ void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDe { const QMetaObject *meta = o->metaObject(); - QDeclarativeType *type = QDeclarativeMetaType::qmlType(o->metaObject()); - QString className = type ? type->qmlTypeName() : QString(); + QDeclarativeType *type = QDeclarativeMetaType::qmlType(meta); + QString className = type ? QString(type->qmlTypeName()) : QString(meta->className()); className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); QCOMPARE(oref.debugId(), QDeclarativeDebugService::idForObject(o)); @@ -292,12 +292,21 @@ void tst_QDeclarativeDebug::initTestCase() QList<QByteArray> qml; qml << "import QtQuick 1.0\n" "Item {" + "id: root\n" "width: 10; height: 20; scale: blueRect.scale;" "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }" "Text { color: blueRect.color; }" "MouseArea {" "onEntered: { console.log('hello') }" "}" + "property variant varObj\n" + "property variant varObjList: []\n" + "Component.onCompleted: {\n" + "varObj = blueRect;\n" + "var list = varObjList;\n" + "list[0] = blueRect;\n" + "varObjList = list;\n" + "}\n" "}"; // add second component to test multiple root contexts @@ -741,7 +750,6 @@ void tst_QDeclarativeDebug::queryObject() QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue"))); QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue"))); - } else { foreach(const QDeclarativeDebugObjectReference &child, obj.children()) QCOMPARE(child.properties().count(), 0); @@ -798,6 +806,8 @@ void tst_QDeclarativeDebug::queryExpressionResult_data() QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60); QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500); QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("<undefined>")); + QTest::newRow("QObject*") << "varObj" << qVariantFromValue(QString("<unnamed object>")); + QTest::newRow("list of QObject*") << "varObjList" << qVariantFromValue(QString("<unknown value>")); } void tst_QDeclarativeDebug::tst_QDeclarativeDebugFileReference() diff --git a/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml b/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml new file mode 100644 index 0000000..d0ee545 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml @@ -0,0 +1,33 @@ +import QtQuick 1.0 + +Flickable { + property bool pressed: ma.pressed + width: 240 + height: 320 + contentWidth: 480 + contentHeight: 320 + flickableDirection: Flickable.HorizontalFlick + pressDelay: 50 + Flickable { + objectName: "innerFlickable" + flickableDirection: Flickable.VerticalFlick + width: 480 + height: 320 + contentWidth: 480 + contentHeight: 400 + pressDelay: 10000 + Rectangle { + y: 100 + anchors.horizontalCenter: parent.horizontalCenter + width: 240 + height: 100 + color: ma.pressed ? 'blue' : 'green' + MouseArea { + id: ma + objectName: "mouseArea" + anchors.fill: parent + } + } + } +} + diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index f4bec8f..65ba316 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -69,6 +69,7 @@ private slots: void maximumFlickVelocity(); void flickDeceleration(); void pressDelay(); + void nestedPressDelay(); void flickableDirection(); void qgraphicswidget(); void resizeContent(); @@ -246,6 +247,34 @@ void tst_qdeclarativeflickable::pressDelay() QCOMPARE(spy.count(),1); } +// QTBUG-17361 +void tst_qdeclarativeflickable::nestedPressDelay() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedPressDelay.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *outer = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject()); + QVERIFY(outer != 0); + + QDeclarativeFlickable *inner = canvas->rootObject()->findChild<QDeclarativeFlickable*>("innerFlickable"); + QVERIFY(inner != 0); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150))); + // the MouseArea is not pressed immediately + QVERIFY(outer->property("pressed").toBool() == false); + + // The outer pressDelay will prevail (50ms, vs. 10sec) + // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec. + QTRY_VERIFY(outer->property("pressed").toBool() == true); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150))); + + delete canvas; +} + void tst_qdeclarativeflickable::flickableDirection() { QDeclarativeComponent component(&engine); diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp index a62ea31..ffd5d38 100644 --- a/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp +++ b/tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp @@ -62,14 +62,24 @@ class tst_qdeclarativefolderlistmodel : public QObject { Q_OBJECT public: - tst_qdeclarativefolderlistmodel() {} + tst_qdeclarativefolderlistmodel() : removeStart(0), removeEnd(0) {} + +public slots: + void removed(const QModelIndex &, int start, int end) { + removeStart = start; + removeEnd = end; + } private slots: void basicProperties(); + void refresh(); private: void checkNoErrors(const QDeclarativeComponent& component); QDeclarativeEngine engine; + + int removeStart; + int removeEnd; }; void tst_qdeclarativefolderlistmodel::checkNoErrors(const QDeclarativeComponent& component) @@ -115,6 +125,28 @@ void tst_qdeclarativefolderlistmodel::basicProperties() QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile("")); } +void tst_qdeclarativefolderlistmodel::refresh() +{ + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); + checkNoErrors(component); + + QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); + QVERIFY(flm != 0); + + flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data")); + QTRY_COMPARE(flm->property("count").toInt(),2); // wait for refresh + + int count = flm->rowCount(); + + connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)), + this, SLOT(removed(const QModelIndex&,int,int))); + + flm->setProperty("sortReversed", true); + + QCOMPARE(removeStart, 0); + QCOMPARE(removeEnd, count-1); +} + QTEST_MAIN(tst_qdeclarativefolderlistmodel) #include "tst_qdeclarativefolderlistmodel.moc" diff --git a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml index 35a398b..b2d9213 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml @@ -1,6 +1,7 @@ import QtQuick 1.0 Rectangle { + property string sectionProperty: "number" width: 240 height: 320 color: "#ffffff" @@ -41,6 +42,11 @@ Rectangle { text: wrapper.y } } + ListView.onRemove: SequentialAnimation { + PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true } + NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 100; easing.type: Easing.InOutQuad } + PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false } + } } } ] @@ -51,7 +57,7 @@ Rectangle { height: 320 model: testModel delegate: myDelegate - section.property: "number" + section.property: sectionProperty section.delegate: Rectangle { objectName: "sect_" + section color: "#99bb99" diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index f358625..e326136 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -1078,6 +1078,65 @@ void tst_QDeclarativeListView::sectionsDelegate() QTRY_COMPARE(item->y(), qreal(i*20*6)); } + // remove section boundary + model.removeItem(5); + qApp->processEvents(); + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, + "sect_" + (i == 0 ? QString("aaa") : QString::number(i))); + QVERIFY(item); + } + + // QTBUG-17606 + QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(contentItem, "sect_1"); + QCOMPARE(items.count(), 1); + + // QTBUG-17759 + model.modifyItem(0, "One", "aaa"); + model.modifyItem(1, "One", "aaa"); + model.modifyItem(2, "One", "aaa"); + model.modifyItem(3, "Four", "aaa"); + model.modifyItem(4, "Four", "aaa"); + model.modifyItem(5, "Four", "aaa"); + model.modifyItem(6, "Five", "aaa"); + model.modifyItem(7, "Five", "aaa"); + model.modifyItem(8, "Five", "aaa"); + model.modifyItem(9, "Two", "aaa"); + model.modifyItem(10, "Two", "aaa"); + model.modifyItem(11, "Two", "aaa"); + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_aaa").count(), 1); + canvas->rootObject()->setProperty("sectionProperty", "name"); + // ensure view has settled. + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_Four").count(), 1); + for (int i = 0; i < 4; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, + "sect_" + model.name(i*3)); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*4)); + } + + // QTBUG-17769 + model.removeItems(10, 20); + // ensure view has settled. + QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "wrapper").count(), 10); + // Drag view up beyond bounds + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,20))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,0)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-200)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,-200))); + // view should settle back at 0 + QTRY_COMPARE(listview->contentY(), 0.0); + delete canvas; } @@ -2408,7 +2467,7 @@ QList<T*> tst_QDeclarativeListView::findItems(QGraphicsObject *parent, const QSt //qDebug() << parent->childItems().count() << "children"; for (int i = 0; i < parent->childItems().count(); ++i) { QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i)); - if(!item) + if(!item || !item->isVisible()) continue; //qDebug() << "try" << item; if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) diff --git a/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml b/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml new file mode 100644 index 0000000..11553fa --- /dev/null +++ b/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml @@ -0,0 +1,24 @@ +import QtQuick 1.1 + +Flickable { + property bool stealing: true + width: 200 + height: 200 + contentWidth: 400 + contentHeight: 400 + Rectangle { + color: "black" + width: 400 + height: 400 + Rectangle { + x: 50; y: 50 + width: 100; height: 100 + color: "steelblue" + MouseArea { + objectName: "mousearea" + anchors.fill: parent + preventStealing: stealing + } + } + } +} diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 845d6bb..e1c34fc 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -43,8 +43,10 @@ #include <QtTest/QSignalSpy> #include <private/qdeclarativemousearea_p.h> #include <private/qdeclarativerectangle_p.h> +#include <private/qdeclarativeflickable_p.h> #include <QtDeclarative/qdeclarativeview.h> #include <QtDeclarative/qdeclarativecontext.h> +#include <QtDeclarative/qdeclarativeengine.h> #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -65,6 +67,9 @@ private slots: void doubleClick(); void clickTwice(); void pressedOrdering(); + void preventStealing(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -356,6 +361,8 @@ void tst_QDeclarativeMouseArea::noOnClickedWithPressAndHold() QVERIFY(!canvas->rootObject()->property("clicked").toBool()); QVERIFY(canvas->rootObject()->property("held").toBool()); + + delete canvas; } void tst_QDeclarativeMouseArea::onMousePressRejected() @@ -399,6 +406,8 @@ void tst_QDeclarativeMouseArea::onMousePressRejected() QVERIFY(canvas->rootObject()->property("mr1_released").toBool()); QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool()); QVERIFY(!canvas->rootObject()->property("mr2_released").toBool()); + + delete canvas; } void tst_QDeclarativeMouseArea::doubleClick() @@ -436,6 +445,7 @@ void tst_QDeclarativeMouseArea::doubleClick() QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1); QCOMPARE(canvas->rootObject()->property("released").toInt(), 2); + delete canvas; } // QTBUG-14832 @@ -476,6 +486,8 @@ void tst_QDeclarativeMouseArea::clickTwice() QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2); QCOMPARE(canvas->rootObject()->property("released").toInt(), 2); QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2); + + delete canvas; } void tst_QDeclarativeMouseArea::pressedOrdering() @@ -512,6 +524,119 @@ void tst_QDeclarativeMouseArea::pressedOrdering() delete canvas; } +void tst_QDeclarativeMouseArea::preventStealing() +{ + QDeclarativeView *canvas = createView(); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/preventstealing.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject()); + QVERIFY(flickable != 0); + + QDeclarativeMouseArea *mouseArea = canvas->rootObject()->findChild<QDeclarativeMouseArea*>("mousearea"); + QVERIFY(mouseArea != 0); + + QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QDeclarativeMouseEvent*))); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80))); + + // Without preventStealing, mouse movement over MouseArea would + // cause the Flickable to steal mouse and trigger content movement. + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove); + moveEvent.setScenePos(QPointF(70, 70)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(60, 60)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(50, 50)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + // We should have received all three move events + QCOMPARE(mousePositionSpy.count(), 3); + QVERIFY(mouseArea->pressed()); + + // Flickable content should not have moved. + QCOMPARE(flickable->contentX(), 0.); + QCOMPARE(flickable->contentY(), 0.); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); + + // Now allow stealing and confirm Flickable does its thing. + canvas->rootObject()->setProperty("stealing", false); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80))); + + // Without preventStealing, mouse movement over MouseArea would + // cause the Flickable to steal mouse and trigger content movement. + moveEvent.setScenePos(QPointF(70, 70)); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(60, 60)); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(50, 50)); + QApplication::sendEvent(scene, &moveEvent); + + // We should only have received the first move event + QCOMPARE(mousePositionSpy.count(), 4); + // Our press should be taken away + QVERIFY(!mouseArea->pressed()); + + // Flickable content should have moved. + QCOMPARE(flickable->contentX(), 10.); + QCOMPARE(flickable->contentY(), 10.); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); + + delete canvas; +} + +void tst_QDeclarativeMouseArea::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; MouseArea { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; MouseArea { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeMouseArea::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("preventStealing") << "preventStealing: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"MouseArea.preventStealing\" is not available in QtQuick 1.0.\n"; +} + QTEST_MAIN(tst_QDeclarativeMouseArea) #include "tst_qdeclarativemousearea.moc" diff --git a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp index 7d746a7..e3a4723 100644 --- a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp +++ b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp @@ -76,6 +76,40 @@ void tst_QDeclarativePropertyMap::insert() map.insert(QLatin1String("key1"),"Hello World"); QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); + + //inserting property names same with existing method(signal, slot, method) names is not allowed + //QDeclarativePropertyMap has an invokable keys() method + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"keys\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("keys"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("keys"))); + QVERIFY(map.value(QLatin1String("keys")).isNull()); + + //QDeclarativePropertyMap has a deleteLater() slot + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"deleteLater\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("deleteLater"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("deleteLater"))); + QVERIFY(map.value(QLatin1String("deleteLater")).isNull()); + + //QDeclarativePropertyMap has an valueChanged() signal + QTest::ignoreMessage(QtWarningMsg, "Creating property with name \"valueChanged\" is not permitted, conflicts with internal symbols. "); + map.insert(QLatin1String("valueChanged"), 1); + QVERIFY(map.keys().count() == 2); + QVERIFY(!map.contains(QLatin1String("valueChanged"))); + QVERIFY(map.value(QLatin1String("valueChanged")).isNull()); + + //but 'valueChange' should be ok + map.insert(QLatin1String("valueChange"), 1); + QVERIFY(map.keys().count() == 3); + QVERIFY(map.contains(QLatin1String("valueChange"))); + QCOMPARE(map.value(QLatin1String("valueChange")), QVariant(1)); + + //'valueCHANGED' should be ok, too + map.insert(QLatin1String("valueCHANGED"), 1); + QVERIFY(map.keys().count() == 4); + QVERIFY(map.contains(QLatin1String("valueCHANGED"))); + QCOMPARE(map.value(QLatin1String("valueCHANGED")), QVariant(1)); } void tst_QDeclarativePropertyMap::operatorInsert() diff --git a/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml b/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml new file mode 100644 index 0000000..bd07d66 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/qtbug_14734.qml @@ -0,0 +1,10 @@ +import QtQuick 1.0 + +Rectangle { + width: 640 + height: 480 + + Text { + text: "Ã " + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 05546cb..7e0069f 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -109,6 +109,7 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void qtbug_14734(); private: QStringList standard; QStringList richText; @@ -1202,6 +1203,19 @@ void tst_qdeclarativetext::testQtQuick11Attributes_data() << ""; } +void tst_qdeclarativetext::qtbug_14734() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/qtbug_14734.qml"); + QVERIFY(canvas); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + delete canvas; +} + QTEST_MAIN(tst_qdeclarativetext) #include "tst_qdeclarativetext.moc" diff --git a/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml b/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml index 9ee8a93..0e1caf6 100644 --- a/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml +++ b/tests/auto/declarative/qdeclarativetextedit/data/navigation.qml @@ -15,6 +15,7 @@ Rectangle { KeyNavigation.right: lastItem KeyNavigation.up: firstItem KeyNavigation.down: lastItem + text: "a" } Item { id: lastItem diff --git a/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml b/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml new file mode 100644 index 0000000..e010135 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/positionAt.qml @@ -0,0 +1,9 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + objectName: "myInput" + width: 50 + height: 25 + text: "This is\n a long piece of text" +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 7d5101c..f642947 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -110,6 +110,7 @@ private slots: void persistentSelection(); void focusOnPress(); void selection(); + void keySelection(); void moveCursorSelection_data(); void moveCursorSelection(); void moveCursorSelectionSequence_data(); @@ -121,12 +122,17 @@ private slots: void dragMouseSelection(); void inputMethodHints(); + void positionAt(); + void cursorDelegate(); + void cursorVisible(); void delegateLoading_data(); void delegateLoading(); void navigation(); void readOnly(); void copyAndPaste(); + void canPaste(); + void canPasteEmpty(); void textInput(); void openInputPanelOnClick(); void openInputPanelOnFocus(); @@ -137,8 +143,12 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void preeditMicroFocus(); + void inputContextMouseHandler(); + void inputMethodComposing(); + private: - void simulateKey(QDeclarativeView *, int key); + void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0); QDeclarativeView *createView(const QString &filename); QStringList standard; @@ -753,6 +763,53 @@ void tst_qdeclarativetextedit::selection() QVERIFY(textEditObject->selectedText().isNull()); } +void tst_qdeclarativetextedit::keySelection() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml"); + canvas->show(); + canvas->setFocus(); + + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeTextEdit *input = qobject_cast<QDeclarativeTextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput"))); + + QVERIFY(input != 0); + QTRY_VERIFY(input->hasActiveFocus() == true); + + QSignalSpy spy(input, SIGNAL(selectionChanged())); + + simulateKey(canvas, Qt::Key_Right, Qt::ShiftModifier); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString("a")); + QCOMPARE(spy.count(), 1); + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 2); + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == false); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 2); + + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(spy.count(), 2); + simulateKey(canvas, Qt::Key_Left, Qt::ShiftModifier); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString("a")); + QCOMPARE(spy.count(), 3); + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == true); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 4); + simulateKey(canvas, Qt::Key_Left); + QVERIFY(input->hasActiveFocus() == false); + QCOMPARE(input->selectedText(), QString()); + QCOMPARE(spy.count(), 4); + + delete canvas; +} + void tst_qdeclarativetextedit::moveCursorSelection_data() { QTest::addColumn<QString>("testStr"); @@ -1177,6 +1234,8 @@ void tst_qdeclarativetextedit::dragMouseSelection() QVERIFY(str2.length() > 3); QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. + + delete canvas; } void tst_qdeclarativetextedit::mouseSelectionMode_data() @@ -1244,6 +1303,56 @@ void tst_qdeclarativetextedit::inputMethodHints() delete canvas; } +void tst_qdeclarativetextedit::positionAt() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextEdit *texteditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(texteditObject != 0); + + QFontMetrics fm(texteditObject->font()); + const int y0 = fm.height() / 2; + const int y1 = fm.height() * 3 / 2; + + int pos = texteditObject->positionAt(texteditObject->width()/2, y0); + int diff = abs(int(fm.width(texteditObject->text().left(pos))-texteditObject->width()/2)); + + // some tollerance for different fonts. +#ifdef Q_OS_LINUX + QVERIFY(diff < 2); +#else + QVERIFY(diff < 5); +#endif + + const qreal x0 = texteditObject->positionToRectangle(pos).x(); + const qreal x1 = texteditObject->positionToRectangle(pos + 1).x(); + + QString preeditText = texteditObject->text().mid(0, pos); + texteditObject->setText(texteditObject->text().mid(pos)); + texteditObject->setCursorPosition(0); + + QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>()); + QApplication::sendEvent(canvas, &inputEvent); + + // Check all points within the preedit text return the same position. + QCOMPARE(texteditObject->positionAt(0, y0), 0); + QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0); + QCOMPARE(texteditObject->positionAt(x0, y0), 0); + + // Verify positioning returns to normal after the preedit text. + QCOMPARE(texteditObject->positionAt(x1, y0), 1); + QCOMPARE(texteditObject->positionToRectangle(1).x(), x1); + + QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0); + + delete canvas; +} + void tst_qdeclarativetextedit::cursorDelegate() { QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml"); @@ -1272,6 +1381,76 @@ void tst_qdeclarativetextedit::cursorDelegate() delete view; } +void tst_qdeclarativetextedit::cursorVisible() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + view.setFocus(); + + QDeclarativeTextEdit edit; + QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool))); + + QCOMPARE(edit.isCursorVisible(), false); + + edit.setCursorVisible(true); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 1); + + edit.setCursorVisible(false); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + edit.setFocus(true); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + scene.addItem(&edit); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 3); + + edit.setFocus(false); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 4); + + edit.setFocus(true); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 5); + + scene.clearFocus(); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 6); + + scene.setFocus(); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 7); + + view.clearFocus(); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 8); + + view.setFocus(); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 9); + + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) + QApplication::setActiveWindow(0); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0)); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 10); + + QApplication::setActiveWindow(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 11); +#endif +} + void tst_qdeclarativetextedit::delegateLoading_data() { QTest::addColumn<QString>("qmlfile"); @@ -1349,6 +1528,8 @@ void tst_qdeclarativetextedit::navigation() simulateKey(canvas, Qt::Key_Right); QVERIFY(input->hasActiveFocus() == true); simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); + simulateKey(canvas, Qt::Key_Right); QVERIFY(input->hasActiveFocus() == false); simulateKey(canvas, Qt::Key_Left); QVERIFY(input->hasActiveFocus() == true); @@ -1416,6 +1597,42 @@ void tst_qdeclarativetextedit::copyAndPaste() { #endif } +void tst_qdeclarativetextedit::canPaste() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->setText("Some text"); + + QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }"; + QDeclarativeComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEdit = qobject_cast<QDeclarativeTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + // check initial value - QTBUG-17765 + QTextControl tc; + QCOMPARE(textEdit->canPaste(), tc.canPaste()); + +#endif +} + +void tst_qdeclarativetextedit::canPasteEmpty() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->clear(); + + QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }"; + QDeclarativeComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEdit = qobject_cast<QDeclarativeTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + // check initial value - QTBUG-17765 + QTextControl tc; + QCOMPARE(textEdit->canPaste(), tc.canPaste()); + +#endif +} + void tst_qdeclarativetextedit::readOnly() { QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); @@ -1440,10 +1657,10 @@ void tst_qdeclarativetextedit::readOnly() delete canvas; } -void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key) +void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key, Qt::KeyboardModifiers modifiers) { - QKeyEvent press(QKeyEvent::KeyPress, key, 0); - QKeyEvent release(QKeyEvent::KeyRelease, key, 0); + QKeyEvent press(QKeyEvent::KeyPress, key, modifiers); + QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers); QApplication::sendEvent(view, &press); QApplication::sendEvent(view, &release); @@ -1460,7 +1677,7 @@ QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1478,8 +1695,40 @@ public: closeInputPanelReceived = true; return QInputContext::filterEvent(event); } + + void update() { updateReceived = true; } + + void sendPreeditText(const QString &text, int cursor) + { + QList<QInputMethodEvent::Attribute> attributes; + attributes.append(QInputMethodEvent::Attribute( + QInputMethodEvent::Cursor, cursor, text.length(), QVariant())); + + QInputMethodEvent event(text, attributes); + sendEvent(event); + } + + void mouseHandler(int x, QMouseEvent *event) + { + cursor = x; + eventType = event->type(); + eventPosition = event->pos(); + eventGlobalPosition = event->globalPos(); + eventButton = event->button(); + eventButtons = event->buttons(); + eventModifiers = event->modifiers(); + } + bool openInputPanelReceived; bool closeInputPanelReceived; + bool updateReceived; + int cursor; + QEvent::Type eventType; + QPoint eventPosition; + QPoint eventGlobalPosition; + Qt::MouseButton eventButton; + Qt::MouseButtons eventButtons; + Qt::KeyboardModifiers eventModifiers; }; void tst_qdeclarativetextedit::textInput() @@ -1797,6 +2046,217 @@ void tst_qdeclarativetextedit::testQtQuick11Attributes_data() << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n"; } +void tst_qdeclarativetextedit::preeditMicroFocus() +{ + QString preeditText = "super"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QRect currentRect; + QRect previousRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + + // Verify that the micro focus rect is positioned the same for position 0 as + // it would be if there was no preedit text. + ic.updateReceived = false; + ic.sendPreeditText(preeditText, 0); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif + + // Verify that the micro focus rect moves to the left as the cursor position + // is incremented. + for (int i = 1; i <= 5; ++i) { + ic.updateReceived = false; + ic.sendPreeditText(preeditText, i); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QVERIFY(previousRect.left() < currentRect.left()); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif + previousRect = currentRect; + } + + // Verify that if there is no preedit cursor then the micro focus rect is the + // same as it would be if it were positioned at the end of the preedit text. + ic.sendPreeditText(preeditText, 0); + ic.updateReceived = false; + ic.sendEvent(QInputMethodEvent(preeditText, QList<QInputMethodEvent::Attribute>())); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif +} + +void tst_qdeclarativetextedit::inputContextMouseHandler() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setPos(0, 0); + edit.setWidth(200); + edit.setText(text.mid(0, 12)); + edit.setPos(0, 0); + edit.setCursorPosition(12); + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + view.setFocus(); + + QFontMetricsF fm(edit.font()); + const qreal y = fm.height() / 2; + + QPoint position2 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); + QPoint position8 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 8)), y))); + QPoint position20 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 20)), y))); + QPoint position27 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 27)), y))); + QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); + QPoint globalposition8 = view.viewport()->mapToGlobal(position8); + QPoint globalposition20 = view.viewport()->mapToGlobal(position20); + QPoint globalposition27 = view.viewport()->mapToGlobal(position27); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one. + ic.eventType = QEvent::None; + + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + // And in the other direction. + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position20); + QCOMPARE(ic.eventGlobalPosition, globalposition20); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 7 && ic.cursor <= 9); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; +} + +void tst_qdeclarativetextedit::inputMethodComposing() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setWidth(200); + edit.setText(text.mid(0, 12)); + edit.setCursorPosition(12); + edit.setPos(0, 0); + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QSignalSpy spy(&edit, SIGNAL(inputMethodComposingChanged())); + + QCOMPARE(edit.isInputMethodComposing(), false); + + ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(edit.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(edit.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(edit.isInputMethodComposing(), false); + QCOMPARE(spy.count(), 2); +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index a6d30a5..a7a4e5e 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -110,8 +110,12 @@ private slots: void passwordCharacter(); void cursorDelegate(); + void cursorVisible(); + void cursorRectangle(); void navigation(); void copyAndPaste(); + void canPasteEmpty(); + void canPaste(); void readOnly(); void openInputPanelOnClick(); @@ -125,6 +129,9 @@ private slots: void testQtQuick11Attributes_data(); void preeditAutoScroll(); + void preeditMicroFocus(); + void inputContextMouseHandler(); + void inputMethodComposing(); private: void simulateKey(QDeclarativeView *, int key); @@ -140,7 +147,8 @@ tst_qdeclarativetextinput::tst_qdeclarativetextinput() standard << "the quick brown fox jumped over the lazy dog" << "It's supercalifragisiticexpialidocious!" << "Hello, world!" - << "!dlrow ,olleH"; + << "!dlrow ,olleH" + << " spacey text "; colorStrings << "aliceblue" << "antiquewhite" @@ -441,6 +449,9 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() QTest::addColumn<int>("selectionEnd"); QTest::addColumn<bool>("reversible"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + QTest::newRow("(t)he|characters") << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectCharacters << 0 << 1 << true; QTest::newRow("do(g)|characters") @@ -578,6 +589,24 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; QTest::newRow("!<()>dlrow|words") << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; + + QTest::newRow(" <s(pac)ey> text |words") + << standard[4] << 1 << 4 << QDeclarativeTextInput::SelectWords << 1 << 7 << true; + QTest::newRow(" spacey <t(ex)t> |words") + << standard[4] << 11 << 13 << QDeclarativeTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365 + QTest::newRow("<( )>spacey text |words|ltr") + << standard[4] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << false; + QTest::newRow("<( )spacey> text |words|rtl") + << standard[4] << 1 << 0 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("spacey <text( )>|words|ltr") + << standard[4] << 14 << 15 << QDeclarativeTextInput::SelectWords << 10 << 15 << false; +// QTBUG-11365 +// QTest::newRow("spacey text<( )>|words|rtl") +// << standard[4] << 15 << 14 << QDeclarativeTextInput::SelectWords << 14 << 15 << false; + QTest::newRow("<()> spacey text |words") + << standard[4] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << false; + QTest::newRow(" spacey text <()>|words") + << standard[4] << 15 << 15 << QDeclarativeTextInput::SelectWords << 15 << 15 << false; } void tst_qdeclarativetextinput::moveCursorSelection() @@ -624,6 +653,11 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() QTest::addColumn<int>("selection2Start"); QTest::addColumn<int>("selection2End"); + // () contains the text selected by the cursor. + // <> contains the actual selection. + // ^ is the revised cursor position. + // {} contains the revised selection. + QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr") << standard[0] << 9 << 13 << 17 @@ -736,6 +770,50 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() << 11 << 9 << 5 << 8 << 13 << 1 << 13; + + QTest::newRow("{<(^} sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 0 + << 0 << 7 + << 0 << 0; + QTest::newRow("{<( ^}sp)acey> text |ltr") + << standard[4] + << 0 << 3 << 1 + << 0 << 7 + << 0 << 1; + QTest::newRow("<( {s^p)acey>} text |rtl") + << standard[4] + << 3 << 0 << 2 + << 0 << 7 + << 1 << 7; + QTest::newRow("<( {^sp)acey>} text |rtl") + << standard[4] + << 3 << 0 << 1 + << 0 << 7 + << 1 << 7; + + QTest::newRow(" spacey <te(xt {^)>}|rtl") + << standard[4] + << 15 << 12 << 15 + << 10 << 15 + << 15 << 15; +// QTBUG-11365 +// QTest::newRow(" spacey <te(xt{^ )>}|rtl") +// << standard[4] +// << 15 << 12 << 14 +// << 10 << 15 +// << 14 << 15; + QTest::newRow(" spacey {<te(x^t} )>|ltr") + << standard[4] + << 12 << 15 << 13 + << 10 << 15 + << 10 << 14; +// QTBUG-11365 +// QTest::newRow(" spacey {<te(xt^} )>|ltr") +// << standard[4] +// << 12 << 15 << 14 +// << 10 << 15 +// << 10 << 14; } void tst_qdeclarativetextinput::moveCursorSelectionSequence() @@ -952,6 +1030,10 @@ void tst_qdeclarativetextinput::positionAt() QVERIFY(diff < 5); #endif + int x = textinputObject->positionToRectangle(pos + 1).x() - 1; + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorBetweenCharacters), pos + 1); + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorOnCharacter), pos); + // Check without autoscroll... textinputObject->setAutoScroll(false); pos = textinputObject->positionAt(textinputObject->width()/2); @@ -964,6 +1046,29 @@ void tst_qdeclarativetextinput::positionAt() QVERIFY(diff < 5); #endif + x = textinputObject->positionToRectangle(pos + 1).x() - 1; + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorBetweenCharacters), pos + 1); + QCOMPARE(textinputObject->positionAt(x, QDeclarativeTextInput::CursorOnCharacter), pos); + + const qreal x0 = textinputObject->positionToRectangle(pos).x(); + const qreal x1 = textinputObject->positionToRectangle(pos + 1).x(); + + QString preeditText = textinputObject->text().mid(0, pos); + textinputObject->setText(textinputObject->text().mid(pos)); + textinputObject->setCursorPosition(0); + + QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>()); + QApplication::sendEvent(canvas, &inputEvent); + + // Check all points within the preedit text return the same position. + QCOMPARE(textinputObject->positionAt(0), 0); + QCOMPARE(textinputObject->positionAt(x0 / 2), 0); + QCOMPARE(textinputObject->positionAt(x0), 0); + + // Verify positioning returns to normal after the preedit text. + QCOMPARE(textinputObject->positionAt(x1), 1); + QCOMPARE(textinputObject->positionToRectangle(1).x(), x1); + delete canvas; } @@ -1142,6 +1247,24 @@ void tst_qdeclarativetextinput::inputMethods() QApplication::sendEvent(canvas, &event); QCOMPARE(input->text(), QString("My Hello world!")); + input->setCursorPosition(2); + event.setCommitString("Your", -2, 2); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Your Hello world!")); + QCOMPARE(input->cursorPosition(), 4); + + input->setCursorPosition(7); + event.setCommitString("Goodbye", -2, 5); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Your Goodbye world!")); + QCOMPARE(input->cursorPosition(), 12); + + input->setCursorPosition(8); + event.setCommitString("Our", -8, 4); + QApplication::sendEvent(canvas, &event); + QCOMPARE(input->text(), QString("Our Goodbye world!")); + QCOMPARE(input->cursorPosition(), 7); + delete canvas; } @@ -1270,6 +1393,42 @@ void tst_qdeclarativetextinput::copyAndPaste() { #endif } +void tst_qdeclarativetextinput::canPasteEmpty() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->clear(); + + QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }"; + QDeclarativeComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textInput = qobject_cast<QDeclarativeTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QLineControl lc; + bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0; + QCOMPARE(textInput->canPaste(), cp); + +#endif +} + +void tst_qdeclarativetextinput::canPaste() { +#ifndef QT_NO_CLIPBOARD + + QApplication::clipboard()->setText("Some text"); + + QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }"; + QDeclarativeComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textInput = qobject_cast<QDeclarativeTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QLineControl lc; + bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0; + QCOMPARE(textInput->canPaste(), cp); + +#endif +} + void tst_qdeclarativetextinput::passwordCharacter() { QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }"; @@ -1314,6 +1473,114 @@ void tst_qdeclarativetextinput::cursorDelegate() delete view; } +void tst_qdeclarativetextinput::cursorVisible() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QDeclarativeTextInput input; + QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool))); + + QCOMPARE(input.isCursorVisible(), false); + + input.setCursorVisible(true); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 1); + + input.setCursorVisible(false); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + input.setFocus(true); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + scene.addItem(&input); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 3); + + input.setFocus(false); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 4); + + input.setFocus(true); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 5); + + scene.clearFocus(); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 6); + + scene.setFocus(); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 7); + + view.clearFocus(); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 8); + + view.setFocus(); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 9); + + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) + QApplication::setActiveWindow(0); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0)); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 10); + + QApplication::setActiveWindow(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 11); +#endif +} + +void tst_qdeclarativetextinput::cursorRectangle() +{ + QString text = "Hello World!"; + + QDeclarativeTextInput input; + input.setText(text); + QFontMetricsF fm(input.font()); + input.setWidth(fm.width(text.mid(0, 5))); + + QRect r; + + for (int i = 0; i <= 5; ++i) { + input.setCursorPosition(i); + r = input.cursorRectangle(); + int textWidth = fm.width(text.mid(0, i)); + + QVERIFY(r.left() < textWidth); + QVERIFY(r.right() > textWidth); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } + + // Check the cursor rectangle remains within the input bounding rect when auto scrolling. + QVERIFY(r.left() < input.boundingRect().width()); + QVERIFY(r.right() >= input.width()); + + for (int i = 6; i < text.length(); ++i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } + + for (int i = text.length() - 2; i >= 0; --i) { + input.setCursorPosition(i); + r = input.cursorRectangle(); + QVERIFY(r.right() >= 0); + QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r); + } +} + void tst_qdeclarativetextinput::readOnly() { QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); @@ -1419,7 +1686,7 @@ QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1438,6 +1705,19 @@ public: return QInputContext::filterEvent(event); } + void update() { updateReceived = true; } + + void mouseHandler(int x, QMouseEvent *event) + { + cursor = x; + eventType = event->type(); + eventPosition = event->pos(); + eventGlobalPosition = event->globalPos(); + eventButton = event->button(); + eventButtons = event->buttons(); + eventModifiers = event->modifiers(); + } + void sendPreeditText(const QString &text, int cursor) { QList<QInputMethodEvent::Attribute> attributes; @@ -1450,6 +1730,14 @@ public: bool openInputPanelReceived; bool closeInputPanelReceived; + bool updateReceived; + int cursor; + QEvent::Type eventType; + QPoint eventPosition; + QPoint eventGlobalPosition; + Qt::MouseButton eventButton; + Qt::MouseButtons eventButtons; + Qt::KeyboardModifiers eventModifiers; }; void tst_qdeclarativetextinput::openInputPanelOnClick() @@ -1747,7 +2035,8 @@ void tst_qdeclarativetextinput::preeditAutoScroll() MyInputContext ic; view.setInputContext(&ic); QDeclarativeTextInput input; - input.setWidth(QFontMetricsF(input.font()).width(committedText)); + QFontMetricsF fm(input.font()); + input.setWidth(fm.width(committedText)); input.setText(committedText); input.setPos(0, 0); input.setFocus(true); @@ -1760,7 +2049,7 @@ void tst_qdeclarativetextinput::preeditAutoScroll() // test the text is scrolled so the preedit is visible. ic.sendPreeditText(preeditText.mid(0, 3), 1); QVERIFY(input.positionAt(0) != 0); - QCOMPARE(input.positionAt(input.width()), 8); + QVERIFY(input.cursorRectangle().left() < input.boundingRect().width()); // test the text is scrolled back when the preedit is removed. ic.sendEvent(QInputMethodEvent()); @@ -1769,26 +2058,31 @@ void tst_qdeclarativetextinput::preeditAutoScroll() // test if the preedit is larger than the text input that the // character preceding the cursor is still visible. + qreal x = input.positionToRectangle(0).x(); for (int i = 0; i < 3; ++i) { ic.sendPreeditText(preeditText, i + 1); - QCOMPARE(input.positionAt(0), 5 + i); + QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i))); + QVERIFY(input.positionToRectangle(0).x() < x); + x = input.positionToRectangle(0).x(); } for (int i = 1; i >= 0; --i) { ic.sendPreeditText(preeditText, i + 1); - QCOMPARE(input.positionAt(0), 5 + i); + QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i))); + QVERIFY(input.positionToRectangle(0).x() > x); + x = input.positionToRectangle(0).x(); } // Test incrementing the preedit cursor doesn't cause further // scrolling when right most text is visible. ic.sendPreeditText(preeditText, preeditText.length() - 3); - int position = input.positionAt(0); + x = input.positionToRectangle(0).x(); for (int i = 2; i >= 0; --i) { ic.sendPreeditText(preeditText, preeditText.length() - i); - QCOMPARE(input.positionAt(0), position); + QCOMPARE(input.positionToRectangle(0).x(), x); } for (int i = 1; i < 3; ++i) { ic.sendPreeditText(preeditText, preeditText.length() - i); - QCOMPARE(input.positionAt(0), position); + QCOMPARE(input.positionToRectangle(0).x(), x); } // Test disabling auto scroll. @@ -1800,6 +2094,217 @@ void tst_qdeclarativetextinput::preeditAutoScroll() QCOMPARE(input.positionAt(input.width()), 5); } +void tst_qdeclarativetextinput::preeditMicroFocus() +{ + QString preeditText = "super"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setPos(0, 0); + input.setAutoScroll(false); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QRect currentRect; + QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + + // Verify that the micro focus rect is positioned the same for position 0 as + // it would be if there was no preedit text. + ic.updateReceived = false; + ic.sendPreeditText(preeditText, 0); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif + + // Verify that the micro focus rect moves to the left as the cursor position + // is incremented. + for (int i = 1; i <= 5; ++i) { + ic.updateReceived = false; + ic.sendPreeditText(preeditText, i); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QVERIFY(previousRect.left() < currentRect.left()); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif + previousRect = currentRect; + } + + // Verify that if there is no preedit cursor then the micro focus rect is the + // same as it would be if it were positioned at the end of the preedit text. + ic.sendPreeditText(preeditText, 0); + ic.updateReceived = false; + ic.sendEvent(QInputMethodEvent(preeditText, QList<QInputMethodEvent::Attribute>())); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + QCOMPARE(ic.updateReceived, true); +#endif +} + +void tst_qdeclarativetextinput::inputContextMouseHandler() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(200); + input.setText(text.mid(0, 12)); + input.setCursorPosition(12); + input.setPos(0, 0); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QFontMetricsF fm(input.font()); + const qreal y = fm.height() / 2; + + QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); + QPoint position8 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 8)), y))); + QPoint position20 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 20)), y))); + QPoint position27 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 27)), y))); + QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); + QPoint globalposition8 = view.viewport()->mapToGlobal(position8); + QPoint globalposition20 = view.viewport()->mapToGlobal(position20); + QPoint globalposition27 = view.viewport()->mapToGlobal(position27); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one. + ic.eventType = QEvent::None; + + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + // And in the other direction. + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position20); + QCOMPARE(ic.eventGlobalPosition, globalposition20); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor >= 7 && ic.cursor <= 9); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; +} + +void tst_qdeclarativetextinput::inputMethodComposing() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(200); + input.setText(text.mid(0, 12)); + input.setCursorPosition(12); + input.setPos(0, 0); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged())); + + QCOMPARE(input.isInputMethodComposing(), false); + + ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(input.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>())); + QCOMPARE(input.isInputMethodComposing(), true); + QCOMPARE(spy.count(), 1); + + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(input.isInputMethodComposing(), false); + QCOMPARE(spy.count(), 2); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp index 19d7967..af54008 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp +++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp @@ -569,6 +569,11 @@ void tst_qdeclarativexmllistmodel::reload() QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int))); QSignalSpy spyCount(model, SIGNAL(countChanged())); + //reload multiple times to test the xml query aborting + model->reload(); + model->reload(); + QCoreApplication::processEvents(); + model->reload(); model->reload(); QTRY_COMPARE(spyCount.count(), 1); QTRY_COMPARE(spyInsert.count(), 1); @@ -839,9 +844,27 @@ void tst_qdeclarativexmllistmodel::threading() data3 += "name=C" + QString::number(i) + ",age=3" + QString::number(i) + ",sport=Curling;"; } + //Set the xml data multiple times with randomized order and mixed with multiple event loops + //to test the xml query reloading/aborting, the result should be stable. + m1->setXml(makeItemXmlAndData(data1)); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); m1->setXml(makeItemXmlAndData(data1)); m2->setXml(makeItemXmlAndData(data2)); + QCoreApplication::processEvents(); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); + m1->setXml(makeItemXmlAndData(data1)); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); QTRY_VERIFY(m1->count() == dataCount && m2->count() == dataCount && m3->count() == dataCount); diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 4b809fb..b2e9e6f 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -110,6 +110,7 @@ SUBDIRS=\ qmimedata \ qmouseevent_modal \ qmovie \ + qvolatileimage \ qnetworkaccessmanager_and_qprogressdialog \ qnetworkcachemetadata \ qnetworkdiskcache \ diff --git a/tests/auto/mediaobject/dummy/dummy.pro b/tests/auto/mediaobject/dummy/dummy.pro index 88b864b..c81411c 100644 --- a/tests/auto/mediaobject/dummy/dummy.pro +++ b/tests/auto/mediaobject/dummy/dummy.pro @@ -1,7 +1,7 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.6.4 + VERSION=4.7.3 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro b/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro new file mode 100644 index 0000000..fb8ecb0 --- /dev/null +++ b/tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_nativeimagehandleprovider.cpp +symbian { + LIBS += -lfbscli -lbitgdi + contains(QT_CONFIG, openvg): QT *= openvg +} diff --git a/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp b/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp new file mode 100644 index 0000000..3a315f2 --- /dev/null +++ b/tests/auto/nativeimagehandleprovider/tst_nativeimagehandleprovider.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** 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 test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtGui/private/qnativeimagehandleprovider_p.h> +#include <QScopedPointer> +#include <QPixmap> +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +#include <fbs.h> +#include <bitdev.h> +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#endif + +QPixmap pixmapFromNativeImageHandleProvider(QNativeImageHandleProvider *source) +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + if (!source) + return QPixmap(); + QScopedPointer<QPixmapData> pd(QPixmapData::create(0, 0, QPixmapData::PixmapType)); + pd->fromNativeType(source, QPixmapData::NativeImageHandleProvider); + return QPixmap(pd.take()); +#else + Q_UNUSED(source); + return QPixmap(); +#endif +} + +class DummyProvider : public QNativeImageHandleProvider +{ +public: + void get(void **handle, QString *type); + void release(void *handle, const QString &type); +}; + +void DummyProvider::get(void **handle, QString *type) +{ + *handle = (void *) 0x12345678; + *type = "some dummy type"; +} + +void DummyProvider::release(void *handle, const QString &type) +{ + Q_UNUSED(handle); + Q_UNUSED(type); +} + +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +class BitmapProvider : public QNativeImageHandleProvider +{ +public: + BitmapProvider() : bmp(0), refCount(0), w(50), h(60) { } + void get(void **handle, QString *type); + void release(void *handle, const QString &type); + + CFbsBitmap *bmp; + int refCount, w, h; + void *returnedHandle; + QString returnedType; +}; + +void BitmapProvider::get(void **handle, QString *type) +{ + // There may not be a release() if the get() fails so don't bother with + // refcounting in such cases. + if (bmp) + ++refCount; + returnedType = QLatin1String("CFbsBitmap"); + returnedHandle = bmp; + *handle = returnedHandle; + *type = returnedType; +} + +void BitmapProvider::release(void *handle, const QString &type) +{ + if (handle == returnedHandle && type == returnedType && returnedHandle) { + --refCount; + } +} +#endif // symbian & openvg + +class tst_NativeImageHandleProvider : public QObject +{ + Q_OBJECT + +public: + tst_NativeImageHandleProvider() { } + +private slots: + void create(); + void bitmap(); + void hibernate(); +}; + +void tst_NativeImageHandleProvider::create() +{ + QPixmap pm = pixmapFromNativeImageHandleProvider(0); + QVERIFY(pm.isNull()); + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + // Verify that null pixmap is properly returned when get() provides bogus results. + DummyProvider prov; + pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(pm.isNull()); + pm = QPixmap(); + } else { + QSKIP("Not openvg, skipping non-trivial tests", SkipSingle); + } +} + +void tst_NativeImageHandleProvider::bitmap() +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + BitmapProvider prov; + + // This should fail because of null ptr. + QPixmap pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(pm.isNull()); + pm = QPixmap(); + QCOMPARE(prov.refCount, 0); + + prov.bmp = new CFbsBitmap; + QCOMPARE(prov.bmp->Create(TSize(prov.w, prov.h), EColor16MAP), KErrNone); + CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(prov.bmp); + CBitmapContext *bitmapContext = 0; + QCOMPARE(bitmapDevice->CreateBitmapContext(bitmapContext), KErrNone); + TRgb symbianColor = TRgb(255, 200, 100); + bitmapContext->SetBrushColor(symbianColor); + bitmapContext->Clear(); + delete bitmapContext; + delete bitmapDevice; + + pm = pixmapFromNativeImageHandleProvider(&prov); + QVERIFY(!pm.isNull()); + QCOMPARE(pm.width(), prov.w); + QCOMPARE(pm.height(), prov.h); + QVERIFY(prov.refCount == 1); + QImage img = pm.toImage(); + QVERIFY(prov.refCount == 1); + QRgb pix = img.pixel(QPoint(1, 2)); + QCOMPARE(qRed(pix), symbianColor.Red()); + QCOMPARE(qGreen(pix), symbianColor.Green()); + QCOMPARE(qBlue(pix), symbianColor.Blue()); + + pm = QPixmap(); // should result in calling release + QCOMPARE(prov.refCount, 0); + delete prov.bmp; + } else { + QSKIP("Not openvg", SkipSingle); + } +#else + QSKIP("Not applicable", SkipSingle); +#endif +} + +void tst_NativeImageHandleProvider::hibernate() +{ +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + BitmapProvider prov; + prov.bmp = new CFbsBitmap; + QCOMPARE(prov.bmp->Create(TSize(prov.w, prov.h), EColor16MAP), KErrNone); + + QPixmap pm = pixmapFromNativeImageHandleProvider(&prov); + QCOMPARE(prov.refCount, 1); + + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pm.pixmapData()); + vgpd->hibernate(); + QCOMPARE(prov.refCount, 0); + + // Calling toVGImage() may cause some warnings as we don't have a gui initialized, + // but the only thing we care about here is get() being called. + vgpd->toVGImage(); + QCOMPARE(prov.refCount, 1); + + pm = QPixmap(); + QCOMPARE(prov.refCount, 0); + delete prov.bmp; + } else { + QSKIP("Not openvg", SkipSingle); + } +#else + QSKIP("Not applicable", SkipSingle); +#endif +} + +int main(int argc, char *argv[]) +{ + QApplication::setGraphicsSystem("openvg"); + QApplication app(argc, argv); + tst_NativeImageHandleProvider tc; + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_nativeimagehandleprovider.moc" diff --git a/tests/auto/other.pro b/tests/auto/other.pro index 3c8f856..40fa4a9 100644 --- a/tests/auto/other.pro +++ b/tests/auto/other.pro @@ -32,7 +32,8 @@ SUBDIRS=\ qvariant \ qwidget \ qworkspace \ - windowsmobile + windowsmobile \ + nativeimagehandleprovider contains(QT_CONFIG, OdfWriter):SUBDIRS += qzip qtextodfwriter mac: { diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index c1938b1..39f0677 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -169,6 +169,25 @@ public slots: int MyObject::callCount = 0; QVariantList MyObject::callArgs; +class MyObjectUnknownType: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject") + Q_CLASSINFO("D-Bus Introspection", "" +" <interface name=\"com.trolltech.QtDBus.MyObjectUnknownTypes\" >\n" +" <property access=\"readwrite\" type=\"~\" name=\"prop1\" />\n" +" <signal name=\"somethingHappened\" >\n" +" <arg direction=\"out\" type=\"~\" />\n" +" </signal>\n" +" <method name=\"ping\" >\n" +" <arg direction=\"in\" type=\"~\" name=\"ping\" />\n" +" <arg direction=\"out\" type=\"~\" name=\"ping\" />\n" +" </method>\n" +" <method name=\"regularMethod\" />\n" +" </interface>\n" + "") +}; + class Spy: public QObject { Q_OBJECT @@ -228,6 +247,7 @@ private slots: void notValidDerived(); void invalidAfterServiceOwnerChanged(); void introspect(); + void introspectUnknownTypes(); void callMethod(); void invokeMethod(); void invokeMethodWithReturn(); @@ -250,8 +270,7 @@ void tst_QDBusInterface::initTestCase() con.registerObject("/", &obj, QDBusConnection::ExportAllProperties | QDBusConnection::ExportAllSlots - | QDBusConnection::ExportAllInvokables - | QDBusConnection::ExportChildObjects); + | QDBusConnection::ExportAllInvokables); } void tst_QDBusInterface::notConnected() @@ -322,6 +341,27 @@ void tst_QDBusInterface::introspect() QVERIFY(mo->indexOfProperty("complexProp") != -1); } +void tst_QDBusInterface::introspectUnknownTypes() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + MyObjectUnknownType obj; + con.registerObject("/unknownTypes", &obj, QDBusConnection::ExportAllContents); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/unknownTypes"), + "com.trolltech.QtDBus.MyObjectUnknownTypes"); + + const QMetaObject *mo = iface.metaObject(); + QVERIFY(mo->indexOfMethod("regularMethod()") != -1); // this is the control + QVERIFY(mo->indexOfMethod("somethingHappened(QDBusRawType<0x7e>*)") != -1); + + QVERIFY(mo->indexOfMethod("ping(QDBusRawType<0x7e>*)") != -1); + int midx = mo->indexOfMethod("ping(QDBusRawType<0x7e>*)"); + QCOMPARE(mo->method(midx).typeName(), "QDBusRawType<0x7e>*"); + + QVERIFY(mo->indexOfProperty("prop1") != -1); + int pidx = mo->indexOfProperty("prop1"); + QCOMPARE(mo->property(pidx).typeName(), "QDBusRawType<0x7e>*"); +} + void tst_QDBusInterface::callMethod() { QDBusConnection con = QDBusConnection::sessionBus(); diff --git a/tests/auto/qdbusmarshall/test/test.pro b/tests/auto/qdbusmarshall/test/test.pro index 8901999..71fc656 100644 --- a/tests/auto/qdbusmarshall/test/test.pro +++ b/tests/auto/qdbusmarshall/test/test.pro @@ -5,4 +5,5 @@ TARGET = ../tst_qdbusmarshall QT = core QT += dbus - +LIBS += $$QT_LIBS_DBUS +QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index c05e49c..9bae6af 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#define DBUS_API_SUBJECT_TO_CHANGE #include <QtCore/QtCore> #include <QtTest/QtTest> #include <QtDBus/QtDBus> @@ -47,6 +46,8 @@ #include "common.h" #include <limits> +#include <dbus/dbus.h> + static const char serviceName[] = "com.trolltech.autotests.qpong"; static const char objectPath[] = "/com/trolltech/qpong"; static const char *interfaceName = serviceName; @@ -88,66 +89,59 @@ private slots: void sendCallErrors_data(); void sendCallErrors(); + void receiveUnknownType_data(); + void receiveUnknownType(); + private: QProcess proc; }; -struct UnregisteredType { }; -Q_DECLARE_METATYPE(UnregisteredType) - -class WaitForQPong: public QObject +class QDBusMessageSpy: public QObject { Q_OBJECT -public: - WaitForQPong(); - bool ok(); -public Q_SLOTS: - void ownerChange(const QString &name) +public slots: + Q_SCRIPTABLE int theSlot(const QDBusMessage &msg) { - if (name == serviceName) - loop.quit(); + list << msg; + return 42; } - -private: - QEventLoop loop; +public: + QList<QDBusMessage> list; }; -WaitForQPong::WaitForQPong() -{ - QDBusConnection con = QDBusConnection::sessionBus(); - if (!ok()) { - connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), - SLOT(ownerChange(QString))); - QTimer::singleShot(2000, &loop, SLOT(quit())); - loop.exec(); - } -} - -bool WaitForQPong::ok() -{ - return QDBusConnection::sessionBus().isConnected() && - QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName); -} +struct UnregisteredType { }; +Q_DECLARE_METATYPE(UnregisteredType) void tst_QDBusMarshall::initTestCase() { commonInit(); + QDBusConnection con = QDBusConnection::sessionBus(); #ifdef Q_OS_WIN proc.start("qpong"); #else proc.start("./qpong/qpong"); #endif - QVERIFY(proc.waitForStarted()); - - WaitForQPong w; - QVERIFY(w.ok()); - //QTest::qWait(2000); + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)) { + QVERIFY(proc.waitForStarted()); + + QVERIFY(con.isConnected()); + con.connect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)); + con.disconnect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + } } void tst_QDBusMarshall::cleanupTestCase() { proc.close(); - proc.kill(); + proc.terminate(); + proc.waitForFinished(200); } void tst_QDBusMarshall::sendBasic_data() @@ -700,6 +694,8 @@ void tst_QDBusMarshall::sendBasic() msg << value; QDBusMessage reply = con.call(msg); + QVERIFY2(reply.type() == QDBusMessage::ReplyMessage, + qPrintable(reply.errorName() + ": " + reply.errorMessage())); //qDebug() << reply; QCOMPARE(reply.arguments().count(), msg.arguments().count()); @@ -938,5 +934,145 @@ void tst_QDBusMarshall::sendCallErrors() QCOMPARE(reply.errorMessage(), errorMsg); } +void tst_QDBusMarshall::receiveUnknownType_data() +{ + QTest::addColumn<int>("receivedTypeId"); + QTest::newRow("in-call") << qMetaTypeId<void*>(); + QTest::newRow("type-variant") << qMetaTypeId<QDBusVariant>(); + QTest::newRow("type-array") << qMetaTypeId<QDBusArgument>(); + QTest::newRow("type-struct") << qMetaTypeId<QDBusArgument>(); + QTest::newRow("type-naked") << qMetaTypeId<void *>(); +} + +struct DisconnectRawDBus { + static void cleanup(DBusConnection *connection) + { + if (!connection) + return; + dbus_connection_close(connection); + dbus_connection_unref(connection); + } +}; +template <typename T, void (*unref)(T *)> struct GenericUnref +{ + static void cleanup(T *type) + { + if (!type) return; + unref(type); + } +}; + +// use these scoped types to avoid memory leaks if QVERIFY or QCOMPARE fails +typedef QScopedPointer<DBusConnection, DisconnectRawDBus> ScopedDBusConnection; +typedef QScopedPointer<DBusMessage, GenericUnref<DBusMessage, dbus_message_unref> > ScopedDBusMessage; +typedef QScopedPointer<DBusPendingCall, GenericUnref<DBusPendingCall, dbus_pending_call_unref> > ScopedDBusPendingCall; + +void tst_QDBusMarshall::receiveUnknownType() +{ +#ifndef DBUS_TYPE_UNIX_FD + QSKIP("Your system's D-Bus library is too old for this test", SkipAll); +#else + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + // this needs to be implemented in raw + // open a new connection to the bus daemon + DBusError error; + dbus_error_init(&error); + ScopedDBusConnection rawcon(dbus_bus_get_private(DBUS_BUS_SESSION, &error)); + QVERIFY2(rawcon.data(), error.name); + + // check if this bus supports passing file descriptors + if (!dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD)) + QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll); + + if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { + // create a call back to us containing a file descriptor + QDBusMessageSpy spy; + con.registerObject("/spyObject", &spy, QDBusConnection::ExportAllSlots); + ScopedDBusMessage msg(dbus_message_new_method_call(con.baseService().toLatin1(), "/spyObject", NULL, "theSlot")); + + int fd = fileno(stdout); + dbus_message_append_args(msg.data(), DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); + + // try to send to us + DBusPendingCall *pending_ptr; + dbus_connection_send_with_reply(rawcon.data(), msg.data(), &pending_ptr, 1000); + ScopedDBusPendingCall pending(pending_ptr); + + // check that it got sent + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now spin our event loop. We don't catch this call, so let's get the reply + QEventLoop loop; + QTimer::singleShot(200, &loop, SLOT(quit())); + loop.exec(); + + // now try to receive the reply + dbus_pending_call_block(pending.data()); + + // check that the spy received what it was supposed to receive + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().size(), 1); + QFETCH(int, receivedTypeId); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); + + msg.reset(dbus_pending_call_steal_reply(pending.data())); + QVERIFY(msg); + QCOMPARE(dbus_message_get_type(msg.data()), DBUS_MESSAGE_TYPE_METHOD_RETURN); + QCOMPARE(dbus_message_get_signature(msg.data()), DBUS_TYPE_INT32_AS_STRING); + + int retval; + QVERIFY(dbus_message_get_args(msg.data(), &error, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID)); + QCOMPARE(retval, 42); + } else { + // create a signal that we'll emit + static const char signalName[] = "signalName"; + static const char interfaceName[] = "local.interface.name"; + ScopedDBusMessage msg(dbus_message_new_signal("/", interfaceName, signalName)); + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); + + QDBusMessageSpy spy; + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &spy, SLOT(theSlot(QDBusMessage))); + + DBusMessageIter iter; + dbus_message_iter_init_append(msg.data(), &iter); + int fd = fileno(stdout); + + if (qstrcmp(QTest::currentDataTag(), "type-naked") == 0) { + // send naked + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd); + } else { + DBusMessageIter subiter; + if (qstrcmp(QTest::currentDataTag(), "type-variant") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-array") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-struct") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, 0, &subiter); + dbus_message_iter_append_basic(&subiter, DBUS_TYPE_UNIX_FD, &fd); + dbus_message_iter_close_container(&iter, &subiter); + } + + // send it + dbus_connection_send(rawcon.data(), msg.data(), 0); + + // check that it got sent + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now let's see what happens + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().count(), 1); + QFETCH(int, receivedTypeId); + //qDebug() << spy.list.at(0).arguments().at(0).typeName(); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); + } +#endif +} + QTEST_MAIN(tst_QDBusMarshall) #include "tst_qdbusmarshall.moc" diff --git a/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp b/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp index 25595c5..f83795c 100644 --- a/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp +++ b/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp @@ -287,11 +287,14 @@ void tst_QDBusXmlParser::methods_data() "</method>" << map; // one invalid arg + method.inputArgs << arg("~", "invalid"); + map.clear(); + map << method; QTest::newRow("two-in-one-invalid") << "<method name=\"Method\">" "<arg type=\"s\" direction=\"in\"/>" - "<arg type=\"~\" name=\"invalid\" direction=\"in\"/>" // this line should be ignored "<arg type=\"v\" direction=\"in\"/>" + "<arg type=\"~\" name=\"invalid\" direction=\"in\"/>" "</method>" << map; // one out argument @@ -380,8 +383,6 @@ void tst_QDBusXmlParser::methods() QFETCH(QString, xmlDataFragment); - if (strcmp(QTest::currentDataTag(), "two-in-one-invalid") == 0) - QTest::ignoreMessage(QtWarningMsg, "Invalid D-BUS type signature '~' found while parsing introspection"); QDBusIntrospection::Interface iface = QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter); @@ -390,9 +391,9 @@ void tst_QDBusXmlParser::methods() QFETCH(MethodMap, methodMap); MethodMap parsedMap = iface.methods; - QCOMPARE(methodMap.count(), parsedMap.count()); - QCOMPARE(methodMap, parsedMap); -} + QCOMPARE(parsedMap.count(), methodMap.count()); + QCOMPARE(parsedMap, methodMap); +} void tst_QDBusXmlParser::signals__data() { diff --git a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp index 0256b82..f66b849 100644 --- a/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp +++ b/tests/auto/qdesktopwidget/tst_qdesktopwidget.cpp @@ -127,7 +127,7 @@ void tst_QDesktopWidget::screenNumberForQWidget() QWidget widget; widget.show(); - QApplication::processEvents(); + QTest::qWaitForWindowShown(&widget); QVERIFY(widget.isVisible()); int widgetScreen = desktop.screenNumber(&widget); @@ -142,7 +142,9 @@ void tst_QDesktopWidget::screenNumberForQPoint() QRect allScreens; for (int i = 0; i < desktopWidget->numScreens(); ++i) { QRect screenGeometry = desktopWidget->screenGeometry(i); +#if !defined(Q_OS_SYMBIAN) QCOMPARE(desktopWidget->screenNumber(screenGeometry.center()), i); +#endif allScreens |= screenGeometry; } @@ -180,7 +182,6 @@ void tst_QDesktopWidget::screenGeometry() total = desktopWidget->screenGeometry(i); available = desktopWidget->availableGeometry(i); } - QVERIFY(total.contains(r)); } QTEST_MAIN(tst_QDesktopWidget) diff --git a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp index 2ca1a47..9875fb5 100644 --- a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp @@ -484,8 +484,6 @@ class ProgressTextTask : public RunFunctionTask<T> public: void runFunctor() { - while (this->isProgressUpdateNeeded() == false) - QTest::qSleep(1); this->setProgressValueAndText(1, QLatin1String("Foo 1")); while (this->isProgressUpdateNeeded() == false) @@ -495,6 +493,10 @@ public: while (this->isProgressUpdateNeeded() == false) QTest::qSleep(1); this->setProgressValueAndText(3, QLatin1String("Foo 3")); + + while (this->isProgressUpdateNeeded() == false) + QTest::qSleep(1); + this->setProgressValueAndText(4, QLatin1String("Foo 4")); } }; @@ -522,14 +524,16 @@ void tst_QFutureWatcher::progressText() QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(f.progressText(), QLatin1String("Foo 3")); - QCOMPARE(f.progressValue(), 3); + QCOMPARE(f.progressText(), QLatin1String("Foo 4")); + QCOMPARE(f.progressValue(), 4); QVERIFY(progressValues.contains(1)); QVERIFY(progressValues.contains(2)); QVERIFY(progressValues.contains(3)); + QVERIFY(progressValues.contains(4)); QVERIFY(progressTexts.contains(QLatin1String("Foo 1"))); QVERIFY(progressTexts.contains(QLatin1String("Foo 2"))); QVERIFY(progressTexts.contains(QLatin1String("Foo 3"))); + QVERIFY(progressTexts.contains(QLatin1String("Foo 4"))); } } diff --git a/tests/auto/qimagereader/images/corrupt-pixel-count.xpm b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm new file mode 100644 index 0000000..3a736ff --- /dev/null +++ b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm @@ -0,0 +1,11 @@ +/* XPM */ +static const char *marble_xpm[] = { +/* width height num_colors chars_per_pixel */ +"2 2 2 -2", +/* colors */ +"a c #adadad", +"b c #dedede", +/* pixels */ +"ab", +"ba" +}; diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 69e8ead..5321864 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -1399,6 +1399,9 @@ void tst_QImageReader::readFromResources_data() QTest::newRow("corrupt-pixels.xpm") << QString("corrupt-pixels.xpm") << QByteArray("xpm") << QSize(0, 0) << QString("QImage: XPM pixels missing on image line 3"); + QTest::newRow("corrupt-pixel-count.xpm") << QString("corrupt-pixel-count.xpm") + << QByteArray("xpm") << QSize(0, 0) + << QString(""); QTest::newRow("marble.xpm") << QString("marble.xpm") << QByteArray("xpm") << QSize(240, 240) << QString(""); diff --git a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp index 0c89013..91dfe47 100644 --- a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp +++ b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp @@ -171,16 +171,16 @@ void tst_QNetworkCookie::parseSingleCookie_data() QTest::newRow("with-value7") << "a = b" << cookie; QTest::newRow("with-value8") << "a = b " << cookie; - cookie.setValue(","); + cookie.setValue("\",\""); QTest::newRow("with-value-with-special1") << "a = \",\" " << cookie; - cookie.setValue(";"); + cookie.setValue("\";\""); QTest::newRow("with-value-with-special2") << "a = \";\" " << cookie; - cookie.setValue(" "); + cookie.setValue("\" \""); QTest::newRow("with-value-with-special3") << "a = \" \" " << cookie; - cookie.setValue("\""); - QTest::newRow("with-value-with-special3") << "a = \"\\\"\" " << cookie; - cookie.setValue("\"a, b; c\""); - QTest::newRow("with-value-with-special4") << "a = \"\\\"a, b; c\\\"\"" << cookie; + cookie.setValue("\"\\\"\""); + QTest::newRow("with-value-with-special4") << "a = \"\\\"\" " << cookie; + cookie.setValue("\"\\\"a, b; c\\\"\""); + QTest::newRow("with-value-with-special5") << "a = \"\\\"a, b; c\\\"\"" << cookie; cookie.setValue("b"); cookie.setSecure(true); @@ -568,10 +568,18 @@ void tst_QNetworkCookie::parseSingleCookie_data() cookie.setDomain("mail.yahoo.com"); QTest::newRow("network3") << "YM.LC=v=2&m=9993_262838_159_1558_1063_0_5649_4012_3776161073,9426_260205_549_1295_1336_0_5141_4738_3922731647,6733_258196_952_1364_643_0_3560_-1_0,3677_237633_1294_1294_19267_0_3244_29483_4102206176,1315_235149_1693_1541_941_0_3224_1691_1861378060,1858_214311_2100_1298_19538_0_2873_30900_716411652,6258_212007_2506_1285_1017_0_2868_3606_4288540264,3743_207884_2895_1362_2759_0_2545_7114_3388520216,2654_205253_3257_1297_1332_0_2504_4682_3048534803,1891_184881_3660_1291_19079_0_978_29178_2592538685&f=1&n=20&s=date&o=down&e=1196548712&b=Inbox&u=removed; path=/; domain=mail.yahoo.com" << cookie; - cookie = QNetworkCookie("__ac", "c2hhdXNtYW46U2FTYW80Wm8%3D"); + cookie = QNetworkCookie("__ac", "\"c2hhdXNtYW46U2FTYW80Wm8%3D\""); cookie.setPath("/"); cookie.setExpirationDate(QDateTime(QDate(2008, 8, 30), QTime(20, 21, 49), Qt::UTC)); QTest::newRow("network4") << "__ac=\"c2hhdXNtYW46U2FTYW80Wm8%3D\"; Path=/; Expires=Sat, 30 Aug 2008 20:21:49 +0000" << cookie; + + // linkedin.com sends cookies in quotes and expects the cookie in quotes + cookie = QNetworkCookie("leo_auth_token", "\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\""); + cookie.setPath("/"); + cookie.setExpirationDate(QDateTime(QDate(2011, 3, 1), QTime(10, 51, 14), Qt::UTC)); + QTest::newRow("network5") << "leo_auth_token=\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"; Version=1; Max-Age=1799; Expires=Tue, 01-Mar-2011 10:51:14 GMT; Path=/" << cookie; + + } void tst_QNetworkCookie::parseSingleCookie() diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index 4cf64f1..c9eca89 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -258,6 +258,8 @@ private slots: void QTBUG14614_gradientCacheRaceCondition(); void drawTextOpacity(); + void QTBUG17053_zeroDashPattern(); + private: void fillData(); void setPenColor(QPainter& p); @@ -4601,6 +4603,26 @@ void tst_QPainter::drawTextOpacity() QCOMPARE(image, copy); } +void tst_QPainter::QTBUG17053_zeroDashPattern() +{ + QImage image(32, 32, QImage::Format_RGB32); + image.fill(0xffffffff); + + QImage original = image; + + QVector<qreal> pattern; + pattern << qreal(0) << qreal(0); + + QPainter p(&image); + QPen pen(Qt::black, 2.0); + pen.setDashPattern(pattern); + + p.setPen(pen); + p.drawLine(0, 0, image.width(), image.height()); + + QCOMPARE(image, original); +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc" diff --git a/tests/auto/qpixmap/qpixmap.pro b/tests/auto/qpixmap/qpixmap.pro index ff8258f..e6a8257 100644 --- a/tests/auto/qpixmap/qpixmap.pro +++ b/tests/auto/qpixmap/qpixmap.pro @@ -25,6 +25,7 @@ wince*: { LIBS += -lfbscli.dll -lbitgdi.dll -lgdi.dll contains(QT_CONFIG, openvg) { LIBS += $$QMAKE_LIBS_OPENVG + QT *= openvg } } else { DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index 62a6eb4..bd9c26f 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -68,6 +68,10 @@ #include <fbs.h> #include <gdi.h> #include <bitdev.h> +#if !defined(QT_NO_OPENVG) +#include <QtOpenVG/qvg.h> +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#endif #endif #ifdef Q_WS_X11 @@ -185,6 +189,10 @@ private slots: void toImageDeepCopy(); void loadAsBitmapOrPixmap(); + +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) + void vgImageReadBack(); +#endif }; static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) @@ -1767,6 +1775,104 @@ void tst_QPixmap::toImageDeepCopy() QVERIFY(first != second); } +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_OPENVG) +Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap); +class FriendlyVGPixmapData : public QVGPixmapData +{ +public: + FriendlyVGPixmapData(PixelType type) : QVGPixmapData(type) { } + bool sourceIsNull() { return source.isNull(); } + friend QPixmap pixmapFromVGImage(VGImage image); +}; +QPixmap pixmapFromVGImage(VGImage image) +{ + if (image != VG_INVALID_HANDLE) { + int w = vgGetParameteri(image, VG_IMAGE_WIDTH); + int h = vgGetParameteri(image, VG_IMAGE_HEIGHT); + FriendlyVGPixmapData *pd = new FriendlyVGPixmapData(QPixmapData::PixmapType); + pd->resize(w, h); + pd->vgImage = image; + pd->recreate = false; + pd->prevSize = QSize(pd->w, pd->h); + return QPixmap(pd); + } + return QPixmap(); +} +class Content : public QWidget +{ +public: + void paintEvent(QPaintEvent *) { + QPainter painter(this); + QColor testPixel(qRgb(200, 150, 100)); + if (pm.isNull()) { // first phase: create a VGImage + painter.beginNativePainting(); + vgimage = vgCreateImage(VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); + QImage img(20, 10, QImage::Format_ARGB32_Premultiplied); + img.fill(qRgb(0, 0, 0)); + QPainter p(&img); + p.fillRect(0, 0, img.width(), img.height(), testPixel); + p.end(); + vgImageSubData(vgimage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height()); + // Now the area 0,0 20x10 (in OpenVG coords) is filled with some color. + painter.endNativePainting(); + } else { // second phase: check if readback works + painter.drawPixmap(0, 0, pm); + // Drawing should not cause readback, this is important for performance; + noreadback_ok = static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull(); + // However toImage() requires readback. + QImage img = pm.toImage(); + readback_ok = img.width() == pm.width(); + readback_ok &= img.height() == pm.height(); + readback_ok &= !static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull(); + uint pix = img.pixel(1, 1); + content_ok = qRed(pix) == testPixel.red(); + content_ok &= qGreen(pix) == testPixel.green(); + content_ok &= qBlue(pix) == testPixel.blue(); + pix = img.pixel(img.width() - 1, img.height() - 1); + content_ok &= qRed(pix) == 0; + content_ok &= qGreen(pix) == 0; + content_ok &= qBlue(pix) == 0; + } + } + int w; + int h; + VGImage vgimage; + QPixmap pm; + bool noreadback_ok; + bool readback_ok; + bool content_ok; +}; +void tst_QPixmap::vgImageReadBack() +{ + QPixmap tmp(10, 20); + if (tmp.pixmapData()->classId() == QPixmapData::OpenVGClass) { + Content c; + c.w = 50; + c.h = 60; + c.vgimage = VG_INVALID_HANDLE; + c.noreadback_ok = c.readback_ok = c.content_ok = false; + c.showFullScreen(); + QTest::qWaitForWindowShown(&c); + QVERIFY(c.vgimage != VG_INVALID_HANDLE); + QPixmap pm = pixmapFromVGImage(c.vgimage); + QVERIFY(!pm.isNull()); + QCOMPARE(pm.width(), c.w); + QCOMPARE(pm.height(), c.h); + QVERIFY(qPixmapToVGImage(pm) == c.vgimage); + QVERIFY(static_cast<FriendlyVGPixmapData *>(pm.pixmapData())->sourceIsNull()); + c.pm = pm; + // Make sure the second phase in paintEvent is executed too. + c.hide(); + c.showFullScreen(); + QTest::qWaitForWindowShown(&c); + QVERIFY(c.noreadback_ok); + QVERIFY(c.readback_ok); + QVERIFY(c.content_ok); + } else { + QSKIP("Not using openvg graphicssystem", SkipSingle); + } +} +#endif // Symbian & OpenVG QTEST_MAIN(tst_QPixmap) #include "tst_qpixmap.moc" diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 8de6fbc..6c89bcb 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -169,6 +169,7 @@ private slots: void nativeFunctionScopes(); void evaluateProgram(); void collectGarbageAfterConnect(); + void collectGarbageAfterNativeArguments(); void promoteThisObjectToQObjectInConstructor(); void qRegExpInport_data(); @@ -5040,6 +5041,16 @@ void tst_QScriptEngine::collectGarbageAfterConnect() QVERIFY(widget == 0); } +void tst_QScriptEngine::collectGarbageAfterNativeArguments() +{ + // QTBUG-17788 + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + QScriptValue arguments = ctx->argumentsObject(); + // Shouldn't crash when marking the arguments object. + collectGarbage_helper(eng); +} + static QScriptValue constructQObjectFromThisObject(QScriptContext *ctx, QScriptEngine *eng) { Q_ASSERT(ctx->isCalledAsConstructor()); diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index bce7281..dfe47cb 100644 --- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -144,6 +144,8 @@ private slots: void taskQTBUG_7537_appearsAndSort(); void taskQTBUG_7716_unnecessaryDynamicSorting(); void taskQTBUG_10287_unnecessaryMapCreation(); + void taskQTBUG_17812_resetInvalidate_data(); + void taskQTBUG_17812_resetInvalidate(); void testMultipleProxiesWithSelection(); void mapSelectionFromSource(); @@ -3213,5 +3215,60 @@ void tst_QSortFilterProxyModel::filteredColumns() } +void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate_data() +{ + QTest::addColumn<int>("test"); + QTest::addColumn<bool>("works"); + + QTest::newRow("nothing") << 0 << false; + QTest::newRow("reset") << 1 << true; + QTest::newRow("invalidate") << 2 << true; + QTest::newRow("invalidate_filter") << 3 << true; +} + +void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate() +{ + QFETCH(int, test); + QFETCH(bool, works); + + struct Proxy : QSortFilterProxyModel { + QString pattern; + virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const { + return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern); + } + void notifyChange(int test) { + switch (test) { + case 0: break; + case 1: reset(); break; + case 2: invalidate(); break; + case 3: invalidateFilter(); break; + } + } + }; + + QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis" + << "Elephant" << "Cochon" << "Serpent" + << "Mouton" << "Ecureuil" << "Mouche"); + Proxy proxy; + proxy.pattern = QString::fromLatin1("n"); + proxy.setSourceModel(&sourceModel); + + QCOMPARE(proxy.rowCount(), 5); + for (int i = 0; i < proxy.rowCount(); i++) { + QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n')); + } + + proxy.pattern = QString::fromLatin1("o"); + proxy.notifyChange(test); + + QCOMPARE(proxy.rowCount(), works ? 4 : 5); + bool ok = true; + for (int i = 0; i < proxy.rowCount(); i++) { + if (!proxy.data(proxy.index(i,0)).toString().contains('o')) + ok = false; + } + QCOMPARE(ok, works); +} + QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index f7d2180..bf68375 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -773,6 +773,27 @@ void tst_QSqlTableModel::removeInsertedRow() QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + // Now insert a row with a null, and check that removing it also works (QTBUG-15979 etc) + model.insertRow(1); + model.setData(model.index(1,0), 55); + model.setData(model.index(1,1), QString("null columns")); + model.setData(model.index(1,2), QVariant()); + + model.submitAll(); + + QCOMPARE(model.rowCount(), 4); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 55); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns")); + QCOMPARE(model.data(model.index(3, 2)).isNull(), true); + + QVERIFY(model.removeRow(3)); + model.submitAll(); + QCOMPARE(model.rowCount(), 3); + + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); } void tst_QSqlTableModel::removeInsertedRows() diff --git a/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp index a6499ff..92e8608 100644 --- a/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +++ b/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp @@ -201,6 +201,7 @@ void tst_QtConcurrentIterateKernel::noIterations() startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)).startBlocking(); } +QMutex threadsMutex; QSet<QThread *> threads; class ThrottleFor : public IterateKernel<TestIterator, void> { @@ -219,8 +220,10 @@ public: QThread *thread = QThread::currentThread(); - if (begin > 140 && end < 160) + if (begin > 140 && end < 160) { + QMutexLocker locker(&threadsMutex); threads.insert(thread); + } if (100 >= begin && 100 < end) { throttling = true; diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index d6cf54c..0f1ff66 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -123,7 +123,7 @@ private slots: void testLineBreakingAllSpaces(); void lineWidthFromBOM(); void textWidthVsWIdth(); - + void textWidthWithStackedTextEngine(); private: QFont testFont; @@ -1388,6 +1388,16 @@ void tst_QTextLayout::textWidthVsWIdth() } } +void tst_QTextLayout::textWidthWithStackedTextEngine() +{ + QString text = QString::fromUtf8("คลิก ถัดไป เพื่อดำเนินการต่อ"); + QTextLayout layout(text); + layout.beginLayout(); + QTextLine line = layout.createLine(); + layout.endLayout(); + QFontMetricsF fm(layout.font()); + QCOMPARE(line.naturalTextWidth(), fm.width(text)); +} QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" diff --git a/tests/auto/qvolatileimage/qvolatileimage.pro b/tests/auto/qvolatileimage/qvolatileimage.pro new file mode 100644 index 0000000..5a0a613 --- /dev/null +++ b/tests/auto/qvolatileimage/qvolatileimage.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +SOURCES += tst_qvolatileimage.cpp + +symbian { + TARGET.EPOCHEAPSIZE = 0x200000 0x800000 + LIBS += -lfbscli +} diff --git a/tests/auto/qvolatileimage/tst_qvolatileimage.cpp b/tests/auto/qvolatileimage/tst_qvolatileimage.cpp new file mode 100644 index 0000000..b91a150 --- /dev/null +++ b/tests/auto/qvolatileimage/tst_qvolatileimage.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** 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 test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtGui/qpainter.h> +#include <QtGui/qpaintengine.h> +#include <QtGui/private/qvolatileimage_p.h> +#ifdef Q_OS_SYMBIAN +#include <fbs.h> +#endif + +class tst_QVolatileImage : public QObject +{ + Q_OBJECT + +public: + tst_QVolatileImage() { } + +private slots: + void create(); + void ensureFormat(); + void dataAccess(); + void sharing(); + void paint(); + void fill(); + void copy(); + void bitmap(); +}; + +void tst_QVolatileImage::create() +{ + QVolatileImage nullImg; + QVERIFY(nullImg.isNull()); + + QVolatileImage img(100, 200, QImage::Format_ARGB32); + QVERIFY(!img.isNull()); + QCOMPARE(img.width(), 100); + QCOMPARE(img.height(), 200); + QCOMPARE(img.format(), QImage::Format_ARGB32); + QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); + QCOMPARE(img.hasAlphaChannel(), true); + QCOMPARE(img.depth(), 32); + + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + img = QVolatileImage(source); + QVERIFY(!img.isNull()); + QCOMPARE(img.width(), 12); + QCOMPARE(img.height(), 23); + QCOMPARE(img.format(), source.format()); + QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + QCOMPARE(img.hasAlphaChannel(), true); + QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel()); + QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel()); + QCOMPARE(img.depth(), 32); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVERIFY(!bmpimg.isNull()); + QCOMPARE(bmpimg.width(), 100); + QCOMPARE(bmpimg.height(), 50); + // Verify that we only did handle duplication, not pixel data copying. + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + // Check if content is still valid. + QImage copyimg = bmpimg.toImage(); + QCOMPARE(copyimg.format(), QImage::Format_ARGB32_Premultiplied); +#endif +} + +void tst_QVolatileImage::ensureFormat() +{ + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + QVolatileImage img(source); + QVERIFY(!img.isNull()); + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + + QVERIFY(img.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op + QVERIFY(img.imageRef() == source); + QVERIFY(img.toImage() == source); + QVERIFY(img.format() == QImage::Format_ARGB32_Premultiplied); + + QVERIFY(img.ensureFormat(QImage::Format_RGB32)); // new data under-the-hood + QVERIFY(img.imageRef() != source); + QVERIFY(img.toImage() != source); + QVERIFY(img.format() == QImage::Format_RGB32); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVERIFY(bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + + // A different format should cause data copying. + QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB32)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + const uchar *prevBits = bmpimg.constBits(); + + QVERIFY(bmpimg.ensureFormat(QImage::Format_RGB16)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QVERIFY(bmpimg.constBits() != prevBits); + prevBits = bmpimg.constBits(); + + QVERIFY(bmpimg.ensureFormat(QImage::Format_MonoLSB)); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QVERIFY(bmpimg.constBits() != prevBits); + + delete bmp; +#endif +} + +void tst_QVolatileImage::dataAccess() +{ + QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); + QVolatileImage img(source); + QVERIFY(!img.isNull()); + img.beginDataAccess(); + QVERIFY(img.constBits()); + QVERIFY(img.imageRef().constBits()); + QVERIFY(img.bits()); + QVERIFY(img.imageRef().bits()); + img.endDataAccess(); + + img = QVolatileImage(12, 23, QImage::Format_ARGB32); + img.beginDataAccess(); + QVERIFY(img.constBits() && img.bits()); + img.endDataAccess(); +} + +void tst_QVolatileImage::sharing() +{ + QVolatileImage img1(100, 100, QImage::Format_ARGB32); + QVolatileImage img2 = img1; + img1.beginDataAccess(); + img2.beginDataAccess(); + QVERIFY(img1.constBits() == img2.constBits()); + img2.endDataAccess(); + img1.endDataAccess(); + img1.imageRef(); // non-const call, should detach + img1.beginDataAccess(); + img2.beginDataAccess(); + QVERIFY(img1.constBits() != img2.constBits()); + img2.endDataAccess(); + img1.endDataAccess(); + + // toImage() should return a copy of the internal QImage. + // imageRef() is a reference to the internal QImage. + QVERIFY(img1.imageRef().constBits() != img1.toImage().constBits()); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor16MAP) == KErrNone); + QVolatileImage bmpimg(bmp); + QVolatileImage bmpimg2; + bmpimg2 = bmpimg; + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress()); + // Now force a detach, which should copy the pixel data under-the-hood. + bmpimg.imageRef(); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg2.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; +#endif +} + +bool fuzzyCompareImages(const QImage &image1, const QImage &image2, int tolerance) +{ + if (image1.bytesPerLine() != image2.bytesPerLine() + || image1.width() != image2.width() + || image1.height() != image2.height()) { + return false; + } + for (int i = 0; i < image1.height(); i++) { + const uchar *line1 = image1.scanLine(i); + const uchar *line2 = image2.scanLine(i); + int bytes = image1.bytesPerLine(); + for (int j = 0; j < bytes; j++) { + int delta = line1[j] - line2[j]; + if (qAbs(delta) > tolerance) + return false; + } + } + return true; +} + +void tst_QVolatileImage::paint() +{ +#ifdef Q_OS_SYMBIAN + QVolatileImage img(100, 100, QImage::Format_ARGB32); + img.beginDataAccess(); + img.imageRef().fill(QColor(Qt::green).rgba()); + QPainter p(&img.imageRef()); + p.drawRect(10, 10, 50, 50); + p.end(); + img.endDataAccess(); + QImage imgA = img.toImage(); + + // The following assumes that on openvg the pixmapdata is backed by QVolatileImage) + // (and that openvg is in use) + // It should pass with any engine nonetheless. + // See if painting into the underlying QImage succeeds. + QPixmap pm(100, 100); + if (pm.paintEngine()->type() == QPaintEngine::Raster) { + pm.fill(Qt::green); + QPainter pmp(&pm); + pmp.drawRect(10, 10, 50, 50); + pmp.end(); + QImage imgB = pm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + // Exercise the accelerated QVolatileImagePaintEngine::drawPixmap() a bit. + QPixmap targetPm(pm.size()); + targetPm.fill(Qt::black); + pmp.begin(&targetPm); + pmp.drawPixmap(QPointF(0, 0), pm); + pmp.end(); + imgB = targetPm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + // Now the overload taking rects. + targetPm.fill(Qt::black); + pmp.begin(&targetPm); + QRectF rect(QPointF(0, 0), pm.size()); + pmp.drawPixmap(rect, pm, rect); + pmp.end(); + imgB = targetPm.toImage(); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + } else { + QSKIP("Pixmaps not painted via raster, skipping paint test", SkipSingle); + } +#endif +} + +void tst_QVolatileImage::fill() +{ + QVolatileImage img(100, 100, QImage::Format_ARGB32_Premultiplied); + QColor col = QColor(10, 20, 30); + img.fill(col.rgba()); + QVERIFY(img.imageRef().pixel(1, 1) == col.rgba()); + QVERIFY(img.toImage().pixel(1, 1) == col.rgba()); + +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = static_cast<CFbsBitmap *>(img.duplicateNativeImage()); + QVERIFY(bmp); + TRgb pix; + bmp->GetPixel(pix, TPoint(1, 1)); + QCOMPARE(pix.Red(), col.red()); + QCOMPARE(pix.Green(), col.green()); + QCOMPARE(pix.Blue(), col.blue()); + delete bmp; +#endif +} + +void tst_QVolatileImage::copy() +{ + QVolatileImage img(100, 100, QImage::Format_RGB32); + img.beginDataAccess(); + img.imageRef().fill(QColor(Qt::green).rgba()); + QPainter p(&img.imageRef()); + p.drawRect(10, 10, 50, 50); + p.end(); + img.endDataAccess(); + + QVolatileImage img2(100, 100, QImage::Format_RGB32); + img2.copyFrom(&img, QRect()); + QImage imgA = img.toImage(); + QImage imgB = img2.toImage(); + QCOMPARE(imgA.size(), imgB.size()); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); + + img2 = QVolatileImage(20, 20, QImage::Format_RGB32); + img2.copyFrom(&img, QRect(5, 5, 20, 20)); + imgA = img.toImage().copy(5, 5, 20, 20); + imgB = img2.toImage(); + QCOMPARE(imgA.size(), imgB.size()); + QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); +} + +void tst_QVolatileImage::bitmap() +{ +#ifdef Q_OS_SYMBIAN + CFbsBitmap *bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(100, 50), EColor64K) == KErrNone); + QVolatileImage bmpimg(bmp); + CFbsBitmap *dupbmp = static_cast<CFbsBitmap *>(bmpimg.duplicateNativeImage()); + QVERIFY(dupbmp); + QVERIFY(dupbmp != bmp); + QCOMPARE(dupbmp->DataAddress(), bmp->DataAddress()); + delete dupbmp; + delete bmp; + bmpimg.beginDataAccess(); + qMemSet(bmpimg.bits(), 0, bmpimg.byteCount()); + qMemSet(bmpimg.bits(), 1, bmpimg.bytesPerLine() * bmpimg.height()); + bmpimg.endDataAccess(); + + // Test bgr->rgb conversion in case of EColor16M. + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16M) == KErrNone); + bmp->BeginDataAccess(); + TUint32 *addr = bmp->DataAddress(); + uint rgb = QColor(10, 20, 30).rgb(); + qMemCopy(bmp->DataAddress(), &rgb, 3); + bmp->EndDataAccess(); + TRgb symrgb; + bmp->GetPixel(symrgb, TPoint(0, 0)); + QVERIFY(symrgb.Red() == 10 && symrgb.Green() == 20 && symrgb.Blue() == 30); + bmpimg = QVolatileImage(bmp); + QVERIFY(bmpimg.toImage().pixel(0, 0) == rgb); + // check if there really was a conversion + bmp->BeginDataAccess(); + bmpimg.beginDataAccess(); + qMemCopy(&rgb, bmpimg.constBits(), 3); + uint rgb2 = rgb; + qMemCopy(&rgb2, bmp->DataAddress(), 3); + QVERIFY(rgb != rgb2); + bmpimg.endDataAccess(true); + bmp->EndDataAccess(true); + delete bmp; + + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EGray2) == KErrNone); + bmpimg = QVolatileImage(bmp); // inverts pixels, but should do it in place + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg.format(), QImage::Format_MonoLSB); + bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied); + QVERIFY(bmpimg.constBits() != (const uchar *) bmp->DataAddress()); + QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied); + delete bmp; + + // The following two formats must be optimal always. + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16MAP) == KErrNone); + bmpimg = QVolatileImage(bmp); + QCOMPARE(bmpimg.format(), QImage::Format_ARGB32_Premultiplied); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + bmpimg.ensureFormat(QImage::Format_ARGB32_Premultiplied); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + bmp = new CFbsBitmap; + QVERIFY(bmp->Create(TSize(101, 89), EColor16MU) == KErrNone); + bmpimg = QVolatileImage(bmp); + QCOMPARE(bmpimg.format(), QImage::Format_RGB32); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + bmpimg.ensureFormat(QImage::Format_RGB32); + QCOMPARE(bmpimg.constBits(), (const uchar *) bmp->DataAddress()); + delete bmp; + +#else + QSKIP("CFbsBitmap is only available on Symbian, skipping bitmap test", SkipSingle); +#endif +} + +int main(int argc, char *argv[]) +{ + QApplication::setGraphicsSystem("openvg"); + QApplication app(argc, argv); + tst_QVolatileImage tc; + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_qvolatileimage.moc" diff --git a/tests/auto/selftests/expected_cmptest.txt b/tests/auto/selftests/expected_cmptest.txt index fccaca3..d70815d 100644 --- a/tests/auto/selftests/expected_cmptest.txt +++ b/tests/auto/selftests/expected_cmptest.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Cmptest ********* -Config: Using QTest library 4.7.2, Qt 4.7.2 +Config: Using QTest library 4.7.3, Qt 4.7.3 PASS : tst_Cmptest::initTestCase() PASS : tst_Cmptest::compare_boolfuncs() PASS : tst_Cmptest::compare_pointerfuncs() diff --git a/tests/auto/selftests/expected_crashes_3.txt b/tests/auto/selftests/expected_crashes_3.txt index 2558f68..2aea62c 100644 --- a/tests/auto/selftests/expected_crashes_3.txt +++ b/tests/auto/selftests/expected_crashes_3.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Crashes ********* -Config: Using QTest library 4.7.2, Qt 4.7.2 +Config: Using QTest library 4.7.3, Qt 4.7.3 PASS : tst_Crashes::initTestCase() QFATAL : tst_Crashes::crash() Received signal 11 FAIL! : tst_Crashes::crash() Received a fatal error. diff --git a/tests/auto/selftests/expected_longstring.txt b/tests/auto/selftests/expected_longstring.txt index c56244b..1fe012f 100644 --- a/tests/auto/selftests/expected_longstring.txt +++ b/tests/auto/selftests/expected_longstring.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_LongString ********* -Config: Using QTest library 4.7.2, Qt 4.7.2 +Config: Using QTest library 4.7.3, Qt 4.7.3 PASS : tst_LongString::initTestCase() FAIL! : tst_LongString::failWithLongString() Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. diff --git a/tests/auto/selftests/expected_maxwarnings.txt b/tests/auto/selftests/expected_maxwarnings.txt index 7846435..cdd6ee8 100644 --- a/tests/auto/selftests/expected_maxwarnings.txt +++ b/tests/auto/selftests/expected_maxwarnings.txt @@ -1,5 +1,5 @@ ********* Start testing of MaxWarnings ********* -Config: Using QTest library 4.7.2, Qt 4.7.2 +Config: Using QTest library 4.7.3, Qt 4.7.3 PASS : MaxWarnings::initTestCase() QWARN : MaxWarnings::warn() 0 QWARN : MaxWarnings::warn() 1 diff --git a/tests/auto/selftests/expected_skip.txt b/tests/auto/selftests/expected_skip.txt index 5c9e497..490c140 100644 --- a/tests/auto/selftests/expected_skip.txt +++ b/tests/auto/selftests/expected_skip.txt @@ -1,5 +1,5 @@ ********* Start testing of tst_Skip ********* -Config: Using QTest library 4.7.2, Qt 4.7.2 +Config: Using QTest library 4.7.3, Qt 4.7.3 PASS : tst_Skip::initTestCase() SKIP : tst_Skip::test() skipping all Loc: [/home/user/depot/qt-git/mainline/tests/auto/selftests/skip/tst_skip.cpp(68)] diff --git a/tools/assistant/tools/assistant/doc/assistant.qdocconf b/tools/assistant/tools/assistant/doc/assistant.qdocconf index 57abeae..575b1e5 100644 --- a/tools/assistant/tools/assistant/doc/assistant.qdocconf +++ b/tools/assistant/tools/assistant/doc/assistant.qdocconf @@ -10,7 +10,7 @@ description = "Qt Assistant" HTML.{postheader,address} = "" HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ - "<td width=\"30%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ + "<td width=\"30%\" align=\"left\">Copyright © 2011 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ "<td width=\"40%\" align=\"center\">Trademarks</td>\n" \ - "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.7.2</div></td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.7.3</div></td>\n" \ "</tr></table></div></address>" diff --git a/tools/qdoc3/doc/files/qt.qdocconf b/tools/qdoc3/doc/files/qt.qdocconf index 44cfbc1..9b16233 100644 --- a/tools/qdoc3/doc/files/qt.qdocconf +++ b/tools/qdoc3/doc/files/qt.qdocconf @@ -22,7 +22,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.472 +qhp.Qt.namespace = com.trolltech.qt.473 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = @@ -36,9 +36,9 @@ qhp.Qt.extraFiles = classic.css \ images/dynamiclayouts-example.png \ images/stylesheet-coffee-plastique.png -qhp.Qt.filterAttributes = qt 4.7.2 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.7.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.2 +qhp.Qt.filterAttributes = qt 4.7.3 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.7.3 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.3 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf index 0e9a2a8..74ab67b 100644 --- a/tools/qdoc3/test/assistant.qdocconf +++ b/tools/qdoc3/test/assistant.qdocconf @@ -13,7 +13,7 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Assistant qhp.Assistant.file = assistant.qhp -qhp.Assistant.namespace = com.trolltech.assistant.472 +qhp.Assistant.namespace = com.trolltech.assistant.473 qhp.Assistant.virtualFolder = qdoc qhp.Assistant.indexTitle = Qt Assistant Manual qhp.Assistant.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Assistant.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Assistant.filterAttributes = qt 4.7.2 tools assistant +qhp.Assistant.filterAttributes = qt 4.7.3 tools assistant qhp.Assistant.customFilters.Assistant.name = Qt Assistant Manual qhp.Assistant.customFilters.Assistant.filterAttributes = qt tools assistant qhp.Assistant.subprojects = manual examples diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf index 637399b..42dbc20 100644 --- a/tools/qdoc3/test/designer.qdocconf +++ b/tools/qdoc3/test/designer.qdocconf @@ -13,7 +13,7 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Designer qhp.Designer.file = designer.qhp -qhp.Designer.namespace = com.trolltech.designer.472 +qhp.Designer.namespace = com.trolltech.designer.473 qhp.Designer.virtualFolder = qdoc qhp.Designer.indexTitle = Qt Designer Manual qhp.Designer.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Designer.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Designer.filterAttributes = qt 4.7.2 tools designer +qhp.Designer.filterAttributes = qt 4.7.3 tools designer qhp.Designer.customFilters.Designer.name = Qt Designer Manual qhp.Designer.customFilters.Designer.filterAttributes = qt tools designer qhp.Designer.subprojects = manual examples diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf index 8ee298e..7c01023 100644 --- a/tools/qdoc3/test/linguist.qdocconf +++ b/tools/qdoc3/test/linguist.qdocconf @@ -13,7 +13,7 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Linguist qhp.Linguist.file = linguist.qhp -qhp.Linguist.namespace = com.trolltech.linguist.472 +qhp.Linguist.namespace = com.trolltech.linguist.473 qhp.Linguist.virtualFolder = qdoc qhp.Linguist.indexTitle = Qt Linguist Manual qhp.Linguist.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.Linguist.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Linguist.filterAttributes = qt 4.7.2 tools linguist +qhp.Linguist.filterAttributes = qt 4.7.3 tools linguist qhp.Linguist.customFilters.Linguist.name = Qt Linguist Manual qhp.Linguist.customFilters.Linguist.filterAttributes = qt tools linguist qhp.Linguist.subprojects = manual examples diff --git a/tools/qdoc3/test/qdeclarative.qdocconf b/tools/qdoc3/test/qdeclarative.qdocconf index e68a935..12c939c 100644 --- a/tools/qdoc3/test/qdeclarative.qdocconf +++ b/tools/qdoc3/test/qdeclarative.qdocconf @@ -21,7 +21,7 @@ edition.DesktopLight.groups = -graphicsview-api qhp.projects = Qml qhp.Qml.file = qml.qhp -qhp.Qml.namespace = com.trolltech.qml.472 +qhp.Qml.namespace = com.trolltech.qml.473 qhp.Qml.virtualFolder = qdoc qhp.Qml.indexTitle = Qml Reference @@ -61,9 +61,9 @@ qhp.Qml.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.Qml.filterAttributes = qt 4.7.2 qtrefdoc -qhp.Qml.customFilters.Qt.name = Qt 4.7.2 -qhp.Qml.customFilters.Qt.filterAttributes = qt 4.7.2 +qhp.Qml.filterAttributes = qt 4.7.3 qtrefdoc +qhp.Qml.customFilters.Qt.name = Qt 4.7.3 +qhp.Qml.customFilters.Qt.filterAttributes = qt 4.7.3 qhp.Qml.subprojects = classes qhp.Qml.subprojects.classes.title = Elements qhp.Qml.subprojects.classes.indexTitle = Qml Elements diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf index b5bc96c..b7d1299 100644 --- a/tools/qdoc3/test/qmake.qdocconf +++ b/tools/qdoc3/test/qmake.qdocconf @@ -13,7 +13,7 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = qmake qhp.qmake.file = qmake.qhp -qhp.qmake.namespace = com.trolltech.qmake.472 +qhp.qmake.namespace = com.trolltech.qmake.473 qhp.qmake.virtualFolder = qdoc qhp.qmake.indexTitle = QMake Manual qhp.qmake.extraFiles = images/bg_l.png \ @@ -50,7 +50,7 @@ qhp.qmake.extraFiles = images/bg_l.png \ style/style_ie8.css \ style/style.css -qhp.qmake.filterAttributes = qt 4.7.2 tools qmake +qhp.qmake.filterAttributes = qt 4.7.3 tools qmake qhp.qmake.customFilters.qmake.name = qmake Manual qhp.qmake.customFilters.qmake.filterAttributes = qt tools qmake qhp.qmake.subprojects = manual diff --git a/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf b/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf index 24696d5..a4d0653 100644 --- a/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf +++ b/tools/qdoc3/test/qt-build-docs_ja_JP.qdocconf @@ -17,15 +17,15 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.472 +qhp.Qt.namespace = com.trolltech.qt.473 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = Qt qhp.Qt.indexTitle = Qt qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.2 qtrefdoc ja_JP -qhp.Qt.customFilters.Qt.name = Qt 4.7.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.2 +qhp.Qt.filterAttributes = qt 4.7.3 qtrefdoc ja_JP +qhp.Qt.customFilters.Qt.name = Qt 4.7.3 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.3 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf index 7789bf7..818b5c5 100644 --- a/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf +++ b/tools/qdoc3/test/qt-build-docs_zh_CN.qdocconf @@ -17,15 +17,15 @@ indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.472 +qhp.Qt.namespace = com.trolltech.qt.473 qhp.Qt.virtualFolder = qdoc qhp.Qt.title = 教程 qhp.Qt.indexTitle = 教程 qhp.Qt.selectors = fake:example -qhp.Qt.filterAttributes = qt 4.7.2 qtrefdoc zh_CN -qhp.Qt.customFilters.Qt.name = Qt 4.7.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.2 +qhp.Qt.filterAttributes = qt 4.7.3 qtrefdoc zh_CN +qhp.Qt.customFilters.Qt.name = Qt 4.7.3 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.3 # Files not referenced in any qdoc file (last four are needed by qtdemo) # See also extraimages.HTML diff --git a/tools/qdoc3/test/qt-project.qdocconf b/tools/qdoc3/test/qt-project.qdocconf index 3ed7cff..2da0e90 100644 --- a/tools/qdoc3/test/qt-project.qdocconf +++ b/tools/qdoc3/test/qt-project.qdocconf @@ -6,7 +6,7 @@ include(qt-defines.qdocconf) project = Qt description = Qt Reference Documentation url = http://qt.nokia.com/doc/4.7 -version = 4.7.2 +version = 4.7.3 sourceencoding = UTF-8 outputencoding = UTF-8 @@ -15,14 +15,14 @@ naturallanguage = en_US qhp.projects = Qt qhp.Qt.file = qt.qhp -qhp.Qt.namespace = com.trolltech.qt.472 +qhp.Qt.namespace = com.trolltech.qt.473 qhp.Qt.virtualFolder = qdoc qhp.Qt.indexTitle = Qt Reference Documentation qhp.Qt.indexRoot = -qhp.Qt.filterAttributes = qt 4.7.2 qtrefdoc -qhp.Qt.customFilters.Qt.name = Qt 4.7.2 -qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.2 +qhp.Qt.filterAttributes = qt 4.7.3 qtrefdoc +qhp.Qt.customFilters.Qt.name = Qt 4.7.3 +qhp.Qt.customFilters.Qt.filterAttributes = qt 4.7.3 qhp.Qt.subprojects = classes overviews examples qhp.Qt.subprojects.classes.title = Classes qhp.Qt.subprojects.classes.indexTitle = Qt's Classes diff --git a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp index e1c0460..ac32995 100644 --- a/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp +++ b/tools/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp @@ -111,6 +111,8 @@ void QMeeGoGraphicsSystemHelper::switchToRaster() QApplication *app = static_cast<QApplication *>(QCoreApplication::instance()); app->setGraphicsSystem(QLatin1String("raster")); + QMeeGoRuntime::invalidateLiveSurfaces(); + QMeeGoSwitchEvent didSwitchEvent(QLatin1String("raster"), QMeeGoSwitchEvent::DidSwitch); foreach (QWidget *widget, QApplication::topLevelWidgets()) QCoreApplication::sendEvent(widget, &didSwitchEvent); diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp index c32b654..7c81d51 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.cpp +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.cpp @@ -65,6 +65,7 @@ typedef bool (*QMeeGoLiveTextureReleaseFunc) (QPixmap*, QImage *i); typedef Qt::HANDLE (*QMeeGoLiveTextureGetHandleFunc) (QPixmap*); typedef void* (*QMeeGoCreateFenceSyncFunc) (void); typedef void (*QMeeGoDestroyFenceSyncFunc) (void *fs); +typedef void (*QMeeGoInvalidateLiveSurfacesFunc) (void); static QMeeGoImageToEglSharedImageFunc qt_meego_image_to_egl_shared_image = NULL; static QMeeGoPixmapDataFromEglSharedImageFunc qt_meego_pixmapdata_from_egl_shared_image = NULL; @@ -81,6 +82,7 @@ static QMeeGoLiveTextureReleaseFunc qt_meego_live_texture_release = NULL; static QMeeGoLiveTextureGetHandleFunc qt_meego_live_texture_get_handle = NULL; static QMeeGoCreateFenceSyncFunc qt_meego_create_fence_sync = NULL; static QMeeGoDestroyFenceSyncFunc qt_meego_destroy_fence_sync = NULL; +static QMeeGoInvalidateLiveSurfacesFunc qt_meego_invalidate_live_surfaces = NULL; void QMeeGoRuntime::initialize() { @@ -109,13 +111,14 @@ void QMeeGoRuntime::initialize() qt_meego_live_texture_get_handle = (QMeeGoLiveTextureGetHandleFunc) library.resolve("qt_meego_live_texture_get_handle"); qt_meego_create_fence_sync = (QMeeGoCreateFenceSyncFunc) library.resolve("qt_meego_create_fence_sync"); qt_meego_destroy_fence_sync = (QMeeGoDestroyFenceSyncFunc) library.resolve("qt_meego_destroy_fence_sync"); + qt_meego_invalidate_live_surfaces = (QMeeGoInvalidateLiveSurfacesFunc) library.resolve("qt_meego_invalidate_live_surfaces"); if (qt_meego_image_to_egl_shared_image && qt_meego_pixmapdata_from_egl_shared_image && qt_meego_pixmapdata_with_gl_texture && qt_meego_destroy_egl_shared_image && qt_meego_update_egl_shared_image_pixmap && qt_meego_set_surface_fixed_size && qt_meego_set_surface_scaling && qt_meego_set_translucent && qt_meego_pixmapdata_with_new_live_texture && qt_meego_pixmapdata_from_live_texture_handle && qt_meego_live_texture_lock && qt_meego_live_texture_release && qt_meego_live_texture_get_handle && - qt_meego_create_fence_sync && qt_meego_destroy_fence_sync) + qt_meego_create_fence_sync && qt_meego_destroy_fence_sync && qt_meego_invalidate_live_surfaces) { qDebug("Successfully resolved MeeGo graphics system: %s %s\n", qPrintable(libraryPrivate->fileName), qPrintable(libraryPrivate->fullVersion)); } else { @@ -232,3 +235,10 @@ void QMeeGoRuntime::destroyFenceSync(void *fs) Q_ASSERT(qt_meego_destroy_fence_sync); qt_meego_destroy_fence_sync(fs); } + +void QMeeGoRuntime::invalidateLiveSurfaces() +{ + ENSURE_INITIALIZED; + Q_ASSERT(qt_meego_invalidate_live_surfaces); + qt_meego_invalidate_live_surfaces(); +} diff --git a/tools/qmeegographicssystemhelper/qmeegoruntime.h b/tools/qmeegographicssystemhelper/qmeegoruntime.h index bdc4eef..b91efae 100644 --- a/tools/qmeegographicssystemhelper/qmeegoruntime.h +++ b/tools/qmeegographicssystemhelper/qmeegoruntime.h @@ -62,6 +62,7 @@ public: static Qt::HANDLE getLiveTextureHandle(QPixmap *pixmap); static void* createFenceSync(); static void destroyFenceSync(void *fs); + static void invalidateLiveSurfaces(); private: static bool initialized; diff --git a/tools/qmeegographicssystemhelper/qmeegoswitchevent.cpp b/tools/qmeegographicssystemhelper/qmeegoswitchevent.cpp index 0ab272f..b833e31 100644 --- a/tools/qmeegographicssystemhelper/qmeegoswitchevent.cpp +++ b/tools/qmeegographicssystemhelper/qmeegoswitchevent.cpp @@ -65,4 +65,4 @@ QEvent::Type QMeeGoSwitchEvent::eventNumber() switchEventNumber = QEvent::registerEventType(); return (QEvent::Type) switchEventNumber; -}
\ No newline at end of file +} diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri index 08cd506..cfc74af 100644 --- a/tools/qml/qml.pri +++ b/tools/qml/qml.pri @@ -19,18 +19,18 @@ SOURCES += $$PWD/qmlruntime.cpp \ RESOURCES = $$PWD/browser/browser.qrc \ $$PWD/startup/startup.qrc -symbian: { - contains(QT_CONFIG, s60): { +symbian { + contains(QT_CONFIG, s60) { LIBS += -lavkon -lcone } !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { LIBS += -lsensrvclient -lsensrvutil - } - !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2): { SOURCES += $$PWD/deviceorientation_symbian.cpp - FORMS = $$PWD/recopts.ui \ - $$PWD/proxysettings.ui + } else { + SOURCES += $$PWD/deviceorientation.cpp } + FORMS = $$PWD/recopts.ui \ + $$PWD/proxysettings.ui } else:maemo5 { QT += dbus HEADERS += $$PWD/texteditautoresizer_maemo5.h diff --git a/tools/shared/symbian/epocroot.cpp b/tools/shared/symbian/epocroot.cpp index e128cd2..5e6bc12 100644 --- a/tools/shared/symbian/epocroot.cpp +++ b/tools/shared/symbian/epocroot.cpp @@ -99,6 +99,11 @@ static void fixEpocRoot(QString &path) if (!path.size() || path[path.size()-1] != QLatin1Char('/')) { path += QLatin1Char('/'); } +#ifdef Q_OS_WIN32 + // Make sure we have drive letter in epocroot + if (path.startsWith(QLatin1Char('/'))) + path.prepend(QDir::currentPath().left(2)); +#endif } /** |