From 71bcd941d577097ca99900554386c9f12d4353e3 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 13 Sep 2011 15:33:31 +0200 Subject: Add missing checks for httpReply in QNetworkHttpBackend. httpReply is not guaranteed to be non-null. Adding missing checks for methods that can be called from outside the class. Reviewed-By: Peter Hartmann --- src/network/access/qnetworkaccesshttpbackend.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index abef8ab..aa477fb 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -737,7 +737,7 @@ void QNetworkAccessHttpBackend::readFromHttp() void QNetworkAccessHttpBackend::replyFinished() { - if (httpReply->bytesAvailable()) + if (!httpReply || httpReply->bytesAvailable()) // we haven't read everything yet. Wait some more. return; @@ -788,6 +788,9 @@ void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode) void QNetworkAccessHttpBackend::replyHeaderChanged() { + if (!httpReply) + return; + setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, httpReply->isPipeliningUsed()); // reconstruct the HTTP header @@ -1128,7 +1131,7 @@ bool QNetworkAccessHttpBackend::canResume() const return false; // Can only resume if server/resource supports Range header. - if (httpReply->headerField("Accept-Ranges", "none") == "none") + if (!httpReply || httpReply->headerField("Accept-Ranges", "none") == "none") return false; // We only support resuming for byte ranges. -- cgit v0.12 From c4cab7199590cc6b1901334e8ff604cd876fccee Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 14 Sep 2011 14:07:06 +0100 Subject: Prevent crash when cache is changed on the fly Calling QNetworkAccessManager::setCache while there were requests being processed using the existing cache caused crashes due to deleting the old cache invalidating pointers to the cache data streams (QTemporaryFile in case of QNetworkDiskCache). Using pointer to deleted data caused a crash in some cases. It has undefined behaviour because the memory may have been overwritten or decommitted. To fix this, use the deleted signal to notify QNetworkReplyImpl that the cache has been destroyed. It then clears the pointer to the data stream and disables caching. This avoids the crash that previously happened when trying to write to the cache file. Task-number: QT-5252 Reviewed-by: Peter Hartmann --- src/network/access/qnetworkreplyimpl.cpp | 23 +++++++++++++++++++---- src/network/access/qnetworkreplyimpl_p.h | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 8a0a944..81cd548 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -446,6 +446,7 @@ bool QNetworkReplyImplPrivate::isCachingEnabled() const void QNetworkReplyImplPrivate::setCachingEnabled(bool enable) { + Q_Q(QNetworkReplyImpl); if (!enable && !cacheEnabled) return; // nothing to do if (enable && cacheEnabled) @@ -468,15 +469,27 @@ void QNetworkReplyImplPrivate::setCachingEnabled(bool enable) networkCache()->remove(url); cacheSaveDevice = 0; cacheEnabled = false; + QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed())); } } +void QNetworkReplyImplPrivate::_q_cacheDestroyed() +{ + //destruction of cache invalidates cacheSaveDevice + cacheSaveDevice = 0; + cacheEnabled = false; +} + void QNetworkReplyImplPrivate::completeCacheSave() { - if (cacheEnabled && errorCode != QNetworkReplyImpl::NoError) { - networkCache()->remove(url); - } else if (cacheEnabled && cacheSaveDevice) { - networkCache()->insert(cacheSaveDevice); + Q_Q(QNetworkReplyImpl); + if (cacheEnabled) { + if (errorCode != QNetworkReplyImpl::NoError) { + networkCache()->remove(url); + } else if (cacheSaveDevice) { + networkCache()->insert(cacheSaveDevice); + } + QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed())); } cacheSaveDevice = 0; cacheEnabled = false; @@ -536,6 +549,8 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice() networkCache()->remove(url); cacheSaveDevice = 0; cacheEnabled = false; + } else { + q->connect(networkCache(), SIGNAL(destroyed()), SLOT(_q_cacheDestroyed())); } } diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 31da297..0e4ff8f 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -103,6 +103,7 @@ public: Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) #endif + Q_PRIVATE_SLOT(d_func(), void _q_cacheDestroyed()) }; class QNetworkReplyImplPrivate: public QNetworkReplyPrivate @@ -139,6 +140,7 @@ public: void _q_networkSessionConnected(); void _q_networkSessionFailed(); #endif + void _q_cacheDestroyed(); void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); -- cgit v0.12 From 5571dbea919d1f122e7331cb0214e584c89efcb9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 16:47:39 +0000 Subject: Fix RConnection handle leak in symbian bearer plugin The implementation was opening RConnection handles on top of previous instances, and not closing RConnection handles. Both of these cause a resource leak in the socket server which cannot clean up the connection until the Qt process has exited. After a lot of this (which could be triggered by the QNetworkReply auto test), the socket server may run out of memory resulting in all socket operations failing. Reviewed-by: Markus Goetz (cherry picked from commit f5e7b6c64caa67bf11fa9754114d686da73b22d6) --- .../bearer/symbian/qnetworksession_impl.cpp | 97 +++++++++------------- src/plugins/bearer/symbian/qnetworksession_impl.h | 1 + 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 5639c4f..fc6e141 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -89,33 +89,43 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) TRAP_IGNORE(iConnectionMonitor.ConnectL()); } -QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +void QNetworkSessionPrivateImpl::closeHandles() { - isOpen = false; - isOpening = false; - // Cancel Connection Progress Notifications first. - // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start() + // Note: ConnectionNotifier must be destroyed before RConnection::Close() // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification() delete ipConnectionNotifier; ipConnectionNotifier = NULL; #ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } + // mobility monitor must be deleted before RConnection is closed + delete iMobility; + iMobility = NULL; #endif - // Cancel possible RConnection::Start() + // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress Cancel(); - iSocketServ.Close(); + //close any open connection (note Close twice is safe in case Cancel did it above) + iConnection.Close(); // Close global 'Open C' RConnection // Clears also possible unsetdefaultif() flags. setdefaultif(0); iConnectionMonitor.Close(); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) + << " - handles closed"; +#endif + iSocketServ.Close(); +} + +QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +{ + isOpen = false; + isOpening = false; + + closeHandles(); iOpenCLibrary.Close(); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) @@ -166,7 +176,7 @@ void QNetworkSessionPrivateImpl::configurationAdded(QNetworkConfigurationPrivate #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "configurationAdded IAP: " - << toSymbianConfig(privateConfiguration(config))->numericIdentifier(); + << toSymbianConfig(config)->numericIdentifier(); #endif syncStateWithInterface(); @@ -372,7 +382,8 @@ void QNetworkSessionPrivateImpl::open() syncStateWithInterface(); return; } - + + Q_ASSERT(!iConnection.SubSessionHandle()); error = iConnection.Open(iSocketServ); if (error != KErrNone) { // Could not open RConnection @@ -414,8 +425,8 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - iConnection.Start(pref, iStatus); if (!IsActive()) { + iConnection.Start(pref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -442,8 +453,8 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - iConnection.Start(snapPref, iStatus); if (!IsActive()) { + iConnection.Start(snapPref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -453,8 +464,8 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - iConnection.Start(iStatus); if (!IsActive()) { + iConnection.Start(iStatus); SetActive(); } newState(QNetworkSession::Connecting); @@ -465,9 +476,7 @@ void QNetworkSessionPrivateImpl::open() isOpening = false; iError = QNetworkSession::UnknownSessionError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); syncStateWithInterface(); } } @@ -521,21 +530,10 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) serviceConfig = QNetworkConfiguration(); -#ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } -#endif + closeHandles(); - if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) { - ipConnectionNotifier->StopNotifications(); - // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate - iHandleStateNotificationsFromManager = true; - } - - Cancel(); // closes iConnection - iSocketServ.Close(); + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; // Close global 'Open C' RConnection. If OpenC supports, // close the defaultif for good to avoid difficult timing @@ -759,12 +757,14 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo* } } -void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) +void QNetworkSessionPrivateImpl::Error(TInt aError) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "roaming Error() occurred, isOpen is: " << isOpen; + << "roaming Error() occurred" << aError << ", isOpen is: " << isOpen; #endif + if (aError == KErrCancel) + return; //avoid recursive deletion if (isOpen) { isOpen = false; isOpening = false; @@ -772,10 +772,7 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::RoamingError; emit QNetworkSessionPrivate::error(iError); - Cancel(); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); QT_TRY { syncStateWithInterface(); // In some cases IAP is still in Connected state when @@ -1102,18 +1099,13 @@ void QNetworkSessionPrivateImpl::RunL() isOpening = false; iError = QNetworkSession::UnknownSessionError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); if (!newActiveConfig.isValid()) { // No valid configuration, bail out. // Status updates from QNCM won't be received correctly // because there is no configuration to associate them with so transit here. - iConnection.Close(); newState(QNetworkSession::Closing); newState(QNetworkSession::Disconnected); - } else { - Cancel(); } QT_TRYCATCH_LEAVING(syncStateWithInterface()); return; @@ -1156,10 +1148,7 @@ void QNetworkSessionPrivateImpl::RunL() serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::InvalidConfigurationError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; case KErrCancel: // Connection attempt cancelled @@ -1178,10 +1167,7 @@ void QNetworkSessionPrivateImpl::RunL() iError = QNetworkSession::UnknownSessionError; } QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; } @@ -1273,10 +1259,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::SessionAbortedError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate iHandleStateNotificationsFromManager = true; emitSessionClosed = true; // Emit SessionClosed after state change has been reported diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 774b988..a597812 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -149,6 +149,7 @@ private: bool easyWlanTrueIapId(TUint32 &trueIapId) const; #endif + void closeHandles(); private: // data SymbianEngine *engine; -- cgit v0.12 From ada33b11092f278ae4f1280a6da07ffd151a31b6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 17:22:32 +0000 Subject: Refactor dangerous multiple inheritance QObject and CBase both expect to be the root class of the object hierarchy so it can cause problems if they are used in multiple inheritance. Refactored the CActive used for starting RConnection into a helper class. Reviewed-by: Markus Goetz (cherry picked from commit 5a6365f14006ab50854e41a5927645c7e9966756) --- .../bearer/symbian/qnetworksession_impl.cpp | 82 ++++++++++++++++------ src/plugins/bearer/symbian/qnetworksession_impl.h | 29 ++++++-- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index fc6e141..5514511 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -61,13 +61,12 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) -: CActive(CActive::EPriorityUserInput), engine(engine), - iDynamicUnSetdefaultif(0), ipConnectionNotifier(0), +: engine(engine), + ipConnectionNotifier(0), ipConnectionStarter(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false), isOpening(false) { - CActiveScheduler::Add(this); #ifdef SNAP_FUNCTIONALITY_AVAILABLE iMobility = NULL; @@ -104,7 +103,8 @@ void QNetworkSessionPrivateImpl::closeHandles() #endif // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress - Cancel(); + delete ipConnectionStarter; + ipConnectionStarter = 0; //close any open connection (note Close twice is safe in case Cancel did it above) iConnection.Close(); @@ -425,9 +425,9 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(pref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(pref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -453,9 +453,9 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(snapPref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(snapPref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -464,9 +464,9 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - if (!IsActive()) { - iConnection.Start(iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(); } newState(QNetworkSession::Connecting); } @@ -1066,13 +1066,14 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia return publicConfig; } -void QNetworkSessionPrivateImpl::RunL() +void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "RConnection::RunL with status code: " << iStatus.Int(); + << "RConnection::Start completed with status code: " << statusCode; #endif - TInt statusCode = iStatus.Int(); + delete ipConnectionStarter; + ipConnectionStarter = 0; switch (statusCode) { case KErrNone: // Connection created successfully @@ -1173,11 +1174,6 @@ void QNetworkSessionPrivateImpl::RunL() } } -void QNetworkSessionPrivateImpl::DoCancel() -{ - iConnection.Close(); -} - // Enters newState if feasible according to current state. // AccessPointId may be given as parameter. If it is zero, state-change is assumed to // concern this session's configuration. If non-zero, the configuration is looked up @@ -1566,6 +1562,50 @@ void ConnectionProgressNotifier::RunL() } } +ConnectionStarter::ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection) + : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) +{ + CActiveScheduler::Add(this); +} + +ConnectionStarter::~ConnectionStarter() +{ + Cancel(); +} + +void ConnectionStarter::Start() +{ + if (!IsActive()) { + iConnection.Start(iStatus); + SetActive(); + } +} + +void ConnectionStarter::Start(TConnPref &pref) +{ + if (!IsActive()) { + iConnection.Start(pref, iStatus); + SetActive(); + } +} + +void ConnectionStarter::RunL() +{ + iOwner.ConnectionStartComplete(iStatus.Int()); + //note owner deletes on callback +} + +TInt ConnectionStarter::RunError(TInt err) +{ + qWarning() << "ConnectionStarter::RunError" << err; + return KErrNone; +} + +void ConnectionStarter::DoCancel() +{ + iConnection.Close(); +} + QT_END_NAMESPACE #endif //QT_NO_BEARERMANAGEMENT diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index a597812..a5a4f87 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -68,11 +68,12 @@ QT_BEGIN_NAMESPACE class ConnectionProgressNotifier; +class ConnectionStarter; class SymbianEngine; typedef void (*TOpenCUnSetdefaultifFunction)(); -class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive +class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate #ifdef SNAP_FUNCTIONALITY_AVAILABLE , public MMobilityProtocolResp #endif @@ -125,7 +126,7 @@ public: // From MMobilityProtocolResp #endif protected: // From CActive - void RunL(); + void ConnectionStartComplete(TInt statusCode); void DoCancel(); private Q_SLOTS: @@ -167,12 +168,13 @@ private: // data mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; ConnectionProgressNotifier* ipConnectionNotifier; - + ConnectionStarter* ipConnectionStarter; + bool iHandleStateNotificationsFromManager; bool iFirstSync; bool iStoppedByUser; bool iClosedByUser; - + #ifdef SNAP_FUNCTIONALITY_AVAILABLE CActiveCommsMobilityApiExt* iMobility; #endif @@ -190,6 +192,7 @@ private: // data bool isOpening; friend class ConnectionProgressNotifier; + friend class ConnectionStarter; }; class ConnectionProgressNotifier : public CActive @@ -212,6 +215,24 @@ private: // Data }; +class ConnectionStarter : public CActive +{ +public: + ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection); + ~ConnectionStarter(); + + void Start(); + void Start(TConnPref &pref); +protected: + void RunL(); + TInt RunError(TInt err); + void DoCancel(); + +private: // Data + QNetworkSessionPrivateImpl &iOwner; + RConnection& iConnection; +}; + QT_END_NAMESPACE #endif //QNETWORKSESSION_IMPL_H -- cgit v0.12 From d04f37fa73d2fbb78dd85a02e9d3180ed4ddbdab Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 19 Sep 2011 14:34:04 +0100 Subject: symbian bearer: fix tst_qnetworksession test failures Symbian is not reporting the expected KLinkLayerClosed event on the last RConnection handle. Instead, it reports the event KConfigDaemonFinishedDeregistrationStop, which indicates the nif plugin is being destroyed (this is followed by unload events) To fix, this event is treated the same as a link down event, and results in the state change to disconnected. Either there has been a behaviour change in the platform, or the test was previously run with another user of the API running in the background (e.g. WLAN wizard, connection monitor) which prevented the unload. Task-Number: QTBUG-21382 Reviewed-By: mread (cherry picked from commit a0ad54acd33873316908080f432768fdf3e3bfc2) --- src/plugins/bearer/symbian/qnetworksession_impl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 5514511..29f0637 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1438,6 +1438,9 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne newState(QNetworkSession::Closing,accessPointId); break; + // Connection stopped + case KConfigDaemonFinishedDeregistrationStop: //this comes if this is the last session, instead of KLinkLayerClosed + case KConfigDaemonFinishedDeregistrationPreserve: // Connection closed case KConnectionClosed: case KLinkLayerClosed: -- cgit v0.12 From fa717293080c9d00b02028bebece1935aef6e093 Mon Sep 17 00:00:00 2001 From: aavit Date: Fri, 25 Mar 2011 13:50:41 +0100 Subject: Avoid runtime warning about interlace handling from libpng 1.5 Task-number: QTBUG-13298, QTBUG-21408 (cherry picked from commit c8851ce8e109fb6b403ae80036d9f319f1b69d7a) --- src/gui/image/qpnghandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 7f5cbe8..c0cebf9 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -217,6 +217,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre png_colorp palette = 0; int num_palette; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); + png_set_interlace_handling(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale -- cgit v0.12 From 849694e4cb9d010517b54b2b30035485487b0e12 Mon Sep 17 00:00:00 2001 From: mread Date: Wed, 21 Sep 2011 11:35:14 +0100 Subject: QML import path puts Qt dirs in correct Symbian order The QML import path contains an entry for the standard import location on each drive on Symbian. These were being ordered so that Z:, the ROM drive, was listed first. In fact the drive order was the reverse of the normal Symbian drive search order. This had the effect that upgraded versions of QML imports installed on the device were generally ignored for older ROM based versions. The import path has now been changed to match the normal Symbian drive search order. This will make it more likely for upgraded QML imports to be picked up and used. Task-number: QTBUG-21409 Reviewed-by: Shane Kearns Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeimport.cpp | 10 ++++++++- .../tst_qdeclarativemoduleplugin.cpp | 25 ++++++++++++++++++++++ .../tst_qdeclarativemoduleplugin.pro | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 6e0b348..c25207a 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -733,8 +734,12 @@ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) } RFs& fs = qt_s60GetRFs(); TPtrC tempPathPtr(reinterpret_cast (tempPath.constData())); + // Symbian searches should start from Y:. Fix start drive otherwise TFindFile starts from the session drive + _LIT(KStartDir, "Y:"); + TFileName dirPath(KStartDir); + dirPath.Append(tempPathPtr); TFindFile finder(fs); - TInt err = finder.FindByDir(tempPathPtr, tempPathPtr); + TInt err = finder.FindByDir(tempPathPtr, dirPath); while (err == KErrNone) { QString foundDir(reinterpret_cast(finder.File().Ptr()), finder.File().Length()); @@ -742,6 +747,9 @@ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) addImportPath(foundDir); err = finder.Find(); } + // TFindFile found the directories in the order we want, but addImportPath reverses it. + // Reverse the order again to get it right. + QAlgorithmsPrivate::qReverse(fileImportPath.begin(), fileImportPath.end()); } else { addImportPath(installImportsPath); } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 2cc2971..96bea68 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "../shared/testhttpserver.h" #include "../../../shared/util.h" @@ -70,6 +71,7 @@ private slots: void remoteImportWithUnquotedUri(); void versionNotInstalled(); void versionNotInstalled_data(); + void importPath(); }; #ifdef Q_OS_SYMBIAN @@ -308,6 +310,29 @@ void tst_qdeclarativemoduleplugin::versionNotInstalled() VERIFY_ERRORS(errorFile.toLatin1().constData()); } +void tst_qdeclarativemoduleplugin::importPath() +{ +#ifndef Q_OS_SYMBIAN + QSKIP("Import path order testing for Symbian only", SkipAll); +#else + QDeclarativeEngine engine; + QStringList imports = engine.importPathList(); + QString installImportsPath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::ImportsPath)); + QString driveOrder(QLatin1String("ZABCDEFGHIJKLMNOPQRSTUVWXY")); + int lastOrder = 30; + foreach(QString import, imports) + { + if (import.endsWith(installImportsPath)) + { + int order = driveOrder.indexOf(import[0]); + QVERIFY(order < lastOrder); + lastOrder = order; + } + } + QVERIFY(lastOrder != 30); +#endif +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro index a92d3a2..2716a8b 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro @@ -9,7 +9,7 @@ CONFIG -= app_bundle symbian: { importFiles.sources = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } -- cgit v0.12 From c3669d24b498aa0661ade5ed7465260788f629b5 Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Thu, 22 Sep 2011 11:23:23 +0300 Subject: QLineControl: selectedTextChanged() signal is omitted in some cases QLineControl does not emit selectionChanged() signal when selection is changed due to handling of input method query. As a fix, the signal is emitted when internal values for selection end and beginning are changed in processInputMethodEvent(). Additionally, added deselect() test case for both QDeclarativeTextEdit and QDeclarativeTextInput to help out autotesting of text selections. Note that there are some differences in the QLineControl and QTextControl implementations. This causes the different signal counts even if the test steps are similar. Task-number: QTBUG-21429 Reviewed-by: Miikka Heikkinen --- src/gui/widgets/qlinecontrol.cpp | 4 + .../tst_qdeclarativetextedit.cpp | 115 ++++++++++++++++++++ .../tst_qdeclarativetextinput.cpp | 117 ++++++++++++++++++++- 3 files changed, 235 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 198bc04..c5232ad 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -447,6 +447,8 @@ void QLineControl::moveCursor(int pos, bool mark) void QLineControl::processInputMethodEvent(QInputMethodEvent *event) { int priorState = 0; + int originalSelectionStart = m_selstart; + int originalSelectionEnd = m_selend; bool isGettingInput = !event->commitString().isEmpty() || event->preeditString() != preeditAreaText() || event->replacementLength() > 0; @@ -525,6 +527,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) } m_textLayout.setAdditionalFormats(formats); updateDisplayText(/*force*/ true); + if (originalSelectionStart != m_selstart || originalSelectionEnd != m_selend) + emit selectionChanged(); if (cursorPositionChanged) emitCursorPositionChanged(); else if (m_preeditCursor != oldPreeditCursor) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index fde0588..b6df308 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -154,6 +154,7 @@ private slots: void inputContextMouseHandler(); void inputMethodComposing(); void cursorRectangleSize(); + void deselect(); private: void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0); @@ -2655,6 +2656,120 @@ void tst_qdeclarativetextedit::cursorRectangleSize() QCOMPARE(microFocusFromScene.size(), cursorRect.size()); QCOMPARE(microFocusFromApp.size(), cursorRect.size()); } + +void tst_qdeclarativetextedit::deselect() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/CursorRect.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextEdit *textEdit = qobject_cast(canvas->rootObject()); + QVERIFY(textEdit != 0); + + textEdit->setText("Select"); + + QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); + QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); + QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged())); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 1); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 1); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + textEdit->deselect(); + + QCOMPARE(selectionStartSpy.count(), 2); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 2); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 6); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectionSpy.count(), 3); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + QKeyEvent leftArrowPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QKeyEvent leftArrowRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier); + QApplication::sendEvent(canvas, &leftArrowPress); + QApplication::sendEvent(canvas, &leftArrowRelese); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 2); + QCOMPARE(selectionSpy.count(), 4); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 5); + + textEdit->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 3); + QCOMPARE(selectionSpy.count(), 5); + QCOMPARE(textEdit->selectionStart(), 5); + QCOMPARE(textEdit->selectionEnd(), 6); + QCOMPARE(textEdit->selectedText(), QLatin1String("t")); + QCOMPARE(textEdit->cursorPosition(), 6); + + QList attributes; + attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); + QInputMethodEvent event(QLatin1String(""), attributes); + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 4); + QCOMPARE(selectionSpy.count(), 6); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 0); + + textEdit->setCursorPosition(1); + + QCOMPARE(selectionStartSpy.count(), 5); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectionSpy.count(), 6); + + QKeyEvent leftArrowShiftPress(QEvent::KeyPress, Qt::Key_Left, Qt::ShiftModifier); + QKeyEvent leftArrowShiftRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::ShiftModifier); + QApplication::sendEvent(canvas, &leftArrowShiftPress); + QApplication::sendEvent(canvas, &leftArrowShiftRelese); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectionSpy.count(), 7); + QCOMPARE(textEdit->selectionStart(), 0); + QCOMPARE(textEdit->selectionEnd(), 1); + QCOMPARE(textEdit->selectedText(), QLatin1String("S")); + QCOMPARE(textEdit->cursorPosition(), 0); + + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 6); + QCOMPARE(selectionSpy.count(), 8); + QCOMPARE(textEdit->selectionStart(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectionEnd(), textEdit->cursorPosition()); + QCOMPARE(textEdit->selectedText(), QLatin1String("")); + QCOMPARE(textEdit->cursorPosition(), 0); +} 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 bb895bf..b077670 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -147,6 +147,7 @@ private slots: void inputContextMouseHandler(); void inputMethodComposing(); void cursorRectangleSize(); + void deselect(); private: void simulateKey(QDeclarativeView *, int key); @@ -2367,7 +2368,7 @@ void tst_qdeclarativetextinput::openInputPanelOnFocus() QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); // input method should not be enabled - // if TextEdit is read only. + // if TextInput is read only. input.setReadOnly(true); ic.openInputPanelReceived = false; input.setFocus(true); @@ -2815,6 +2816,120 @@ void tst_qdeclarativetextinput::cursorRectangleSize() QCOMPARE(microFocusFromApp.size(), cursorRect.size()); } +void tst_qdeclarativetextinput::deselect() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); + QVERIFY(canvas->rootObject() != 0); + canvas->show(); + canvas->setFocus(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + + QDeclarativeTextInput *textInput = qobject_cast(canvas->rootObject()); + QVERIFY(textInput != 0); + + textInput->setText("Select"); + + QSignalSpy selectionStartSpy(textInput, SIGNAL(selectionStartChanged())); + QSignalSpy selectionEndSpy(textInput, SIGNAL(selectionEndChanged())); + QSignalSpy selectedTextSpy(textInput, SIGNAL(selectedTextChanged())); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 1); + QCOMPARE(selectionEndSpy.count(), 0); + QCOMPARE(selectedTextSpy.count(), 1); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + textInput->deselect(); + + QCOMPARE(selectionStartSpy.count(), 2); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectedTextSpy.count(), 2); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 6); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 3); + QCOMPARE(selectionEndSpy.count(), 1); + QCOMPARE(selectedTextSpy.count(), 3); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + QKeyEvent leftArrowPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QKeyEvent leftArrowRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier); + QApplication::sendEvent(canvas, &leftArrowPress); + QApplication::sendEvent(canvas, &leftArrowRelese); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 2); + QCOMPARE(selectedTextSpy.count(), 4); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 5); + + textInput->select(5, 6); + + QCOMPARE(selectionStartSpy.count(), 4); + QCOMPARE(selectionEndSpy.count(), 3); + QCOMPARE(selectedTextSpy.count(), 5); + QCOMPARE(textInput->selectionStart(), 5); + QCOMPARE(textInput->selectionEnd(), 6); + QCOMPARE(textInput->selectedText(), QLatin1String("t")); + QCOMPARE(textInput->cursorPosition(), 6); + + QList attributes; + attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); + QInputMethodEvent event(QLatin1String(""), attributes); + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 5); + QCOMPARE(selectionEndSpy.count(), 4); + QCOMPARE(selectedTextSpy.count(), 6); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 0); + + textInput->setCursorPosition(1); + + QCOMPARE(selectionStartSpy.count(), 6); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectedTextSpy.count(), 6); + + QKeyEvent leftArrowShiftPress(QEvent::KeyPress, Qt::Key_Left, Qt::ShiftModifier); + QKeyEvent leftArrowShiftRelese(QEvent::KeyRelease, Qt::Key_Left, Qt::ShiftModifier); + QApplication::sendEvent(canvas, &leftArrowShiftPress); + QApplication::sendEvent(canvas, &leftArrowShiftRelese); + + QCOMPARE(selectionStartSpy.count(), 7); + QCOMPARE(selectionEndSpy.count(), 5); + QCOMPARE(selectedTextSpy.count(), 7); + QCOMPARE(textInput->selectionStart(), 0); + QCOMPARE(textInput->selectionEnd(), 1); + QCOMPARE(textInput->selectedText(), QLatin1String("S")); + QCOMPARE(textInput->cursorPosition(), 0); + + QApplication::sendEvent(canvas, &event); + + QCOMPARE(selectionStartSpy.count(), 8); + QCOMPARE(selectionEndSpy.count(), 6); + QCOMPARE(selectedTextSpy.count(), 8); + QCOMPARE(textInput->selectionStart(), textInput->cursorPosition()); + QCOMPARE(textInput->selectionEnd(), textInput->cursorPosition()); + QCOMPARE(textInput->selectedText(), QLatin1String("")); + QCOMPARE(textInput->cursorPosition(), 0); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v0.12 From 6f6493747121db428a71d494c8cb3f04a0292279 Mon Sep 17 00:00:00 2001 From: Viktor Kolesnyk Date: Mon, 5 Sep 2011 15:08:23 +0300 Subject: Incorrect 'break' in switch-case was replaced by 'return' --- src/gui/kernel/qcursor_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index cef83f5..a68472c 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -477,7 +477,7 @@ void QCursorData::update() QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape); hcurs = create32BitCursor(pixmap, hx, hy); } - break; + return; default: qWarning("QCursor::update: Invalid cursor shape %d", cshape); return; -- cgit v0.12 From 872872f3d3f0d89010d3a196b70e8445a08d0784 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Fri, 23 Sep 2011 07:47:24 +0300 Subject: Fix to QtOpenGL crash Exiting the native video recorder on Symbian and going back to Qt app which runs on opengl graphics system crashed on some devices because there was not enough GPU memory and also because low GPU mem device environment detection was flawed. This patch fixes 32MB GPU memory detection and adds wait/retrial to EGL surface creation if it fails. Task-number: QTBUG-21499 Reviewed-by: Laszlo Agocs --- src/gui/egl/qegl.cpp | 32 ++++++++ src/gui/painting/qgraphicssystemex_symbian.cpp | 105 +++++++++++++++++++++---- 2 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 4db4a6a..02adef8 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -684,6 +684,37 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr else props = 0; EGLSurface surf; +#ifdef Q_OS_SYMBIAN + // On Symbian there might be situations (especially on 32MB GPU devices) + // where Qt is trying to create EGL surface while some other application + // is still holding all available GPU memory but is about to release it + // soon. For an example when exiting native video recorder and going back to + // Qt application behind it. Video stack tear down takes some time and Qt + // app might be too quick in reserving its EGL surface and thus running out + // of GPU memory right away. So if EGL surface creation fails due to bad + // alloc, let's try recreating it four times within ~1 second if needed. + // This strategy gives some time for video recorder to tear down its stack + // and a chance to Qt for creating a valid surface. + int tries = 4; + while(tries--) { + if (devType == QInternal::Widget) + surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); + else + surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props); + if (surf == EGL_NO_SURFACE) { + EGLint error = eglGetError(); + if (error == EGL_BAD_ALLOC) { + if (tries) { + User::After(1000 * 250); // 250ms + continue; + } + } + qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", error); + } else { + break; + } + } +#else if (devType == QInternal::Widget) surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); else @@ -691,6 +722,7 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr if (surf == EGL_NO_SURFACE) { qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); } +#endif return surf; } #endif diff --git a/src/gui/painting/qgraphicssystemex_symbian.cpp b/src/gui/painting/qgraphicssystemex_symbian.cpp index 4469704..46731d8 100644 --- a/src/gui/painting/qgraphicssystemex_symbian.cpp +++ b/src/gui/painting/qgraphicssystemex_symbian.cpp @@ -46,31 +46,106 @@ #include +#ifdef Q_SYMBIAN_SUPPORTS_SURFACES +#include "private/qegl_p.h" +#endif + QT_BEGIN_NAMESPACE static bool bcm2727Initialized = false; static bool bcm2727 = false; +typedef EGLBoolean (*NOK_resource_profiling)(EGLDisplay, EGLint, EGLint*, EGLint, EGLint*); +#define EGL_PROF_TOTAL_MEMORY_NOK 0x3070 + +// Detect if Qt is running on BCM2727 chip. +// BCM2727 is a special case on Symbian because +// it has only 32MB GPU memory which exposes +// significant limitations to hw accelerated UI. bool QSymbianGraphicsSystemEx::hasBCM2727() { if (bcm2727Initialized) return bcm2727; - const TUid KIvePropertyCat = {0x2726beef}; - enum TIvePropertyChipType { - EVCBCM2727B1 = 0x00000000, - EVCBCM2763A0 = 0x04000100, - EVCBCM2763B0 = 0x04000102, - EVCBCM2763C0 = 0x04000103, - EVCBCM2763C1 = 0x04000104, - EVCBCMUnknown = 0x7fffffff - }; - - TInt chipType = EVCBCMUnknown; - if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) { - if (chipType == EVCBCM2727B1) +#ifdef Q_SYMBIAN_SUPPORTS_SURFACES + EGLDisplay display = QEgl::display(); +#if 1 + // Hacky but fast ~0ms. + const char* vendor = eglQueryString(display, EGL_VENDOR); + if (strstr(vendor, "Broadcom")) { + const TUid KIvePropertyCat = {0x2726beef}; + enum TIvePropertyChipType { + EVCBCM2727B1 = 0x00000000, + EVCBCM2763A0 = 0x04000100, + EVCBCM2763B0 = 0x04000102, + EVCBCM2763C0 = 0x04000103, + EVCBCM2763C1 = 0x04000104, + EVCBCMUnknown = 0x7fffffff + }; + + // Broadcom driver publishes KIvePropertyCat PS key on + // devices which are running on BCM2727 chip and post Anna Symbian. + TInt chipType = EVCBCMUnknown; + if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) { + if (chipType == EVCBCM2727B1) + bcm2727 = true; + } else if (QSysInfo::symbianVersion() <= QSysInfo::SV_SF_3) { + // Device is running on Symbian Anna or older Symbian^3 in which + // KIvePropertyCat is not published. These ones are always 32MB devices. + bcm2727 = true; + } else { + // We have some other Broadcom chip on post Anna Symbian. + // Should have > 32MB GPU memory. + } + } +#else + // Fool proof but takes 15-20ms and we don't want this delay on app startup... + + // All devices with <= 32MB GPU memory should be + // dealed in similar manner to BCM2727 + // So let's query max GPU memory amount. + NOK_resource_profiling eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK"); + if (eglQueryProfilingData) { + EGLint dataCount; + eglQueryProfilingData(display, + EGL_PROF_QUERY_GLOBAL_BIT_NOK | + EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, + NULL, + 0, + (EGLint*)&dataCount); + + // Allocate room for the profiling data + EGLint* profData = (EGLint*)malloc(dataCount * sizeof(EGLint)); + memset(profData,0,dataCount * sizeof(EGLint)); + + // Retrieve the profiling data + eglQueryProfilingData(display, + EGL_PROF_QUERY_GLOBAL_BIT_NOK | + EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, + profData, + dataCount, + (EGLint*)&dataCount); + + int totalMemory; + EGLint i = 0; + while (profData && i < dataCount) { + switch (profData[i++]) { + case EGL_PROF_TOTAL_MEMORY_NOK: + totalMemory = profData[i++]; + break; + default: + i++; + } + } + + // ok, hasBCM2727() naming is a bit misleading but Qt must + // behave the same on all chips like BCM2727 (<= 32MB GPU memory) + // and our code (and others) are already using this function. + if (totalMemory <= 33554432) bcm2727 = true; } +#endif +#endif // Q_SYMBIAN_SUPPORTS_SURFACES bcm2727Initialized = true; @@ -80,7 +155,9 @@ bool QSymbianGraphicsSystemEx::hasBCM2727() void QSymbianGraphicsSystemEx::releaseCachedGpuResources() { // Do nothing here - // This is implemented in graphics system specific plugin + + // This virtual function should be implemented in graphics system specific + // plugin } void QSymbianGraphicsSystemEx::releaseAllGpuResources() -- cgit v0.12 From e90cffc2c5f313cc813d0a21a1d9d0afe8d0ea7a Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Tue, 27 Sep 2011 08:17:25 +0300 Subject: Crash in QDeclarativeCompiler::indexOfProperty In QDeclarativePropertyCache, plain integer bitfield overrideIndex is initialized with -1 in class constructor. Unfortunately, ARM compiler treats bitfields as unsigned, unless explicitly defined as signed [1]. Therefore, overrideIndex actually gets initial value of 2147483647, which causes array operations done with the index to fail. As a fix, define overrideIndex as signed int bitfield. [1] http://www.keil.com/support/man/docs/armccref/armccref_Babjddhe.htm Under bitfields/Note: "A plain bitfield, declared without either signed or unsigned qualifiers, is treated as unsigned" Task-number: QT-5285 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativepropertycache_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 581f519..c648d25 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -111,7 +111,7 @@ public: int relatedIndex; // When IsFunction }; uint overrideIndexIsProperty : 1; - int overrideIndex : 31; + signed int overrideIndex : 31; int revision; int metaObjectOffset; -- cgit v0.12 From 24855ef3983fa5d87b3e3a06fe891a769e670ae5 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 31 Aug 2011 15:52:25 +0100 Subject: Always recreate backing store when TLW transparency changes When using either the opengl or openvg graphics system on Symbian, if a TLW is made transparent, the widget switches to using raster rendering, because EGL surface transparency is currently not supported by the platform. This patch enables the reverse to occur: when the widget is subsequently made opaque, rendering switches back to using GL/VG. Task-number: QTBUG-21211 Reviewed-by: Jani Hautakangas Reviewed-by: Laszlo Agocs Reviewed-by: Sami Merila --- src/gui/kernel/qwidget.cpp | 24 ++++++++++++---- src/gui/kernel/qwidget_p.h | 1 + src/gui/kernel/qwidget_s60.cpp | 58 ++++++++++++++++++++++++-------------- tests/auto/qwidget/tst_qwidget.cpp | 45 ++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 27 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 8e8266c..bda0885 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -2238,10 +2238,16 @@ void QWidgetPrivate::updateIsOpaque() #endif #ifdef Q_WS_S60 - if (q->windowType() == Qt::Dialog && q->testAttribute(Qt::WA_TranslucentBackground) - && S60->avkonComponentsSupportTransparency) { - setOpaque(false); - return; + if (q->testAttribute(Qt::WA_TranslucentBackground)) { + if (q->windowType() & Qt::Dialog || q->windowType() & Qt::Popup) { + if (S60->avkonComponentsSupportTransparency) { + setOpaque(false); + return; + } + } else { + setOpaque(false); + return; + } } #endif @@ -2261,11 +2267,16 @@ void QWidgetPrivate::updateIsOpaque() } if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) { +#ifdef Q_WS_S60 + setOpaque(true); + return; +#else const QBrush &windowBrush = q->palette().brush(QPalette::Window); if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) { setOpaque(true); return; } +#endif } setOpaque(false); } @@ -10845,11 +10856,14 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } break; case Qt::WA_TranslucentBackground: +#if defined(Q_OS_SYMBIAN) + setAttribute(Qt::WA_NoSystemBackground, on); +#else if (on) { setAttribute(Qt::WA_NoSystemBackground); d->updateIsTranslucent(); } - +#endif break; case Qt::WA_AcceptTouchEvents: #if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index e30497c..caa6454 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -228,6 +228,7 @@ struct QTLWExtra { uint inExpose : 1; // Prevents drawing recursion uint nativeWindowTransparencyEnabled : 1; // Tracks native window transparency uint forcedToRaster : 1; + uint noSystemRotationDisabled : 1; #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index e80eced..e12dfa7 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -820,19 +820,12 @@ void QWidgetPrivate::setConstraints_sys() void QWidgetPrivate::s60UpdateIsOpaque() { Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) return; - const bool writeAlpha = extraData()->nativePaintMode == QWExtra::BlitWriteAlpha; - if (!q->testAttribute(Qt::WA_TranslucentBackground) && !writeAlpha) - return; const bool requireAlphaChannel = !isOpaque || writeAlpha; - createTLExtra(); - RWindow *const window = static_cast(q->effectiveWinId()->DrawableWindow()); - #ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces && !extra->topextra->forcedToRaster) { @@ -841,25 +834,47 @@ void QWidgetPrivate::s60UpdateIsOpaque() return; } #endif + const bool recreateBackingStore = extra->topextra->backingStore.data() && ( + QApplicationPrivate::graphics_system_name == QLatin1String("openvg") || + QApplicationPrivate::graphics_system_name == QLatin1String("opengl") + ); if (requireAlphaChannel) { - const TDisplayMode displayMode = static_cast(window->SetRequiredDisplayMode(EColor16MA)); - if (window->SetTransparencyAlphaChannel() == KErrNone) { + window->SetRequiredDisplayMode(EColor16MA); + if (window->SetTransparencyAlphaChannel() == KErrNone) window->SetBackgroundColor(TRgb(255, 255, 255, 0)); - extra->topextra->nativeWindowTransparencyEnabled = 1; - if (extra->topextra->backingStore.data() && ( - QApplicationPrivate::graphics_system_name == QLatin1String("openvg") - || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"))) { - // Semi-transparent EGL surfaces aren't supported. We need to - // recreate backing store to get translucent surface (raster surface). - extra->topextra->backingStore.create(q); - extra->topextra->backingStore.registerWidget(q); - // FixNativeOrientation() will not work without an EGL surface. + } else { + if (recreateBackingStore) { + // Clear the UI surface to ensure that the EGL surface content is visible + CWsScreenDevice *screenDevice = S60->screenDevice(q); + QScopedPointer gc(new CWindowGc(screenDevice)); + const int err = gc->Construct(); + if (!err) { + gc->Activate(*window); + window->BeginRedraw(); + gc->SetDrawMode(CWindowGc::EDrawModeWriteAlpha); + gc->SetBrushColor(TRgb(0, 0, 0, 0)); + gc->Clear(TRect(0, 0, q->width(), q->height())); + window->EndRedraw(); + } + } + if (extra->topextra->nativeWindowTransparencyEnabled) + window->SetTransparentRegion(TRegionFix<1>()); + } + extra->topextra->nativeWindowTransparencyEnabled = requireAlphaChannel; + if (recreateBackingStore) { + extra->topextra->backingStore.create(q); + extra->topextra->backingStore.registerWidget(q); + bool noSystemRotationDisabled = false; + if (requireAlphaChannel) { + if (q->testAttribute(Qt::WA_SymbianNoSystemRotation)) { + // FixNativeOrientation() will not work without an EGL surface q->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + noSystemRotationDisabled = true; } + } else { + q->setAttribute(Qt::WA_SymbianNoSystemRotation, extra->topextra->noSystemRotationDisabled); } - } else if (extra->topextra->nativeWindowTransparencyEnabled) { - window->SetTransparentRegion(TRegionFix<1>()); - extra->topextra->nativeWindowTransparencyEnabled = 0; + extra->topextra->noSystemRotationDisabled = noSystemRotationDisabled; } } @@ -1020,6 +1035,7 @@ void QWidgetPrivate::createTLSysExtra() extra->topextra->inExpose = 0; extra->topextra->nativeWindowTransparencyEnabled = 0; extra->topextra->forcedToRaster = 0; + extra->topextra->noSystemRotationDisabled = 0; } void QWidgetPrivate::deleteTLSysExtra() diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 43dd077..2161f99 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -397,6 +397,9 @@ private slots: void minimizedWindowModeTransitions(); void normalWindowModeTransitions(); void focusSwitchClosesPopupMenu(); +#if !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) + void opacityChangeCausesBackingStoreRecreation(); +#endif #endif void focusProxyAndInputMethods(); @@ -10336,7 +10339,47 @@ void tst_QWidget::focusSwitchClosesPopupMenu() mainWindow.activateWindow(); QVERIFY(!CEikonEnv::Static()->AppUiFactory()->MenuBar()->IsDisplayed()); } -#endif + +#if !defined(Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE) +class OpacityChangeWidget : public QWidget +{ +public: + OpacityChangeWidget() : m_paintEngineType(QPaintEngine::MaxUser) { } + void paintEvent(QPaintEvent *) + { + QPainter painter(this); + m_paintEngineType = painter.paintEngine()->type(); + } + QPaintEngine::Type paintEngineType() const { return m_paintEngineType; } +private: + QPaintEngine::Type m_paintEngineType; +}; + +void tst_QWidget::opacityChangeCausesBackingStoreRecreation() +{ + OpacityChangeWidget w; + w.show(); + QTest::qWaitForWindowShown(&w); + const QPaintEngine::Type type = w.paintEngineType(); + if (QPaintEngine::OpenGL != type && QPaintEngine::OpenVG != type) { + QSKIP("Test case is only valid when using opengl or openvg graphics system", SkipAll); + } else { + if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { + QSKIP("Test case is only valid when EGL surface transparency is not supported", SkipAll); + } else { + // Making window transparent should force switch to raster graphics system + w.setAttribute(Qt::WA_TranslucentBackground, true); + w.repaint(); + QCOMPARE(w.paintEngineType(), QPaintEngine::Raster); + // Making window opaque should cause switch back to previous graphics system + w.setAttribute(Qt::WA_TranslucentBackground, false); + w.repaint(); + QCOMPARE(w.paintEngineType(), type); + } + } +} +#endif // !Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE +#endif // Q_OS_SYMBIAN class InputContextTester : public QInputContext { -- cgit v0.12 From 55d25e4471074241a4edf9b9c0033cce4e211bdf Mon Sep 17 00:00:00 2001 From: Eero Hyyti Date: Tue, 27 Sep 2011 16:09:42 +0300 Subject: Document updates to Qt for Symbian installation instructions and platform notes. --- doc/src/getting-started/installation.qdoc | 570 ++++++++++++++++-------------- doc/src/platforms/platform-notes.qdoc | 95 +++-- 2 files changed, 374 insertions(+), 291 deletions(-) diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc index ef010b4..bec9ee4 100644 --- a/doc/src/getting-started/installation.qdoc +++ b/doc/src/getting-started/installation.qdoc @@ -79,6 +79,8 @@ for your platform from the following list. \snippet doc/src/snippets/code/doc_src_installation.qdoc 1 Type \c{./configure -help} to get a list of all available options. + The \l{Configuration Options for Qt} page gives a brief overview + of these. To create the library and compile all the demos, examples, tools, and tutorials, type: @@ -218,7 +220,8 @@ for your platform from the following list. \snippet doc/src/snippets/code/doc_src_installation.qdoc 8 - Type \c{configure -help} to get a list of all available options. + Type \c{configure -help} to get a list of all available options. The + \l{Configuration Options for Qt} page gives a brief overview of these. If you have multiple compilers installed, and want to build the Qt library using a specific compiler, you must specify a \c qmake specification. @@ -433,7 +436,9 @@ in the \l{Qt for Windows CE Requirements} document. If you want to configure Qt for another platform or with other options, type \c{configure -help} to get a list of all available - options. See the \c README file for the list of supported platforms. + options. The \l{Configuration Options for Qt} page gives a brief + overview of these. See the \c README file for the list of supported + platforms. \section1 Step 4: Build Qt Library @@ -505,7 +510,10 @@ in the \l{Qt for the Symbian platform Requirements} document. \section1 Step 1: Install Qt - Run \c{qt-symbian-opensource-%VERSION%.exe} and follow the instructions. + Download the \c {Qt libraries 4.x for Windows} package (for \c minGW or \c {VS 2008}) + from the \l {http://qt.nokia.com/downloads#qt-lib}{downloads} page. + + Run the downloaded package and follow the instructions. \note Qt must be installed on the same drive as the Symbian SDK you are using, and the install path must not contain any spaces. @@ -626,6 +634,10 @@ Binary Package} document. \snippet doc/src/snippets/code/doc_src_installation.qdoc 31 (to build the tools using MinGW, and the libraries using SBSv2) + Type \c{./configure -help} to get a list of all available options. + The \l{Configuration Options for Qt} page gives a brief overview + of these. + SBSv2 (also known as \l{http://developer.symbian.org/wiki/index.php/Introduction_to_RAPTOR} {Raptor}) is a next-generation Symbian build system. SBSv2 is not officially supported by any of the S60 SDKs currently available from Forum Nokia. @@ -643,23 +655,39 @@ Binary Package} document. Congratulations, Qt is now ready to use. \section1 Step 7: Installing Qt Libraries on the Device - - To run the demo on a real device, you first have to install - the Qt libraries on the device: + + To run a Qt application on a device, it must have Qt libraries installed. + + Symbian devices have a pre-installed Qt as follows: + \list + \o Symbian Anna devices have the pre-installed Qt, Qt Mobility, and Qt Webkit. + \o Symbian Belle and later devices have the pre-installed Qt on the device firmware. + \endlist + + \l {http://www.developer.nokia.com/Community/Wiki/Nokia_Smart_Installer_for_Symbian} + {Nokia Smart Installer for Symbian} deploys the required Qt libraries to supported S60 + and Symbian devices if the libraries are not pre-installed. + + Nokia Developer site's \l {http://www.developer.nokia.com/Devices/Device_specifications/?filter1=qt} + {Device specifications} provide information on which devices have a + pre-installed Qt and the used Qt version. + + To create your own Qt installation package, do as follows: \snippet doc/src/snippets/code/doc_src_installation.qdoc 29 - The Qt libraries are built with "All -Tcb" capability, so that - they can support all types of application. - If you don't have a suitable certificate, it is possible to patch - the binaries as follows: - - If you have no certificate, build a self signed Qt: -\snippet doc/src/snippets/code/doc_src_installation.qdoc 34 + The Qt libraries are built with "All -Tcb" capability, so they can support + all types of applications. If you don't have a suitable certificate, you can + patch the binaries in either of the following ways: + + \list + \o If you have no certificate, build a self-signed Qt: + \snippet doc/src/snippets/code/doc_src_installation.qdoc 34 - If you have a symbian-signed developer certificate, specify the + \o If you have a symbian-signed developer certificate, specify the capabilities you can sign for, for example: -\snippet doc/src/snippets/code/doc_src_installation.qdoc 35 + \snippet doc/src/snippets/code/doc_src_installation.qdoc 35 + \endlist \section1 Running Qt demos @@ -740,6 +768,9 @@ to build the libraries using RVCT or to build the libraries using GCCE. +Type \c{./configure -help} to get a list of all available options. +The \l{Configuration Options for Qt} page gives a brief overview +of these. \section1 Step 5: Build Qt @@ -1303,7 +1334,12 @@ We hope you will enjoy using Qt. \brief Setting up the Symbian platform environment for Qt. \previouspage General Qt Requirements - Qt for the Symbian platform requires the following software installed on your development PC: + \l {http://qt.nokia.com/downloads}{Qt SDK} provides all the necessary tools + and libraries for developing Qt applications. However, if you want to build + Qt itself for Symbian, follow the instructions below. + + Qt for the Symbian platform requires the following software installed on + your development PC: \list \o \l{http://www.forum.nokia.com/Library/Tools_and_downloads/Other/Carbide.c++/}{Carbide.c++ v2.3.0 or higher recommended}. \list @@ -1368,253 +1404,263 @@ We hope you will enjoy using Qt. /*! \page configure-options.html - \title Configure options for Qt + \title Configuration Options for Qt \ingroup installation - \brief Brief description of available options building Qt. - - This page gives a brief description of the different options - available when building Qt using configure. To build Qt using - default options, just call configure from the command line like - showed below. If you would like to customize your build, please - use the options listed in the following tables. - - \c {.\configure.exe} - - \section2 Cross platform options: - - \table - \header \o Option \o Description \o Note - \row \o \c {-buildkey } \o Build the Qt library and plugins - using the specified \o - \row \o \c {} \o When the library loads plugins, it will only - load those that have a matching . \o - \row \o \c {-release } \o Compile and link Qt with debugging turned off. \o - \row \o \c {-debug } \o Compile and link Qt with debugging turned on. - \o Default value. - \row \o \c {-debug-and-release} \o Compile and link two Qt libraries, - with and without debugging turned on. \o This option denotes a default - value and needs to be evaluated. If the evaluation succeeds, the - feature is included. - \row \o \c {-opensource} \o Compile and link the Open-Source Edition - of Qt. \o - \row \o \c {-commercial } \o Compile and link the Commercial Edition - of Qt. \o - \row \o \c {-developer-build} \o Compile and link Qt with Qt developer - options including auto-tests exporting) \o - \row \o \c {-shared} \o Create and use shared Qt libraries. \o Default - value. - \row \o \c {-static} \o Create and use static Qt libraries. \o - \row \o \c {-ltcg} \o Use Link Time Code Generation. \o Apply to release - builds only. - \row \o \c {-no-ltcg} \o Do not use Link Time Code Generation. \o Default - value. - \row \o \c {-no-fast} \o Configure Qt normally by generating Makefiles for - all project files. \o Default value. - \row \o \c {-fast} \o Configure Qt quickly by generating Makefiles only for - library and subdirectory targets. \o All other Makefiles are created as - wrappers which will in turn run qmake. - \row \o \c {-no-exceptions} \o Disable exceptions on platforms that support - it. \o - \row \o \c {-exceptions} \o Enable exceptions on platforms that support it. - \o Default value. - \row \o \c {-no-accessibility} \o Do not compile Windows Active - Accessibility support. \o - \row \o \c {-accessibility} \o Compile Windows Active Accessibility - support. \o Default value. - \row \o \c {-no-stl} \o Do not compile STL support. \o - \row \o \c {-stl} \o Compile STL support. \o Default value. - \row \o \c {-no-sql-} \o Disable SQL entirely, by default - none are turned on. \o - \row \o \c {-qt-sql-} \o Enable a SQL in the Qt Library. - \o - \row \o \c {-plugin-sql-} \o Enable SQL as a plugin to be - linked to at run time. \o Available values for : mysql, psql, - oci, odbc, tds, db2, sqlite, sqlite2, ibase. Drivers marked with a - '+' during configure have been detected as available on this system. - \row \o \c {-system-sqlite} \o Use sqlite from the operating system. \o - \row \o \c {-no-qt3support} \o Disables the Qt 3 support functionality. \o - \row \o \c {-no-opengl} \o Disables OpenGL functionality \o - \row \o \c {-opengl } \o Enable OpenGL support with specified API - version. \o Available values for : desktop - Enable support for - Desktop OpenGL (Default), es1 - Enable support for OpenGL ES Common - Profile, es2 - Enable support for OpenGL ES 2.0. - \row \o \c {-no-openvg} \o Disables OpenVG functionality \o Default value. - \row \o \c {-openvg} \o Enables OpenVG functionality \o Requires EGL - support, typically supplied by an OpenGL or other graphics - implementation. - \row \o \c {-platform } \o The operating system and compiler you - are building on. \o The default value is %QMAKESPEC%. - \row \o \c {-xplatform } \o The operating system and compiler you - are cross compiling for. \o See the README file for a list of supported - operating systems and compilers. - \row \o \c {-qtnamespace } \o Wraps all Qt library code in - 'namespace name {..} \o - \row \o \c {-qtlibinfix } \o Renames all Qt* libs to Qt* - \o - \row \o \c {-D } \o Add an explicit define to the preprocessor. - \o - \row \o \c {-I } \o Add an explicit include path. \o - \row \o \c {-L } \o Add an explicit library path. \o - \row \o \c {-l } \o Add an explicit library name, residing - in a librarypath. \o - \row \o \c {-graphicssystem } \o Specify which graphics system should - be used. \o Available values for : * raster - Software rasterizer, - opengl - Using OpenGL acceleration, experimental!, openvg - Using - OpenVG acceleration, experimental! - \row \o \c {-help, -h, -?} \o Display this information. \o - \endtable - - \section2 Third Party Libraries: - \table - \header \o Option \o Description \o Note - \row \o \c {-qt-zlib} \o Use the zlib bundled with Qt. \o - \row \o \c {-system-zlib} \o Use zlib from the operating system. - \o See http://www.gzip.org/zlib - \row \o \c {-no-gif} \o Do not compile GIF reading support. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-qt-gif} \o Compile GIF reading support. \o See also - src/gui/image/qgifhandler_p.h - \row \o \c {-no-libpng} \o Do not compile PNG support. \o - \row \o \c {-qt-libpng} \o Use the libpng bundled with Qt. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-system-libpng} \o Use libpng from the operating system. - \o See http://www.libpng.org/pub/png - \row \o \c {-no-libmng} \o Do not compile MNG support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libmng} \o Use the libmng bundled with Qt. \o - \row \o \c {-system-libmng} \o Use libmng from the operating system. - \o See http://www.libmng.com - \row \o \c {-no-libtiff} \o Do not compile TIFF support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libtiff} \o Use the libtiff bundled with Qt. \o - \row \o \c {-system-libtiff} \o Use libtiff from the operating system. - \o See http://www.libtiff.org - \row \o \c {-no-libjpeg} \o Do not compile JPEG support. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-qt-libjpeg} \o Use the libjpeg bundled with Qt. \o - \row \o \c {-system-libjpeg} \o Use libjpeg from the operating system. - \o See http://www.ijg.org. This option denotes a default value and - needs to be evaluated. If the evaluation succeeds, the feature is - included. - \endtable - - \section2 Qt for Windows only: - \table - \header \o Option \o Description \o Note - \row \o \c {-no-dsp} \o Do not generate VC++ .dsp files. \o - \row \o \c {-dsp} \o Generate VC++ .dsp files, only if spec "win32-msvc". - \o Default value. - \row \o \c {-no-vcproj} \o Do not generate VC++ .vcproj files. \o - \row \o \c {-vcproj} \o Generate VC++ .vcproj files, only if platform - "win32-msvc.net". \o Default value. - \row \o \c {-no-incredibuild-xge} \o Do not add IncrediBuild XGE distribution - commands to custom build steps. \o - \row \o \c {-incredibuild-xge} \o Add IncrediBuild XGE distribution commands - to custom build steps. This will distribute MOC and UIC steps, and other - custom buildsteps which are added to the INCREDIBUILD_XGE variable. - \o The IncrediBuild distribution commands are only added to Visual Studio - projects. This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-no-plugin-manifests} \o Do not embed manifests in plugins. \o - \row \o \c {-plugin-manifests} \o Embed manifests in plugins. - \o Default value. - \row \o \c {-no-qmake} \o Do not compile qmake. \o - \row \o \c {-qmake} \o Compile qmake. \o Default value - \row \o \c {-dont-process} \o Do not generate Makefiles/Project files. This - will override -no-fast if specified. \o - \row \o \c {-process} \o Generate Makefiles/Project files. \o Default value. - \row \o \c {-no-rtti} \o Do not compile runtime type information. \o - \row \o \c {-rtti} \o Compile runtime type information. \o Default value. - \row \o \c {-no-mmx} \o Do not compile with use of MMX instructions \o - \row \o \c {-mmx} \o Compile with use of MMX instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-3dnow} \o Do not compile with use of 3DNOW instructions \o - \row \o \c {-3dnow} \o Compile with use of 3DNOW instructions \o This - option denotes a default value and needs to be evaluated. If the - evaluation succeeds, the feature is included. - \row \o \c {-no-sse} \o Do not compile with use of SSE instructions \o - \row \o \c {-sse} \o Compile with use of SSE instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-sse2} \o Do not compile with use of SSE2 instructions \o - \row \o \c {-sse2} \o Compile with use of SSE2 instructions \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-openssl} \o Do not compile in OpenSSL support \o - \row \o \c {-openssl} \o Compile in run-time OpenSSL support \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-openssl-linked} \o Compile in linked OpenSSL support \o - \row \o \c {-no-dbus} \o Do not compile in D-Bus support \o - \row \o \c {-dbus} \o Compile in D-Bus support and load libdbus-1 dynamically. - \o This option denotes a default value and needs to be evaluated. - If the evaluation succeeds, the feature is included. - \row \o \c {-dbus-linked} \o Compile in D-Bus support and link to - libdbus-1 \o - \row \o \c {-no-phonon} \o Do not compile in the Phonon module \o - \row \o \c {-phonon} \o Compile the Phonon module. \o Phonon is built if a - decent C++ compiler is used. This option denotes a default value and needs - to be evaluated. If the evaluation succeeds, the feature is included. - \row \o \c {-no-phonon-backend} \o Do not compile the platform-specific - Phonon backend-plugin \o - \row \o \c {-phonon-backend} \o Compile in the platform-specific Phonon - backend-plugin \o Default value. - \row \o \c {-no-multimedia} \o Do not compile the multimedia module \o - \row \o \c {-multimedia} \o Compile in multimedia module \o Default value. - \row \o \c {-no-audio-backend} \o Do not compile in the platform audio - backend into QtMultimedia \o - \row \o \c {-audio-backend} \o Compile in the platform audio backend into - QtMultimedia \o This option denotes a default value and needs to be - evaluated. If the evaluation succeeds, the feature is included. - \row \o \c {-no-webkit} \o Do not compile in the WebKit module \o - \row \o \c {-webkit} \o Compile in the WebKit module \o WebKit is built - if a decent C++ compiler is used. This option denotes a default value - and needs to be evaluated. If the evaluation succeeds, the feature is - included. - \row \o \c {-webkit-debug} \o Compile in the WebKit module with debug - symbols. \o - \row \o \c {-no-script} \o Do not build the QtScript module. \o - \row \o \c {-script} \o Build the QtScript module. \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-scripttools} \o Do not build the QtScriptTools module. \o - \row \o \c {-scripttools} \o Build the QtScriptTools module. \o This - option denotes a default value and needs to be evaluated. If the - evaluation succeeds, the feature is included. - \row \o \c {-no-declarative} \o Do not build the declarative module \o - \row \o \c {-declarative} \o Build the declarative module \o This option - denotes a default value and needs to be evaluated. If the evaluation - succeeds, the feature is included. - \row \o \c {-no-declarative-debug} \o Do not build the declarative debugging - support \o - \row \o \c {-declarative-debug} \o Build the declarative debugging support - \o Default value. - \row \o \c {-arch } \o Specify an architecture. \o Available values for - : * windows, windowsce, symbian, boundschecker, generic. - \row \o \c {-no-style-