From d7438b4761787ffdb6cee82ce0103d653d4cbd24 Mon Sep 17 00:00:00 2001 From: Peter Yard Date: Fri, 14 May 2010 10:13:57 +1000 Subject: Fixed documentation typo. --- doc/src/platforms/platform-notes.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc index 8f5b6a5..16e0c0f 100644 --- a/doc/src/platforms/platform-notes.qdoc +++ b/doc/src/platforms/platform-notes.qdoc @@ -517,7 +517,7 @@ Note that some modules rely on other modules. If your application uses QtXmlPatterns, QtWebkit or QtScript it may still require \c NetworkServices - \o as these modules rely on QtNetwork to go online. + as these modules rely on QtNetwork to go online. For more information see the documentation of the individual Qt classes. If a class does not mention Symbian capabilities, it requires none. -- cgit v0.12 From dcc9a7e72fe4c283df59378d08d75aecfa3b3b05 Mon Sep 17 00:00:00 2001 From: Peter Yard Date: Fri, 14 May 2010 10:14:25 +1000 Subject: Added snippet labels to QML Dial example. --- examples/declarative/dial/content/Dial.qml | 6 ++++++ examples/declarative/dial/dial-example.qml | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/declarative/dial/content/Dial.qml b/examples/declarative/dial/content/Dial.qml index f9ab3e3..6f24801 100644 --- a/examples/declarative/dial/content/Dial.qml +++ b/examples/declarative/dial/content/Dial.qml @@ -8,6 +8,7 @@ Item { Image { source: "background.png" } +//! [needle_shadow] Image { x: 93 y: 35 @@ -17,6 +18,8 @@ Item { angle: needleRotation.angle } } +//! [needle_shadow] +//! [needle] Image { id: needle x: 95; y: 33 @@ -33,5 +36,8 @@ Item { } } } +//! [needle] +//! [overlay] Image { x: 21; y: 18; source: "overlay.png" } +//! [overlay] } diff --git a/examples/declarative/dial/dial-example.qml b/examples/declarative/dial/dial-example.qml index fd899a5..dd51435 100644 --- a/examples/declarative/dial/dial-example.qml +++ b/examples/declarative/dial/dial-example.qml @@ -1,6 +1,7 @@ import Qt 4.7 import "content" +//! [0] Rectangle { color: "#545454" width: 300; height: 300 @@ -14,7 +15,10 @@ Rectangle { Rectangle { id: container - anchors { bottom: parent.bottom; left: parent.left; right: parent.right; leftMargin: 20; rightMargin: 20; bottomMargin: 10 } + anchors { bottom: parent.bottom; left: parent.left + right: parent.right; leftMargin: 20; rightMargin: 20 + bottomMargin: 10 + } height: 16 radius: 8 @@ -37,8 +41,10 @@ Rectangle { MouseArea { anchors.fill: parent - drag.target: parent; drag.axis: "XAxis"; drag.minimumX: 2; drag.maximumX: container.width - 32 + drag.target: parent; drag.axis: "XAxis"; drag.minimumX: 2 + drag.maximumX: container.width - 32 } } } } +//! [0] \ No newline at end of file -- cgit v0.12 From 08b6114240a6c02dbeb0297d0deeb538ebc3fde9 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 13 May 2010 10:16:48 +1000 Subject: Cherry pick fix for MOBILITY-828 from Qt Mobility. Change e5f8e3069d0de428a751e8a1dd88f3585f2d3f5f from Qt Mobility. --- .../bearer/symbian/qnetworksession_impl.cpp | 369 ++++++++++++--------- src/plugins/bearer/symbian/qnetworksession_impl.h | 15 +- src/plugins/bearer/symbian/symbianengine.cpp | 248 +++++++++----- src/plugins/bearer/symbian/symbianengine.h | 27 +- tests/auto/qnetworksession/lackey/main.cpp | 24 +- .../qnetworksession/test/tst_qnetworksession.cpp | 361 ++++++++++++-------- 6 files changed, 658 insertions(+), 386 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 1b9c8cc..04853c4 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -53,15 +53,17 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) - : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0), - iError(QNetworkSession::UnknownSessionError), - iALREnabled(0), iConnectInBackground(false) + : CActive(CActive::EPriorityStandard), engine(engine), + ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false), + iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iDeprecatedConnectionId(0), + iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false) { CActiveScheduler::Add(this); #ifdef SNAP_FUNCTIONALITY_AVAILABLE iMobility = NULL; #endif + TRAP_IGNORE(iConnectionMonitor.ConnectL()); } @@ -90,18 +92,72 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() // Close global 'Open C' RConnection setdefaultif(0); - - iConnectionMonitor.CancelNotifications(); + iConnectionMonitor.Close(); } +void QNetworkSessionPrivateImpl::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState) +{ + if (iHandleStateNotificationsFromManager) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId) + << "configurationStateChanged connMon ID : " << QString::number(connMonId) + << " : to a state: " << newState + << " whereas my current state is: " << state; +#endif + if (connMonId == iDeprecatedConnectionId) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "however status update from manager ignored because it related to already closed connection."; +#endif + return; + } + this->newState(newState, accessPointId); + } +} + +void QNetworkSessionPrivateImpl::configurationRemoved(QNetworkConfigurationPrivatePointer config) +{ + if (!publicConfig.isValid()) + return; + + SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(config); + + symbianConfig->mutex.lock(); + TUint32 configNumericId = symbianConfig->numericId; + symbianConfig->mutex.unlock(); + + symbianConfig = toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + TUint32 publicNumericId = symbianConfig->numericId; + symbianConfig->mutex.unlock(); + + if (configNumericId == publicNumericId) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "configurationRemoved IAP: " << QString::number(publicNumericId) << " : going to State: Invalid"; +#endif + this->newState(QNetworkSession::Invalid, publicNumericId); + } +} + void QNetworkSessionPrivateImpl::syncStateWithInterface() { if (!publicConfig.isValid()) return; - // Start monitoring changes in IAP states - TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this)); + if (iFirstSync && publicConfig.isValid()) { + QObject::connect(engine, SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)), + this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State))); + // Listen to configuration removals, so that in case the configuration + // this session is based on is removed, session knows to enter Invalid -state. + QObject::connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)), + this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer))); + } + // Start listening IAP state changes from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; // Check open connections to see if there is already // an open connection to selected IAP or SNAP @@ -137,11 +193,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() } if (state != QNetworkSession::Connected) { - // There were no open connections to used IAP or SNAP - if (iError == QNetworkSession::InvalidConfigurationError) { - newState(QNetworkSession::Invalid); - } else if ((publicConfig.state() & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { + if ((publicConfig.state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { newState(QNetworkSession::Disconnected); } else { newState(QNetworkSession::NotAvailable); @@ -245,13 +298,18 @@ QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const void QNetworkSessionPrivateImpl::open() { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "open() called, session state is: " << state << " and isOpen is: " + << isOpen; +#endif if (isOpen || (state == QNetworkSession::Connecting)) { return; } - - // Cancel notifications from RConnectionMonitor + + // Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring - iConnectionMonitor.CancelNotifications(); + iHandleStateNotificationsFromManager = false; // Configuration may have been invalidated after session creation by platform // (e.g. configuration has been deleted). @@ -259,19 +317,25 @@ void QNetworkSessionPrivateImpl::open() newState(QNetworkSession::Invalid); iError = QNetworkSession::InvalidConfigurationError; emit QNetworkSessionPrivate::error(iError); - syncStateWithInterface(); return; } - // If opening a (un)defined configuration, session emits error and enters - // NotAvailable -state. - if (publicConfig.state() == QNetworkConfiguration::Undefined || - publicConfig.state() == QNetworkConfiguration::Defined) { + // If opening a undefined configuration, session emits error and enters + // NotAvailable -state. Note that we will try ones in 'defined' state to avoid excessive + // need for WLAN scans (via updateConfigurations()), because user may have walked + // into a WLAN range, but periodic background scan has not occurred yet --> + // we don't want to force application to make frequent updateConfigurations() calls + // to be able to try if e.g. home WLAN is available. + if (publicConfig.state() == QNetworkConfiguration::Undefined) { newState(QNetworkSession::NotAvailable); iError = QNetworkSession::InvalidConfigurationError; emit QNetworkSessionPrivate::error(iError); return; } - + // Clear possible previous states + iStoppedByUser = false; + iClosedByUser = false; + iDeprecatedConnectionId = 0; + TInt error = iSocketServ.Connect(); if (error != KErrNone) { // Could not open RSocketServ @@ -446,9 +510,18 @@ TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const void QNetworkSessionPrivateImpl::close(bool allowSignals) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "close() called, session state is: " << state << " and isOpen is : " + << isOpen; +#endif if (!isOpen) { return; } + // Mark this session as closed-by-user so that we are able to report + // distinguish between stop() and close() state transitions + // when reporting. + iClosedByUser = true; SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(activeConfig)); @@ -469,8 +542,10 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) } #endif - if (ipConnectionNotifier) { + if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) { ipConnectionNotifier->StopNotifications(); + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; } iConnection.Close(); @@ -488,7 +563,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) newState(QNetworkSession::Closing); } - syncStateWithInterface(); if (allowSignals) { if (publicConfig.type() == QNetworkConfiguration::UserChoice) { newState(QNetworkSession::Disconnected); @@ -499,9 +573,19 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) void QNetworkSessionPrivateImpl::stop() { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "stop() called, session state is: " << state << " and isOpen is : " + << isOpen; +#endif if (!isOpen && publicConfig.isValid() && publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "since session is not open, using RConnectionMonitor to stop() the interface"; +#endif + iStoppedByUser = true; // If the publicConfig is type of IAP, enumerate through connections at // connection monitor. If publicConfig is active in that list, stop it. // Otherwise there is nothing to stop. Note: because this QNetworkSession is not open, @@ -532,11 +616,25 @@ void QNetworkSessionPrivateImpl::stop() ETrue); } } + // Enter disconnected state right away since the session is not even open. + // Symbian^3 connection monitor does not emit KLinkLayerClosed when + // connection is stopped via connection monitor. + newState(QNetworkSession::Disconnected); } } else if (isOpen) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "since session is open, using RConnection to stop() the interface"; +#endif // Since we are open, use RConnection to stop the interface isOpen = false; + iStoppedByUser = true; newState(QNetworkSession::Closing); + if (ipConnectionNotifier) { + ipConnectionNotifier->StopNotifications(); + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; + } iConnection.Stop(RConnection::EStopAuthoritative); isOpen = true; close(false); @@ -654,6 +752,10 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo* void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "roaming Error() occured"; +#endif if (isOpen) { isOpen = false; activeConfig = QNetworkConfiguration(); @@ -671,6 +773,11 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) // changes immediately to Disconnected. newState(QNetworkSession::Disconnected); emit closed(); + } else if (iStoppedByUser) { + // If the user of this session has called the stop() and + // configuration is based on internet SNAP, this needs to be + // done here because platform might roam. + newState(QNetworkSession::Disconnected); } } #endif @@ -975,7 +1082,12 @@ void QNetworkSessionPrivateImpl::RunL() isOpen = false; activeConfig = QNetworkConfiguration(); serviceConfig = QNetworkConfiguration(); - iError = QNetworkSession::UnknownSessionError; + if (publicConfig.state() == QNetworkConfiguration::Undefined || + publicConfig.state() == QNetworkConfiguration::Defined) { + iError = QNetworkSession::InvalidConfigurationError; + } else { + iError = QNetworkSession::UnknownSessionError; + } emit QNetworkSessionPrivate::error(iError); Cancel(); if (ipConnectionNotifier) { @@ -991,8 +1103,16 @@ 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 +// and checked if it matches the configuration this session is based on. bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "NEW STATE, IAP ID : " << QString::number(accessPointId) << " , newState : " << QString::number(newState); +#endif // Make sure that activeConfig is always updated when SNAP is signaled to be // connected. if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork && @@ -1027,9 +1147,29 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) { return false; } + + // Make sure that Connected state is not reported when Connection is + // already Closing. + // Note: Stopping connection results sometimes KLinkLayerOpen + // to be reported first (just before KLinkLayerClosed). + if (state == QNetworkSession::Closing && newState == QNetworkSession::Connected) { + return false; + } + + // Make sure that some lagging 'closing' state-changes do not overwrite + // if we are already disconnected or closed. + if (state == QNetworkSession::Disconnected && newState == QNetworkSession::Closing) { + return false; + } bool emitSessionClosed = false; - if (isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) { + + // If we abruptly go down and user hasn't closed the session, we've been aborted. + // Note that session may be in 'closing' state and not in 'connected' state, because + // depending on platform the platform may report KConfigDaemonStartingDeregistration + // event before KLinkLayerClosed + if ((isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) || + (isOpen && !iClosedByUser && newState == QNetworkSession::Disconnected)) { // Active & Connected state should change directly to Disconnected state // only when something forces connection to close (eg. when another // application or session stops connection or when network drops @@ -1043,14 +1183,17 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (ipConnectionNotifier) { ipConnectionNotifier->StopNotifications(); } - // Start monitoring changes in IAP states - TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this)); + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; emitSessionClosed = true; // Emit SessionClosed after state change has been reported } bool retVal = false; if (accessPointId == 0) { state = newState; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed A to: " << state; +#endif emit stateChanged(state); retVal = true; } else { @@ -1063,6 +1206,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint configLocker.unlock(); state = newState; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state; +#endif emit stateChanged(state); retVal = true; } @@ -1075,6 +1221,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint configLocker.unlock(); state = newState; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state; +#endif emit stateChanged(state); retVal = true; } @@ -1088,20 +1237,13 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (symbianConfig->numericId == accessPointId) { if (newState == QNetworkSession::Connected) { - // Make sure that when AccessPoint is reported to be Connected - // also state of the related configuration changes to Active. - symbianConfig->state = QNetworkConfiguration::Active; - configLocker.unlock(); - state = newState; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D to: " << state; +#endif emit stateChanged(state); retVal = true; } else { - if (newState == QNetworkSession::Disconnected) { - // Make sure that when AccessPoint is reported to be disconnected - // also state of the related configuration changes from Active to Defined. - symbianConfig->state = QNetworkConfiguration::Defined; - } QNetworkConfiguration config = bestConfigFromSNAP(publicConfig); if ((config.state() == QNetworkConfiguration::Defined) || (config.state() == QNetworkConfiguration::Discovered)) { @@ -1109,6 +1251,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint configLocker.unlock(); state = newState; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E to: " << state; +#endif emit stateChanged(state); retVal = true; } @@ -1121,6 +1266,19 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (emitSessionClosed) { emit closed(); } + if (state == QNetworkSession::Disconnected) { + // The connection has gone down, and processing of status updates must be + // stopped. Depending on platform, there may come 'connecting/connected' states + // considerably later (almost a second). Connection id is an increasing + // number, so this does not affect next _real_ 'conneting/connected' states. + + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + iDeprecatedConnectionId = symbianConfig->connectionId; + symbianConfig->mutex.unlock(); + } return retVal; } @@ -1129,6 +1287,9 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne TInt aError, TUint accessPointId) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << QString::number(accessPointId) << " , status : " << QString::number(aConnectionStatus); +#endif switch (aConnectionStatus) { // Connection unitialised @@ -1167,6 +1328,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne case KCsdGotLoginInfo: break; + case KConfigDaemonStartingRegistration: // Creating connection (e.g. GPRS activation) case KCsdStartingConnect: case KCsdFinishedConnect: @@ -1193,6 +1355,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne case KDataTransferTemporarilyBlocked: break; + case KConfigDaemonStartingDeregistration: // Hangup or GRPS deactivation case KConnectionStartingClose: newState(QNetworkSession::Closing,accessPointId); @@ -1200,136 +1363,26 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne // Connection closed case KConnectionClosed: - break; - case KLinkLayerClosed: newState(QNetworkSession::Disconnected,accessPointId); + // Report manager about this to make sure this event + // is received by all interseted parties (mediated by + // manager because it does always receive all events from + // connection monitor). +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "reporting disconnection to manager."; +#endif + if (publicConfig.isValid()) { + engine->configurationStateChangeReport(toSymbianConfig(privateConfiguration(publicConfig))->numericId, QNetworkSession::Disconnected); + } break; - // Unhandled state default: break; } } -void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent) -{ - switch (aEvent.EventType()) - { - case EConnMonConnectionStatusChange: - { - CConnMonConnectionStatusChange* realEvent; - realEvent = (CConnMonConnectionStatusChange*) &aEvent; - - TUint connectionId = realEvent->ConnectionId(); - TInt connectionStatus = realEvent->ConnectionStatus(); - - // Try to Find IAP Id using connection Id - TUint apId = 0; - if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { - QList subConfigurations = publicConfig.children(); - for (int i = 0; i < subConfigurations.count(); i++ ) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(subConfigurations[i])); - - QMutexLocker configLocker(&symbianConfig->mutex); - - if (symbianConfig->connectionId == connectionId) { - apId = symbianConfig->numericId; - break; - } - } - } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(publicConfig)); - - symbianConfig->mutex.lock(); - if (symbianConfig->connectionId == connectionId) - apId = symbianConfig->numericId; - symbianConfig->mutex.unlock(); - } - - if (apId > 0) { - handleSymbianConnectionStatusChange(connectionStatus, KErrNone, apId); - } - } - break; - - case EConnMonCreateConnection: - { - CConnMonCreateConnection* realEvent; - realEvent = (CConnMonCreateConnection*) &aEvent; - TUint apId; - TUint connectionId = realEvent->ConnectionId(); - TRequestStatus status; - iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status); - User::WaitForRequest(status); - if (status.Int() == KErrNone) { - // Store connection id to related AccessPoint Configuration - if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { - QList subConfigurations = publicConfig.children(); - for (int i = 0; i < subConfigurations.count(); i++ ) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(subConfigurations[i])); - - QMutexLocker configLocker(&symbianConfig->mutex); - - if (symbianConfig->numericId == apId) { - symbianConfig->connectionId = connectionId; - break; - } - } - } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(publicConfig)); - - symbianConfig->mutex.lock(); - if (symbianConfig->numericId == apId) - symbianConfig->connectionId = connectionId; - symbianConfig->mutex.unlock(); - } - } - } - break; - - case EConnMonDeleteConnection: - { - CConnMonDeleteConnection* realEvent; - realEvent = (CConnMonDeleteConnection*) &aEvent; - TUint connectionId = realEvent->ConnectionId(); - // Remove connection id from related AccessPoint Configuration - if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { - QList subConfigurations = publicConfig.children(); - for (int i = 0; i < subConfigurations.count(); i++ ) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(subConfigurations[i])); - - QMutexLocker configLocker(&symbianConfig->mutex); - - if (symbianConfig->connectionId == connectionId) { - symbianConfig->connectionId = 0; - break; - } - } - } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(publicConfig)); - - symbianConfig->mutex.lock(); - if (symbianConfig->connectionId == connectionId) - symbianConfig->connectionId = 0; - symbianConfig->mutex.unlock(); - } - } - break; - - default: - // For unrecognized events - break; - } -} - -ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection) +ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection) : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection) { CActiveScheduler::Add(this); diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 7116519..9767293 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -75,9 +75,8 @@ class SymbianEngine; class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, #ifdef SNAP_FUNCTIONALITY_AVAILABLE - public MMobilityProtocolResp, + public MMobilityProtocolResp #endif - public MConnectionMonitorObserver { Q_OBJECT public: @@ -130,8 +129,9 @@ protected: // From CActive void RunL(); void DoCancel(); -private: // MConnectionMonitorObserver - void EventL(const CConnMonEventBase& aEvent); +private Q_SLOTS: + void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState); + void configurationRemoved(QNetworkConfigurationPrivatePointer config); private: TUint iapClientCount(TUint aIAPId) const; @@ -157,6 +157,13 @@ private: // data mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; ConnectionProgressNotifier* ipConnectionNotifier; + + bool iHandleStateNotificationsFromManager; + bool iFirstSync; + bool iStoppedByUser; + bool iClosedByUser; + TUint32 iDeprecatedConnectionId; + #ifdef SNAP_FUNCTIONALITY_AVAILABLE CActiveCommsMobilityApiExt* iMobility; #endif diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index 8e9675e..cea8b67 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -45,14 +45,14 @@ #include #include #include +#include #include #include #include // For randgen seeding #include // For randgen seeding -// #define QT_BEARERMGMT_CONFIGMGR_DEBUG -#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG #include #endif @@ -73,7 +73,9 @@ QT_BEGIN_NAMESPACE -static const int KValueThatWillBeAddedToSNAPId = 1000; +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + static const int KValueThatWillBeAddedToSNAPId = 1000; +#endif static const int KUserChoiceIAPId = 0; SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate() @@ -657,26 +659,34 @@ void SymbianEngine::updateActiveAccessPoints() iConnectionMonitor.GetConnectionCount(connectionCount, status); User::WaitForRequest(status); - // Go through all connections and set state of related IAPs to Active + // Go through all connections and set state of related IAPs to Active. + // Status needs to be checked carefully, because ConnMon lists also e.g. + // WLAN connections that are being currently tried --> we don't want to + // state these as active. TUint connectionId; TUint subConnectionCount; TUint apId; + TInt connectionStatus; if (status.Int() == KErrNone) { for (TUint i = 1; i <= connectionCount; i++) { iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount); iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); User::WaitForRequest(status); QString ident = QString::number(qHash(apId)); - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); if (ptr) { - online = true; - inactiveConfigs.removeOne(ident); + iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status); + User::WaitForRequest(status); + if (connectionStatus == KLinkLayerOpen) { + online = true; + inactiveConfigs.removeOne(ident); - toSymbianConfig(ptr)->connectionId = connectionId; + QMutexLocker configLocker(&ptr->mutex); + toSymbianConfig(ptr)->connectionId = connectionId; - // Configuration is Active - changeConfigurationStateTo(ptr, QNetworkConfiguration::Active); + // Configuration is Active + changeConfigurationStateTo(ptr, QNetworkConfiguration::Active); + } } } } @@ -733,12 +743,12 @@ void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapIn } } - // Make sure that state of rest of the IAPs won't be Discovered or Active + // Make sure that state of rest of the IAPs won't be Active foreach (const QString &iface, unavailableConfigs) { QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); if (ptr) { // Configuration is Defined - changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined); + changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered); } } } @@ -894,21 +904,22 @@ void SymbianEngine::RunL() QMutexLocker locker(&mutex); if (iIgnoringUpdates) { -#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG - qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently)."); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug("QNCM CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently)."); #endif return; } if (iStatus != KErrCancel) { RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int()); + switch (event) { case RDbNotifier::EUnlock: /** All read locks have been removed. */ case RDbNotifier::ECommit: /** A transaction has been committed. */ case RDbNotifier::ERollback: /** A transaction has been rolled back */ case RDbNotifier::ERecover: /** The database has been recovered */ -#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG - qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int()); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int()); #endif iIgnoringUpdates = true; // Other events than ECommit get lower priority. In practice with those events, @@ -957,73 +968,95 @@ void SymbianEngine::DoCancel() ipCommsDB->CancelRequestNotification(); } - void SymbianEngine::EventL(const CConnMonEventBase& aEvent) { QMutexLocker locker(&mutex); switch (aEvent.EventType()) { - case EConnMonCreateConnection: + case EConnMonConnectionStatusChange: { - CConnMonCreateConnection* realEvent; - realEvent = (CConnMonCreateConnection*) &aEvent; - TUint subConnectionCount = 0; - TUint apId; - TUint connectionId = realEvent->ConnectionId(); - TRequestStatus status; - iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); - User::WaitForRequest(status); - QString ident = QString::number(qHash(apId)); - - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); - if (ptr) { - toSymbianConfig(ptr)->connectionId = connectionId; - // Configuration is Active - if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) - updateStatesToSnaps(); - - if (!iOnline) { - iOnline = true; - - locker.unlock(); - emit this->onlineStateChanged(iOnline); - locker.relock(); + CConnMonConnectionStatusChange* realEvent; + realEvent = (CConnMonConnectionStatusChange*) &aEvent; + TInt connectionStatus = realEvent->ConnectionStatus(); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId(); +#endif + if (connectionStatus == KConfigDaemonStartingRegistration) { + TUint connectionId = realEvent->ConnectionId(); + TUint subConnectionCount = 0; + TUint apId; + TRequestStatus status; + iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); + User::WaitForRequest(status); + QString ident = QString::number(qHash(apId)); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + toSymbianConfig(ptr)->connectionId = connectionId; + emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connecting); } - } - } - break; - - case EConnMonDeleteConnection: - { - CConnMonDeleteConnection* realEvent; - realEvent = (CConnMonDeleteConnection*) &aEvent; - TUint connectionId = realEvent->ConnectionId(); - - QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId); - if (ptr) { - toSymbianConfig(ptr)->connectionId = 0; - // Configuration is either Defined or Discovered - if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) - updateStatesToSnaps(); - } - - bool online = false; - foreach (const QString &iface, accessPointConfigurations.keys()) { - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); - if (ptr->state == QNetworkConfiguration::Active) { - online = true; - break; + } else if (connectionStatus == KLinkLayerOpen) { + // Connection has been successfully opened + TUint connectionId = realEvent->ConnectionId(); + TUint subConnectionCount = 0; + TUint apId; + TRequestStatus status; + iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); + User::WaitForRequest(status); + QString ident = QString::number(qHash(apId)); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + toSymbianConfig(ptr)->connectionId = connectionId; + // Configuration is Active + if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) { + updateStatesToSnaps(); + } + emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connected); + if (!iOnline) { + iOnline = true; + emit this->onlineStateChanged(iOnline); + } } - } - if (iOnline != online) { - iOnline = online; + } else if (connectionStatus == KConfigDaemonStartingDeregistration) { + TUint connectionId = realEvent->ConnectionId(); + QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Closing); + } + } else if (connectionStatus == KLinkLayerClosed || + connectionStatus == KConnectionClosed) { + // Connection has been closed. Which of the above events is reported, depends on the Symbian + // platform. + TUint connectionId = realEvent->ConnectionId(); + QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId); + if (ptr) { + // Configuration is either Defined or Discovered + if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) { + updateStatesToSnaps(); + } - locker.unlock(); - emit this->onlineStateChanged(iOnline); - locker.relock(); + QMutexLocker configLocker(&ptr->mutex); + emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Disconnected); + } + + bool online = false; + foreach (const QString &iface, accessPointConfigurations.keys()) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface); + QMutexLocker configLocker(&ptr->mutex); + if (ptr->state == QNetworkConfiguration::Active) { + online = true; + break; + } + } + if (iOnline != online) { + iOnline = online; + emit this->onlineStateChanged(iOnline); + } } } - break; + break; case EConnMonIapAvailabilityChange: { @@ -1051,21 +1084,78 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) } break; + case EConnMonCreateConnection: + { + // This event is caught to keep connection monitor IDs up-to-date. + CConnMonCreateConnection* realEvent; + realEvent = (CConnMonCreateConnection*) &aEvent; + TUint subConnectionCount = 0; + TUint apId; + TUint connectionId = realEvent->ConnectionId(); + TRequestStatus status; + iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status); + User::WaitForRequest(status); + QString ident = QString::number(qHash(apId)); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name; +#endif + toSymbianConfig(ptr)->connectionId = connectionId; + } + } + break; default: // For unrecognized events break; } } -// Waits for 1..4 seconds. +// Sessions may use this function to report configuration state changes, +// because on some Symbian platforms (especially Symbian^3) all state changes are not +// reported by the RConnectionMonitor, in particular in relation to stop() call, +// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize +// this data here so that other sessions may benefit from it too (not all sessions necessarily have +// RConnection progress notifiers available but they relay on having e.g. disconnected information from +// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome. +void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState) +{ +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState; +#endif + switch (newState) { + case QNetworkSession::Disconnected: + { + QString ident = QString::number(qHash(accessPointId)); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident); + if (ptr) { + // Configuration is either Defined or Discovered + if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) { + updateStatesToSnaps(); + } + + QMutexLocker configLocker(&ptr->mutex); + emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, + toSymbianConfig(ptr)->connectionId, + QNetworkSession::Disconnected); + } + } + break; + default: + break; + } +} + +// Waits for 2..6 seconds. void SymbianEngine::waitRandomTime() { - iTimeToWait = (qAbs(qrand()) % 5) * 1000; - if (iTimeToWait < 1000) { - iTimeToWait = 1000; + iTimeToWait = (qAbs(qrand()) % 7) * 1000; + if (iTimeToWait < 2000) { + iTimeToWait = 2000; } -#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG - qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug("QNCM waiting random time: %d ms", iTimeToWait); #endif QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit())); iIgnoreEventLoop->exec(); @@ -1076,11 +1166,11 @@ QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aCon QMutexLocker locker(&mutex); QNetworkConfiguration item; - QHash::const_iterator i = accessPointConfigurations.constBegin(); while (i != accessPointConfigurations.constEnd()) { QNetworkConfigurationPrivatePointer ptr = i.value(); + QMutexLocker configLocker(&ptr->mutex); if (toSymbianConfig(ptr)->connectionId == aConnectionId) return ptr; diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h index afb37de..7d565db 100644 --- a/src/plugins/bearer/symbian/symbianengine.h +++ b/src/plugins/bearer/symbian/symbianengine.h @@ -52,6 +52,9 @@ #include #endif +// Uncomment and compile QtBearer to gain detailed state tracing +// #define QT_BEARERMGMT_SYMBIAN_DEBUG + class CCommsDatabase; class QEventLoop; @@ -90,7 +93,18 @@ public: Bearer bearer; + // So called IAP id from the platform. Remains constant as long as the + // platform is aware of the configuration ie. it is stored in the databases + // --> does not depend on whether connections are currently open or not. + // In practice is the same for the lifetime of the QNetworkConfiguration. TUint32 numericId; + // So called connection id, or connection monitor ID. A dynamic ID assigned + // by RConnectionMonitor whenever a new connection is opened. ConnectionID and + // numericId/IAP id have 1-to-1 mapping during the lifetime of the connection at + // connection monitor. Notably however it changes whenever a new connection to + // a given IAP is created. In a sense it is constant during the time the + // configuration remains between states Discovered..Active..Discovered, do not + // however relay on this. TUint connectionId; }; @@ -124,6 +138,9 @@ public: Q_SIGNALS: void onlineStateChanged(bool isOnline); + void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, + QNetworkSession::State newState); + public Q_SLOTS: void updateConfigurations(); @@ -157,12 +174,17 @@ private: void startMonitoringIAPData(TUint32 aIapId); QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId); -protected: // From CActive +protected: + // From CActive void RunL(); void DoCancel(); -private: // MConnectionMonitorObserver +private: + // MConnectionMonitorObserver void EventL(const CConnMonEventBase& aEvent); + // For QNetworkSessionPrivate to indicate about state changes + void configurationStateChangeReport(TUint32 accessPointId, + QNetworkSession::State newState); private: // Data bool iFirstUpdate; @@ -181,6 +203,7 @@ private: // Data friend class QNetworkSessionPrivate; friend class AccessPointsAvailabilityScanner; + friend class QNetworkSessionPrivateImpl; #ifdef SNAP_FUNCTIONALITY_AVAILABLE RCmManager iCmManager; diff --git a/tests/auto/qnetworksession/lackey/main.cpp b/tests/auto/qnetworksession/lackey/main.cpp index 8759b52..ec2fad9 100644 --- a/tests/auto/qnetworksession/lackey/main.cpp +++ b/tests/auto/qnetworksession/lackey/main.cpp @@ -47,6 +47,8 @@ #include #include +#include +#include #include QT_USE_NAMESPACE @@ -60,15 +62,14 @@ int main(int argc, char** argv) { QCoreApplication app(argc, argv); - // Cannot read/write to processes on WinCE or Symbian. - // Easiest alternative is to use sockets for IPC. - - QLocalSocket oopSocket; - - oopSocket.connectToServer("tst_qnetworksession"); - oopSocket.waitForConnected(-1); - + // Update configurations so that everything is up to date for this process too. + // Event loop is used to wait for awhile. QNetworkConfigurationManager manager; + manager.updateConfigurations(); + QEventLoop iIgnoreEventLoop; + QTimer::singleShot(3000, &iIgnoreEventLoop, SLOT(quit())); + iIgnoreEventLoop.exec(); + QList discovered = manager.allConfigurations(QNetworkConfiguration::Discovered); @@ -82,6 +83,13 @@ int main(int argc, char** argv) return NO_DISCOVERED_CONFIGURATIONS_ERROR; } + // Cannot read/write to processes on WinCE or Symbian. + // Easiest alternative is to use sockets for IPC. + QLocalSocket oopSocket; + + oopSocket.connectToServer("tst_qnetworksession"); + oopSocket.waitForConnected(-1); + qDebug() << "Lackey started"; QNetworkSession *session = 0; diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 23cdc6a..8ab9da2 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -100,6 +100,7 @@ private slots: private: QNetworkConfigurationManager manager; + QMap testsToRun; int inProcessSessionManagementCount; @@ -117,6 +118,7 @@ private: bool openSession(QNetworkSession *session); bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true); void updateConfigurations(); +void printConfigurations(); QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType); void tst_QNetworkSession::initTestCase() @@ -125,7 +127,19 @@ void tst_QNetworkSession::initTestCase() qRegisterMetaType("QNetworkSession::SessionError"); qRegisterMetaType("QNetworkConfiguration"); qRegisterMetaType("QNetworkConfiguration::Type"); - + + // If you wish to skip tests, set value as false. This is often very convinient because tests are so lengthy. + // Better way still would be to make this readable from a file. + testsToRun["robustnessBombing"] = true; + testsToRun["outOfProcessSession"] = true; + testsToRun["invalidSession"] = true; + testsToRun["repeatedOpenClose"] = true; + testsToRun["roamingErrorCodes"] = true; + testsToRun["sessionStop"] = true; + testsToRun["sessionProperties"] = true; + testsToRun["userChoiceSession"] = true; + testsToRun["sessionOpenCloseStop"] = true; + #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); @@ -238,6 +252,10 @@ void tst_QNetworkSession::cleanupTestCase() // Robustness test for calling interfaces in nonsense order / with nonsense parameters void tst_QNetworkSession::robustnessBombing() { + if (!testsToRun["robustnessBombing"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } + QNetworkConfigurationManager mgr; QNetworkSession testSession(mgr.defaultConfiguration()); // Should not reset even session is not opened @@ -253,7 +271,10 @@ void tst_QNetworkSession::robustnessBombing() void tst_QNetworkSession::invalidSession() -{ +{ + if (!testsToRun["invalidSession"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } // 1. Verify that session created with invalid configuration remains in invalid state QNetworkSession session(QNetworkConfiguration(), 0); QVERIFY(!session.isOpen()); @@ -270,11 +291,24 @@ void tst_QNetworkSession::invalidSession() QVERIFY(error == QNetworkSession::InvalidConfigurationError); QVERIFY(session.error() == QNetworkSession::InvalidConfigurationError); QVERIFY(session.state() == QNetworkSession::Invalid); - + #ifdef QNETWORKSESSION_MANUAL_TESTS + + QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint); + if (invalidatedConfig.isValid()) { + // 3. Verify that invalidating a session after its successfully configured works + QNetworkSession invalidatedSession(invalidatedConfig); + qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name(); + QTest::qWait(60000); + QVERIFY(!invalidatedConfig.isValid()); + QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid); + qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name(); + QTest::qWait(60000); + } + QNetworkConfiguration definedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint); if (definedConfig.isValid()) { - // 3. Verify that opening a session with defined configuration emits error and enters notavailable-state + // 4. Verify that opening a session with defined configuration emits error and enters notavailable-state // TODO these timer waits should be changed to waiting appropriate signals, now these wait excessively qDebug() << "Shutdown WLAN IAP (waiting 60 seconds): " << definedConfig.name(); QTest::qWait(60000); @@ -283,43 +317,27 @@ void tst_QNetworkSession::invalidSession() QNetworkSession definedSession(definedConfig); QSignalSpy errorSpy(&definedSession, SIGNAL(error(QNetworkSession::SessionError))); QNetworkSession::SessionError sessionError; + updateConfigurations(); definedSession.open(); +#ifdef Q_OS_SYMBIAN + // On symbian, the connection opening is tried even with defined state. + qDebug("Waiting for 10 seconds to all signals to propagate."); + QTest::qWait(10000); +#endif + updateConfigurations(); QVERIFY(definedConfig.isValid()); // Session remains valid QVERIFY(definedSession.state() == QNetworkSession::NotAvailable); // State is not available because WLAN is not in coverage QVERIFY(!errorSpy.isEmpty()); // Session tells with error about invalidated configuration sessionError = qvariant_cast (errorSpy.first().at(0)); - qDebug() << "Error code is: " << sessionError; QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError); - qDebug() << "Turn the WLAN IAP back on (waiting 60 seconds): " << definedConfig.name(); QTest::qWait(60000); - updateConfigurations(); - + updateConfigurations(); QVERIFY(definedConfig.state() == QNetworkConfiguration::Discovered); } - - QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint); - if (invalidatedConfig.isValid()) { - // 4. Verify that invalidating a session after its successfully configured works - QNetworkSession invalidatedSession(invalidatedConfig); - QSignalSpy errorSpy(&invalidatedSession, SIGNAL(error(QNetworkSession::SessionError))); - QNetworkSession::SessionError sessionError; - - qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name(); - QTest::qWait(60000); - - invalidatedSession.open(); - QVERIFY(!invalidatedConfig.isValid()); - QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid); - QVERIFY(!errorSpy.isEmpty()); - - sessionError = qvariant_cast (errorSpy.first().at(0)); - QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError); - qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name(); - QTest::qWait(60000); - } + #endif } @@ -337,12 +355,12 @@ void tst_QNetworkSession::sessionProperties_data() void tst_QNetworkSession::sessionProperties() { + if (!testsToRun["sessionProperties"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } QFETCH(QNetworkConfiguration, configuration); - QNetworkSession session(configuration); - QVERIFY(session.configuration() == configuration); - QStringList validBearerNames = QStringList() << QLatin1String("Unknown") << QLatin1String("Ethernet") << QLatin1String("WLAN") @@ -356,9 +374,6 @@ void tst_QNetworkSession::sessionProperties() if (!configuration.isValid()) { QVERIFY(configuration.bearerName().isEmpty()); } else { - qDebug() << "Type:" << configuration.type() - << "Bearer:" << configuration.bearerName(); - switch (configuration.type()) { case QNetworkConfiguration::ServiceNetwork: @@ -374,9 +389,7 @@ void tst_QNetworkSession::sessionProperties() // QNetworkSession::interface() should return an invalid interface unless // session is in the connected state. - qDebug() << "Session state:" << session.state(); #ifndef QT_NO_NETWORKINTERFACE - qDebug() << "Session iface:" << session.interface().isValid() << session.interface().name(); #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__)) // On Symbian emulator, the support for data bearers is limited QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid()); @@ -420,7 +433,12 @@ void tst_QNetworkSession::repeatedOpenClose_data() { } // Tests repeated-open close. -void tst_QNetworkSession::repeatedOpenClose() { +void tst_QNetworkSession::repeatedOpenClose() +{ + if (!testsToRun["repeatedOpenClose"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } + QFETCH(QString, bearerType); QFETCH(QNetworkConfiguration::Type, configurationType); QFETCH(int, repeatTimes); @@ -436,13 +454,20 @@ void tst_QNetworkSession::repeatedOpenClose() { !closeSession(&permanentSession)) { QSKIP("Unable to open/close session, skipping this round of repeated open-close test.", SkipSingle); } - for (int i = repeatTimes; i > 0; i--) { + for (int i = 0; i < repeatTimes; i++) { + qDebug() << "Opening, loop number " << i; QVERIFY(openSession(&permanentSession)); + qDebug() << "Closing, loop number, then waiting 5 seconds: " << i; QVERIFY(closeSession(&permanentSession)); + QTest::qWait(5000); } } -void tst_QNetworkSession::roamingErrorCodes() { +void tst_QNetworkSession::roamingErrorCodes() +{ + if (!testsToRun["roamingErrorCodes"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } #ifndef Q_OS_SYMBIAN QSKIP("Roaming supported on Symbian.", SkipAll); #else @@ -466,41 +491,11 @@ void tst_QNetworkSession::roamingErrorCodes() { adminIapSession.stop(); // requires NetworkControl capabilities QTRY_VERIFY(!errorSpy.isEmpty()); // wait for error signals QNetworkSession::SessionError error = qvariant_cast(errorSpy.first().at(0)); + QTest::qWait(2000); // Wait for a moment to all platform signals to propagate QVERIFY(error == QNetworkSession::SessionAbortedError); QVERIFY(iapSession.state() == QNetworkSession::Disconnected); QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected); #endif // Q_OS_SYMBIAN - -#ifdef QNETWORKSESSION_MANUAL_TESTS - // Check for roaming error. - // Case requires that you have controllable WLAN in Internet SNAP (only). - QNetworkConfiguration snapConfig = suitableConfiguration("bearer_not_relevant_with_snaps", QNetworkConfiguration::ServiceNetwork); - if (!snapConfig.isValid()) { - QSKIP("No SNAP accessible, skipping test.", SkipAll); - } - QNetworkSession snapSession(snapConfig); - QVERIFY(openSession(&snapSession)); - QSignalSpy errorSpySnap(&snapSession, SIGNAL(error(QNetworkSession::SessionError))); - qDebug("Disconnect the WLAN now"); - QTRY_VERIFY(!errorSpySnap.isEmpty()); // wait for error signals - QVERIFY(errorSpySnap.count() == 1); - error = qvariant_cast(errorSpySnap.first().at(0)); - qDebug() << "Error received when turning off wlan on SNAP: " << error; - QVERIFY(error == QNetworkSession::RoamingError); - - qDebug("Connect the WLAN now"); - QTest::qWait(60000); // Wait for WLAN to get up - QNetworkConfiguration wlanIapConfig2 = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint); - QNetworkSession iapSession2(wlanIapConfig2); - QVERIFY(openSession(&iapSession2)); - QSignalSpy errorSpy2(&iapSession2, SIGNAL(error(QNetworkSession::SessionError))); - qDebug("Disconnect the WLAN now"); - QTRY_VERIFY(!errorSpy2.isEmpty()); // wait for error signals - QVERIFY(errorSpy2.count() == 1); - error = qvariant_cast(errorSpy2.first().at(0)); - QVERIFY(error == QNetworkSession::SessionAbortedError); - QVERIFY(iapSession2.state() == QNetworkSession::Disconnected); -#endif } @@ -515,6 +510,9 @@ void tst_QNetworkSession::sessionStop_data() { void tst_QNetworkSession::sessionStop() { + if (!testsToRun["sessionStop"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } #ifndef Q_OS_SYMBIAN QSKIP("Testcase contains mainly Symbian specific checks, because it is only platform to really support interface (IAP-level) Stop.", SkipAll); #endif @@ -522,6 +520,9 @@ void tst_QNetworkSession::sessionStop() QFETCH(QNetworkConfiguration::Type, configurationType); int configWaitdelayInMs = 2000; + + updateConfigurations(); + printConfigurations(); QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType); if (!config.isValid()) { @@ -539,6 +540,9 @@ void tst_QNetworkSession::sessionStop() QSignalSpy closedSessionStateChangedSpy(&closedSession, SIGNAL(stateChanged(QNetworkSession::State))); QSignalSpy closedErrorSpy(&closedSession, SIGNAL(error(QNetworkSession::SessionError))); + QSignalSpy openedSessionClosedSpy(&openedSession, SIGNAL(closed())); + QSignalSpy openedSessionStateChangedSpy(&openedSession, SIGNAL(stateChanged(QNetworkSession::State))); + QSignalSpy innocentSessionClosedSpy(&innocentSession, SIGNAL(closed())); QSignalSpy innocentSessionStateChangedSpy(&innocentSession, SIGNAL(stateChanged(QNetworkSession::State))); QSignalSpy innocentErrorSpy(&innocentSession, SIGNAL(error(QNetworkSession::SessionError))); @@ -554,10 +558,18 @@ void tst_QNetworkSession::sessionStop() closedSessionClosedSpy.clear(); closedSessionStateChangedSpy.clear(); closedErrorSpy.clear(); + openedSessionStateChangedSpy.clear(); + openedSessionClosedSpy.clear(); + openedSession.stop(); - QVERIFY(openedSession.state() == QNetworkSession::Disconnected); + qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs); QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals + + // First to closing, then to disconnected + QVERIFY(openedSessionStateChangedSpy.count() == 2); + QVERIFY(!openedSessionClosedSpy.isEmpty()); + QVERIFY(openedSession.state() == QNetworkSession::Disconnected); QVERIFY(config.state() != QNetworkConfiguration::Active); // 2. Verify that stopping a session based on non-connected configuration does nothing @@ -583,18 +595,20 @@ void tst_QNetworkSession::sessionStop() // 3. Check that stopping a opened session affects also other opened session based on the same configuration. if (config.type() == QNetworkConfiguration::InternetAccessPoint) { qDebug("----------3. Check that stopping a opened session affects also other opened session based on the same configuration."); + QVERIFY(openSession(&openedSession)); QVERIFY(openSession(&innocentSession)); - + configChangeSpy.clear(); innocentSessionClosedSpy.clear(); innocentSessionStateChangedSpy.clear(); innocentErrorSpy.clear(); - + openedSession.stop(); qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs); QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals - + QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals + QVERIFY(!innocentSessionClosedSpy.isEmpty()); QVERIFY(!innocentSessionStateChangedSpy.isEmpty()); QVERIFY(!innocentErrorSpy.isEmpty()); @@ -614,14 +628,19 @@ void tst_QNetworkSession::sessionStop() if (config.type() == QNetworkConfiguration::ServiceNetwork) { qDebug("----------4. Skip for SNAP configuration."); } else if (config.type() == QNetworkConfiguration::InternetAccessPoint) { - qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration"); - QVERIFY(openSession(&innocentSession)); + qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration"); + qDebug("----------4.1 Opening innocent session"); + QVERIFY(openSession(&innocentSession)); qDebug("Waiting for %d ms after open to make sure all platform indications are propagated", configWaitdelayInMs); QTest::qWait(configWaitdelayInMs); + qDebug("----------4.2 Calling closedSession.stop()"); closedSession.stop(); qDebug("Waiting for %d ms to get all configurationChange signals from platform..", configWaitdelayInMs); QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals + QTest::qWait(configWaitdelayInMs); + QTest::qWait(configWaitdelayInMs); + QVERIFY(!innocentSessionClosedSpy.isEmpty()); QVERIFY(!innocentSessionStateChangedSpy.isEmpty()); QVERIFY(!innocentErrorSpy.isEmpty()); @@ -653,6 +672,9 @@ void tst_QNetworkSession::userChoiceSession_data() void tst_QNetworkSession::userChoiceSession() { + if (!testsToRun["userChoiceSession"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } QFETCH(QNetworkConfiguration, configuration); QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice); @@ -786,6 +808,9 @@ void tst_QNetworkSession::sessionOpenCloseStop_data() void tst_QNetworkSession::sessionOpenCloseStop() { + if (!testsToRun["sessionOpenCloseStop"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } QFETCH(QNetworkConfiguration, configuration); QFETCH(bool, forceSessionStop); @@ -894,26 +919,30 @@ void tst_QNetworkSession::sessionOpenCloseStop() QVERIFY(session.error() == QNetworkSession::UnknownSessionError); session2.open(); - + QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty()); + if (errorSpy2.isEmpty()) { + QVERIFY(session2.isOpen()); + QVERIFY(session2.state() == QNetworkSession::Connected); + } QVERIFY(session.isOpen()); - QVERIFY(session2.isOpen()); QVERIFY(session.state() == QNetworkSession::Connected); - QVERIFY(session2.state() == QNetworkSession::Connected); #ifndef QT_NO_NETWORKINTERFACE #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__)) // On Symbian emulator, the support for data bearers is limited QVERIFY(session.interface().isValid()); #endif - QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress()); - QCOMPARE(session.interface().index(), session2.interface().index()); + if (errorSpy2.isEmpty()) { + QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress()); + QCOMPARE(session.interface().index(), session2.interface().index()); + } #endif } sessionOpenedSpy2.clear(); - if (forceSessionStop) { + if (forceSessionStop && session2.isOpen()) { // Test forcing the second session to stop the interface. QNetworkSession::State previousState = session.state(); #ifdef Q_CC_NOKIAX86 @@ -922,15 +951,17 @@ void tst_QNetworkSession::sessionOpenCloseStop() #else bool expectStateChange = previousState != QNetworkSession::Disconnected; #endif - session2.stop(); + // QNetworkSession::stop() must result either closed() signal + // or error() signal QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty()); - QVERIFY(!session2.isOpen()); if (!errorSpy2.isEmpty()) { - QVERIFY(!errorSpy.isEmpty()); + // QNetworkSession::stop() resulted error() signal for session2 + // => also session should emit error() signal + QTRY_VERIFY(!errorSpy.isEmpty()); // check for SessionAbortedError QNetworkSession::SessionError error = @@ -950,9 +981,12 @@ void tst_QNetworkSession::sessionOpenCloseStop() QVERIFY(errorSpy.isEmpty()); QVERIFY(errorSpy2.isEmpty()); - + + // Wait for Disconnected state + QTRY_NOOP(session2.state() == QNetworkSession::Disconnected); + if (expectStateChange) - QTRY_VERIFY(stateChangedSpy2.count() >= 2 || !errorSpy2.isEmpty()); + QTRY_VERIFY(stateChangedSpy2.count() >= 1 || !errorSpy2.isEmpty()); if (!errorSpy2.isEmpty()) { QVERIFY(session2.state() == previousState); @@ -996,16 +1030,29 @@ void tst_QNetworkSession::sessionOpenCloseStop() state = qvariant_cast(stateChangedSpy2.at(3).at(0)); QVERIFY(state == QNetworkSession::Disconnected); + + QTRY_VERIFY(session.state() == QNetworkSession::Roaming || + session.state() == QNetworkSession::Connected || + session.state() == QNetworkSession::Disconnected); + QTRY_VERIFY(stateChangedSpy.count() > 0); - state = qvariant_cast(stateChangedSpy.at(0).at(0)); + state = qvariant_cast(stateChangedSpy.at(stateChangedSpy.count() - 1).at(0)); + if (state == QNetworkSession::Roaming) { - QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1); - if (stateChangedSpy.count() > 1 && - qvariant_cast(stateChangedSpy.at(1).at(0)) == - QNetworkSession::Connected) { - roamedSuccessfully = true; + QTRY_VERIFY(session.state() == QNetworkSession::Connected); + QTRY_VERIFY(session2.state() == QNetworkSession::Connected); + roamedSuccessfully = true; + } else if (state == QNetworkSession::Disconnected) { + QTRY_VERIFY(!errorSpy.isEmpty()); + QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected); + } else if (state == QNetworkSession::Connected) { + QTRY_VERIFY(errorSpy.isEmpty()); + if (stateChangedSpy.count() > 1) { + state = qvariant_cast(stateChangedSpy.at(stateChangedSpy.count() - 2).at(0)); + QVERIFY(state == QNetworkSession::Roaming); } - } + roamedSuccessfully = true; + } if (roamedSuccessfully) { QString configId = session.sessionProperty("ActiveConfiguration").toString(); @@ -1013,37 +1060,36 @@ void tst_QNetworkSession::sessionOpenCloseStop() QNetworkSession session3(config); QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError))); QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened())); - session3.open(); - session3.waitForOpened(); - + session3.waitForOpened(); if (session.isOpen()) QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty()); - session.stop(); - QTRY_VERIFY(session.state() == QNetworkSession::Disconnected); - QTRY_VERIFY(session3.state() == QNetworkSession::Disconnected); } #ifndef Q_CC_NOKIAX86 if (!roamedSuccessfully) QVERIFY(!errorSpy.isEmpty()); #endif } else { - QCOMPARE(stateChangedSpy2.count(), 2); - - QNetworkSession::State state = - qvariant_cast(stateChangedSpy2.at(0).at(0)); - QVERIFY(state == QNetworkSession::Closing); - - state = qvariant_cast(stateChangedSpy2.at(1).at(0)); - QVERIFY(state == QNetworkSession::Disconnected); + QTest::qWait(2000); // Wait awhile to get all signals from platform + + if (stateChangedSpy2.count() == 2) { + QNetworkSession::State state = + qvariant_cast(stateChangedSpy2.at(0).at(0)); + QVERIFY(state == QNetworkSession::Closing); + state = qvariant_cast(stateChangedSpy2.at(1).at(0)); + QVERIFY(state == QNetworkSession::Disconnected); + } else { // Assume .count() == 1 + QCOMPARE(stateChangedSpy2.count(), 1); + QNetworkSession::State state = qvariant_cast(stateChangedSpy2.at(0).at(0)); + // Symbian version dependant. + QVERIFY(state == QNetworkSession::Disconnected); + } } QTRY_VERIFY(!sessionClosedSpy.isEmpty()); - QTRY_VERIFY(session.state() == QNetworkSession::Disconnected); - QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected); } QVERIFY(errorSpy2.isEmpty()); @@ -1062,7 +1108,7 @@ void tst_QNetworkSession::sessionOpenCloseStop() QVERIFY(!session.isOpen()); #endif QVERIFY(!session2.isOpen()); - } else { + } else if (session2.isOpen()) { // Test closing the second session. { int stateChangedCountBeforeClose = stateChangedSpy2.count(); @@ -1161,11 +1207,15 @@ QDebug operator<<(QDebug debug, const QList &list) // at Discovered -state. void tst_QNetworkSession::outOfProcessSession() { - qDebug() << "START"; - + if (!testsToRun["outOfProcessSession"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } #if defined(Q_OS_SYMBIAN) && defined(__WINS__) QSKIP("Symbian emulator does not support two [QR]PRocesses linking a dll (QtBearer.dll) with global writeable static data.", SkipAll); #endif + updateConfigurations(); + QTest::qWait(2000); + QNetworkConfigurationManager manager; // Create a QNetworkConfigurationManager to detect configuration changes made in Lackey. This // is actually the essence of this testcase - to check that platform mediates/reflects changes @@ -1182,16 +1232,15 @@ void tst_QNetworkSession::outOfProcessSession() QLocalServer::removeServer("tst_qnetworksession"); oopServer.listen("tst_qnetworksession"); - qDebug() << "starting lackey"; QProcess lackey; lackey.start("lackey/lackey"); qDebug() << lackey.error() << lackey.errorString(); QVERIFY(lackey.waitForStarted()); - qDebug() << "waiting for connection"; + QVERIFY(oopServer.waitForNewConnection(-1)); QLocalSocket *oopSocket = oopServer.nextPendingConnection(); - qDebug() << "got connection"; + do { QByteArray output; @@ -1258,7 +1307,6 @@ void tst_QNetworkSession::outOfProcessSession() default: QSKIP("Lackey failed", SkipAll); } - qDebug("STOP"); } // A convinience / helper function for testcases. Return the first matching configuration. @@ -1269,6 +1317,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur // Refresh configurations and derive configurations matching given parameters. QNetworkConfigurationManager mgr; QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted())); + mgr.updateConfigurations(); QTRY_NOOP(updateSpy.count() == 1); if (updateSpy.count() != 1) { @@ -1277,8 +1326,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur } QList discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered); foreach(QNetworkConfiguration config, discoveredConfigs) { - if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - // qDebug() << "Dumping config because is active: " << config.name(); + if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { discoveredConfigs.removeOne(config); } else if (config.type() != configType) { // qDebug() << "Dumping config because type (IAP/SNAP) mismatches: " << config.name(); @@ -1315,9 +1363,23 @@ void updateConfigurations() QTRY_NOOP(updateSpy.count() == 1); } +// A convinience-function: updates and prints all available confiurations and their states +void printConfigurations() +{ + QNetworkConfigurationManager manager; + QList allConfigs = + manager.allConfigurations(); + qDebug("tst_QNetworkSession::printConfigurations QNetworkConfigurationManager gives following configurations: "); + foreach(QNetworkConfiguration config, allConfigs) { + qDebug() << "Name of the configuration: " << config.name(); + qDebug() << "State of the configuration: " << config.state(); + } +} + // A convinience function for test-cases: opens the given configuration and return // true if it was done gracefully. bool openSession(QNetworkSession *session) { + bool result = true; QNetworkConfigurationManager mgr; QSignalSpy openedSpy(session, SIGNAL(opened())); QSignalSpy stateChangeSpy(session, SIGNAL(stateChanged(QNetworkSession::State))); @@ -1327,43 +1389,57 @@ bool openSession(QNetworkSession *session) { // active by some other session QNetworkConfiguration::StateFlags configInitState = session->configuration().state(); QNetworkSession::State sessionInitState = session->state(); + qDebug() << "tst_QNetworkSession::openSession() name of the configuration to be opened: " << session->configuration().name(); + qDebug() << "tst_QNetworkSession::openSession() state of the configuration to be opened: " << session->configuration().state(); + qDebug() << "tst_QNetworkSession::openSession() state of the session to be opened: " << session->state(); if (session->isOpen() || !session->sessionProperty("ActiveConfiguration").toString().isEmpty()) { qDebug("tst_QNetworkSession::openSession() failure: session was already open / active."); - return false; + result = false; } else { session->open(); session->waitForOpened(120000); // Bringing interfaces up and down may take time at platform } + QTest::qWait(5000); // Wait a moment to ensure all signals are propagated // Check that connection opening went by the book. Add checks here if more strictness needed. if (!session->isOpen()) { qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::open() failed."); - return false; + result = false; } if (openedSpy.count() != 1) { qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::opened() - signal not received."); - return false; + result = false; } if (!errorSpy.isEmpty()) { qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::error() - signal was detected."); - return false; + result = false; } if (sessionInitState != QNetworkSession::Connected && stateChangeSpy.isEmpty()) { qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::stateChanged() - signals not detected."); - return false; + result = false; } if (configInitState != QNetworkConfiguration::Active && configChangeSpy.isEmpty()) { qDebug("tst_QNetworkSession::openSession() failure: QNetworkConfigurationManager::configurationChanged() - signals not detected."); - return false; + result = false; } if (session->configuration().state() != QNetworkConfiguration::Active) { qDebug("tst_QNetworkSession::openSession() failure: session's configuration is not in 'Active' -state."); - return false; + qDebug() << "tst_QNetworkSession::openSession() state is: " << session->configuration().state(); + result = false; + } + if (result == false) { + qDebug() << "tst_QNetworkSession::openSession() opening session failed."; + } else { + qDebug() << "tst_QNetworkSession::openSession() opening session succeeded."; } - return true; + qDebug() << "tst_QNetworkSession::openSession() name of the configuration is: " << session->configuration().name(); + qDebug() << "tst_QNetworkSession::openSession() configuration state is: " << session->configuration().state(); + qDebug() << "tst_QNetworkSession::openSession() session state is: " << session->state(); + + return result; } // Helper function for closing opened session. Performs checks that @@ -1376,6 +1452,11 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) { qDebug("tst_QNetworkSession::closeSession() failure: NULL session given"); return false; } + + qDebug() << "tst_QNetworkSession::closeSession() name of the configuration to be closed: " << session->configuration().name(); + qDebug() << "tst_QNetworkSession::closeSession() state of the configuration to be closed: " << session->configuration().state(); + qDebug() << "tst_QNetworkSession::closeSession() state of the session to be closed: " << session->state(); + if (session->state() != QNetworkSession::Connected || !session->isOpen()) { qDebug("tst_QNetworkSession::closeSession() failure: session is not opened."); @@ -1387,38 +1468,48 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) { QSignalSpy sessionErrorSpy(session, SIGNAL(error(QNetworkSession::SessionError))); QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration))); + bool result = true; session->close(); + QTest::qWait(5000); // Wait a moment so that all signals are propagated if (!sessionErrorSpy.isEmpty()) { qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::error() received."); - return false; + result = false; } if (sessionClosedSpy.count() != 1) { qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::closed() signal not received."); - return false; + result = false; } if (lastSessionOnConfiguration && sessionStateChangedSpy.isEmpty()) { qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::stateChanged() signals not received."); - return false; + result = false; } if (lastSessionOnConfiguration && session->state() != QNetworkSession::Disconnected) { qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession is not in Disconnected -state"); - return false; + result = false; } QTRY_NOOP(!configChangeSpy.isEmpty()); if (lastSessionOnConfiguration && configChangeSpy.isEmpty()) { qDebug("tst_QNetworkSession::closeSession() failure: QNetworkConfigurationManager::configurationChanged() - signal not detected."); - return false; + result = false; } if (lastSessionOnConfiguration && session->configuration().state() == QNetworkConfiguration::Active) { qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is still in active state."); - return false; + result = false; } - return true; + if (result == false) { + qDebug() << "tst_QNetworkSession::closeSession() closing session failed."; + } else { + qDebug() << "tst_QNetworkSession::closeSession() closing session succeeded."; + } + qDebug() << "tst_QNetworkSession::closeSession() name of the configuration is: " << session->configuration().name(); + qDebug() << "tst_QNetworkSession::closeSession() configuration state is: " << session->configuration().state(); + qDebug() << "tst_QNetworkSession::closeSession() session state is: " << session->state(); + return result; } void tst_QNetworkSession::sessionAutoClose_data() -- cgit v0.12 From e6efa3ea81dff9eb0ade1c2ba868c272ccfcc958 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 13 May 2010 10:49:52 +1000 Subject: Bearer management changes from Qt Mobility. 9286bfcc43d38e0cb3bfd1d3f99ac7ab5d88b7e3 --- examples/network/bearermonitor/bearermonitor.cpp | 3 +++ examples/network/bearermonitor/sessionwidget.cpp | 12 ++++++++++-- examples/network/bearermonitor/sessionwidget.h | 5 ++++- examples/network/bearermonitor/sessionwidget.ui | 2 +- .../auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp | 7 +++++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/examples/network/bearermonitor/bearermonitor.cpp b/examples/network/bearermonitor/bearermonitor.cpp index 4a6c6ff..0d98eff 100644 --- a/examples/network/bearermonitor/bearermonitor.cpp +++ b/examples/network/bearermonitor/bearermonitor.cpp @@ -255,6 +255,7 @@ void BearerMonitor::onlineStateChanged(bool isOnline) void BearerMonitor::registerNetwork() { QTreeWidgetItem *item = treeWidget->currentItem(); + if (!item) return; QNetworkConfiguration configuration = manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString()); @@ -276,6 +277,7 @@ void BearerMonitor::registerNetwork() void BearerMonitor::unregisterNetwork() { QTreeWidgetItem *item = treeWidget->currentItem(); + if (!item) return; QNetworkConfiguration configuration = manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString()); @@ -384,6 +386,7 @@ void BearerMonitor::createSessionFor(QTreeWidgetItem *item) void BearerMonitor::createNewSession() { QTreeWidgetItem *item = treeWidget->currentItem(); + if (!item) return; createSessionFor(item); } diff --git a/examples/network/bearermonitor/sessionwidget.cpp b/examples/network/bearermonitor/sessionwidget.cpp index 443f4b2..3a8e5ea 100644 --- a/examples/network/bearermonitor/sessionwidget.cpp +++ b/examples/network/bearermonitor/sessionwidget.cpp @@ -59,7 +59,7 @@ SessionWidget::SessionWidget(const QNetworkConfiguration &config, QWidget *paren connect(session, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateSession())); connect(session, SIGNAL(error(QNetworkSession::SessionError)), - this, SLOT(updateSession())); + this, SLOT(updateSessionError(QNetworkSession::SessionError))); updateSession(); @@ -105,7 +105,6 @@ void SessionWidget::deleteSession() void SessionWidget::updateSession() { updateSessionState(session->state()); - updateSessionError(session->error()); if (session->state() == QNetworkSession::Connected) statsTimer = startTimer(1000); @@ -128,12 +127,14 @@ void SessionWidget::updateSession() void SessionWidget::openSession() { + clearError(); session->open(); updateSession(); } void SessionWidget::openSyncSession() { + clearError(); session->open(); session->waitForOpened(); updateSession(); @@ -141,12 +142,14 @@ void SessionWidget::openSyncSession() void SessionWidget::closeSession() { + clearError(); session->close(); updateSession(); } void SessionWidget::stopSession() { + clearError(); session->stop(); updateSession(); } @@ -195,3 +198,8 @@ void SessionWidget::updateSessionError(QNetworkSession::SessionError error) errorString->setText(session->errorString()); } +void SessionWidget::clearError() +{ + lastError->clear(); + errorString->clear(); +} diff --git a/examples/network/bearermonitor/sessionwidget.h b/examples/network/bearermonitor/sessionwidget.h index 5e9d62c..b299b47 100644 --- a/examples/network/bearermonitor/sessionwidget.h +++ b/examples/network/bearermonitor/sessionwidget.h @@ -63,7 +63,7 @@ public: private: void updateSessionState(QNetworkSession::State state); - void updateSessionError(QNetworkSession::SessionError error); + void clearError(); private Q_SLOTS: void openSession(); @@ -71,9 +71,12 @@ private Q_SLOTS: void closeSession(); void stopSession(); void updateSession(); + void updateSessionError(QNetworkSession::SessionError error); #if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) void deleteSession(); #endif + + private: QNetworkSession *session; int statsTimer; diff --git a/examples/network/bearermonitor/sessionwidget.ui b/examples/network/bearermonitor/sessionwidget.ui index 45135f5..56a2d0e 100644 --- a/examples/network/bearermonitor/sessionwidget.ui +++ b/examples/network/bearermonitor/sessionwidget.ui @@ -195,7 +195,7 @@ - Error String + Error String: diff --git a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp index ce3acb7..a3cccb2 100644 --- a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp +++ b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp @@ -45,6 +45,13 @@ #include #include +/* + Although this unit test doesn't use QNetworkAccessManager + this include is used to ensure that bearer continues to compile against + Qt 4.7+ which has a QNetworkConfiguration enabled QNetworkAccessManager +*/ +#include + #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5) #include #include -- cgit v0.12 From e75161c4d54406d137f34b9f54fed853c16a6269 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 13 May 2010 10:51:13 +1000 Subject: Cherry pick fix for MOBILITY-828 from Qt Mobility. Change 29776be110cdc121eb5a22446be6adae8ff6f4d8 from Qt Mobility. --- .../bearer/symbian/qnetworksession_impl.cpp | 4 +-- .../qnetworksession/test/tst_qnetworksession.cpp | 30 +++++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 04853c4..f09c73a 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) - : CActive(CActive::EPriorityStandard), engine(engine), + : CActive(CActive::EPriorityUserInput), engine(engine), ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iDeprecatedConnectionId(0), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false) @@ -1383,7 +1383,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne } ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection) - : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection) + : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) { CActiveScheduler::Add(this); } diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 8ab9da2..934a50e 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -263,10 +263,6 @@ void tst_QNetworkSession::robustnessBombing() testSession.accept(); testSession.ignore(); testSession.reject(); - quint64 temp; - temp = testSession.bytesWritten(); - temp = testSession.bytesReceived(); - temp = testSession.activeTime(); } @@ -704,7 +700,20 @@ void tst_QNetworkSession::userChoiceSession() session.open(); +#if defined(Q_OS_SYMBIAN) + // Opening & closing multiple connections in a row sometimes + // results hanging of connection opening on Symbian devices + // => If first open fails, wait a moment and try again. + if (!session.waitForOpened()) { + qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****"); + session.close(); + QTest::qWait(5000); // Wait a while before trying to open session again + session.open(); + session.waitForOpened(); + } +#else session.waitForOpened(); +#endif if (session.isOpen()) QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty()); @@ -843,7 +852,20 @@ void tst_QNetworkSession::sessionOpenCloseStop() session.open(); +#if defined(Q_OS_SYMBIAN) + // Opening & closing multiple connections in a row sometimes + // results hanging of connection opening on Symbian devices + // => If first open fails, wait a moment and try again. + if (!session.waitForOpened()) { + qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****"); + session.close(); + QTest::qWait(5000); // Wait a while before trying to open session again + session.open(); + session.waitForOpened(); + } +#else session.waitForOpened(); +#endif if (session.isOpen()) QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty()); -- cgit v0.12 From 608d39c9ffee622114d9bc178d5e8ad3d1eadfb5 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 13 May 2010 10:54:01 +1000 Subject: Cherry pick fix for MOBILITY-962 from Qt Mobility. 6ea1caf2babc68d366fb6d3dc215c1bb18a76368 --- tests/manual/bearerex/bearerex.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/manual/bearerex/bearerex.cpp b/tests/manual/bearerex/bearerex.cpp index 19246a2..bf60dd1 100644 --- a/tests/manual/bearerex/bearerex.cpp +++ b/tests/manual/bearerex/bearerex.cpp @@ -300,8 +300,12 @@ SessionTab::SessionTab(QNetworkConfiguration* apNetworkConfiguration, SessionTab::~SessionTab() { + // Need to be nulled, because modal dialogs may return after destruction of this object and + // use already released resources. delete m_NetworkSession; + m_NetworkSession = NULL; delete m_http; + m_http = NULL; } void SessionTab::on_createQHttpButton_clicked() @@ -551,10 +555,16 @@ void SessionTab::done(bool error) msgBox.setText(QString("HTTP request finished successfully.\nReceived ")+QString::number(result.length())+QString(" bytes.")); } msgBox.exec(); - - sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+ - QString(" / ")+ - QString::number(m_NetworkSession->bytesReceived())); + // Check if the networksession still exists - it may have gone after returning from + // the modal dialog (in the case that app has been closed, and deleting QHttp will + // trigger the done() invokation). + if (m_NetworkSession) { + sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+ + QString(" / ")+ + QString::number(m_NetworkSession->bytesReceived())); + } else { + sentRecDataLineEdit->setText("Data amounts not available."); + } } // End of file -- cgit v0.12 From 75c4dea93ad415dd9c79cb57ec5598e38789b28d Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 13 May 2010 10:55:06 +1000 Subject: Cherry pick fix for MOBILITY-932 from Qt Mobility. 807e9868152bb06d37895a5e3d1a3e49908a6036 --- .../bearer/symbian/qnetworksession_impl.cpp | 32 ++++++++++------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index f09c73a..ce2203d 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -523,13 +523,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) // when reporting. iClosedByUser = true; - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(activeConfig)); - - symbianConfig->mutex.lock(); - TUint activeIap = symbianConfig->numericId; - symbianConfig->mutex.unlock(); - isOpen = false; activeConfig = QNetworkConfiguration(); serviceConfig = QNetworkConfiguration(); @@ -554,19 +547,12 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) // Close global 'Open C' RConnection setdefaultif(0); -#ifdef Q_CC_NOKIAX86 - if ((allowSignals && iapClientCount(activeIap) <= 0) || -#else - if ((allowSignals && iapClientCount(activeIap) <= 1) || -#endif - (publicConfig.type() == QNetworkConfiguration::UserChoice)) { + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { newState(QNetworkSession::Closing); + newState(QNetworkSession::Disconnected); } if (allowSignals) { - if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - newState(QNetworkSession::Disconnected); - } emit closed(); } } @@ -599,7 +585,7 @@ void QNetworkSessionPrivateImpl::stop() } TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f TUint connectionId; - for (TInt i = 1; i <= count; ++i) { + for (TUint i = 1; i <= count; ++i) { // Get (connection monitor's assigned) connection ID TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections); if (ret == KErrNone) { @@ -1236,7 +1222,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint QMutexLocker configLocker(&symbianConfig->mutex); if (symbianConfig->numericId == accessPointId) { - if (newState == QNetworkSession::Connected) { + if (newState != QNetworkSession::Disconnected) { state = newState; #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D to: " << state; @@ -1256,6 +1242,16 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint #endif emit stateChanged(state); retVal = true; + } else if (config.state() == QNetworkConfiguration::Active) { + // Connection to used IAP was closed, but there is another + // IAP that's active in used SNAP + // => Change state back to Connected + state = QNetworkSession::Connected; + emit stateChanged(state); + retVal = true; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed F to: " << state; +#endif } } } -- cgit v0.12 From ef0a942bc57485ddaad413cd27c0283a1c90149f Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 14 May 2010 10:38:52 +0200 Subject: Updated changelog. --- dist/changes-4.7.0 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0 index 6bf7ea5..919c25a 100644 --- a/dist/changes-4.7.0 +++ b/dist/changes-4.7.0 @@ -76,6 +76,18 @@ QtGui * Fixed rendering bugs when scrolling graphics items with drop shadows. + - QGraphicsItem + * [QTBUG-8112] itemChange() is now called when transformation + properties change (setRotation, setScale, setTransformOriginPoint). + + - QGraphicsTextItem + * [QTBUG-7333] Fixed keyboard shortcuts not being triggered when the + the item has focus and something else has the same shortcut sequence. + + - QGraphicsView + * [QTBUG-7438] Fixed viewport cursor getting reset when releasing + the mouse. + - QImage * [QTBUG-9640] Prevented unneccessary copy in QImage::setAlphaChannel(). -- cgit v0.12 From aeff7ca3bdc7d4c2518f6f27f69332935ff8b104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 14 May 2010 10:42:31 +0200 Subject: Some 4.7 changes. --- dist/changes-4.7.0 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0 index 919c25a..47992f9 100644 --- a/dist/changes-4.7.0 +++ b/dist/changes-4.7.0 @@ -33,7 +33,6 @@ New features - QNetworkSession, QNetworkConfiguration, QNetworkConfigurationManager * New bearer management classes added. - Third party components ---------------------- @@ -89,11 +88,17 @@ QtGui the mouse. - QImage - * [QTBUG-9640] Prevented unneccessary copy in - QImage::setAlphaChannel(). - * Added QImage::bitPlaneCount(). (QTBUG-7982) + * [QTBUG-9640] Prevented unneccessary copy in QImage::setAlphaChannel(). + * [QTBUG-7982] Added QImage::bitPlaneCount(). + + - QPicture + * [QTBUG-4974] Printing QPictures containing text to a high resolution + QPrinter would in many cases cause incorrect character spacing. - QPainter + * Added QPainter::drawPixmapFragments(), which makes it possible to draw + pixmaps, or sub-rectangles of pixmaps, at various positions with + different scale, opacity and rotation. * [QTBUG-10018] Fixed image drawing inconsistencies when drawing 1x1 source rects with rotating / shear / perspective transforms. * Optimized various blending and rendering operations for ARM -- cgit v0.12 From 37c817ac5d19fe70e1457dddc8ba62ad6702cfdb Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 14 May 2010 11:32:01 +0200 Subject: doc: Added some \briefs to how-to docs. --- doc/src/frameworks-technologies/dbus-adaptors.qdoc | 1 + doc/src/howtos/HWacceleration.qdoc | 15 +++++++++------ doc/src/howtos/accelerators.qdoc | 1 + doc/src/howtos/appicon.qdoc | 1 + doc/src/howtos/guibooks.qdoc | 1 + doc/src/howtos/qtdesigner.qdoc | 1 + doc/src/howtos/restoring-geometry.qdoc | 2 +- doc/src/howtos/session.qdoc | 2 +- doc/src/howtos/sharedlibrary.qdoc | 2 +- doc/src/howtos/timers.qdoc | 2 +- doc/src/sql-programming/qsqldatatype-table.qdoc | 19 ++++++++++--------- 11 files changed, 28 insertions(+), 19 deletions(-) diff --git a/doc/src/frameworks-technologies/dbus-adaptors.qdoc b/doc/src/frameworks-technologies/dbus-adaptors.qdoc index 11c5998..25c6a43 100644 --- a/doc/src/frameworks-technologies/dbus-adaptors.qdoc +++ b/doc/src/frameworks-technologies/dbus-adaptors.qdoc @@ -43,6 +43,7 @@ \page usingadaptors.html \title Using QtDBus Adaptors \ingroup technology-apis + \brief How to create and use DBus adaptors in Qt. \ingroup best-practices diff --git a/doc/src/howtos/HWacceleration.qdoc b/doc/src/howtos/HWacceleration.qdoc index fbc657c..c7b1a72 100644 --- a/doc/src/howtos/HWacceleration.qdoc +++ b/doc/src/howtos/HWacceleration.qdoc @@ -41,17 +41,20 @@ /*! \page HWAcc_rendering.html - \title Using hardware acceleration on embedded platforms. + \title Hardware Acceleration & Embedded Platforms. + \brief How to use hardware acceleration for fast rendering. \ingroup best-practices \section1 Abstract + This document describes how to use hardware acceleration for fast - rendering on embedded platforms supported by Qt. In short, it explains - how the graphics pipeline works. Since there might be differences to - how the APIs are being used on different embedded platforms, a table - links to documentation dedicated to platform specific documentation - for each supported hardware acceleration API. + rendering on embedded platforms supported by Qt. In short, it + explains how the graphics pipeline works. Since there might be + differences to how the APIs are being used on different embedded + platforms, a table links to documentation dedicated to platform + specific documentation for each supported hardware acceleration + API. \input platforms/emb-hardwareacceleration.qdocinc diff --git a/doc/src/howtos/accelerators.qdoc b/doc/src/howtos/accelerators.qdoc index 65f1def..b6ef5c2 100644 --- a/doc/src/howtos/accelerators.qdoc +++ b/doc/src/howtos/accelerators.qdoc @@ -42,6 +42,7 @@ /*! \page accelerators.html \title Standard Accelerator Keys + \brief Recommended accelerator keys. \ingroup best-practices diff --git a/doc/src/howtos/appicon.qdoc b/doc/src/howtos/appicon.qdoc index dd39509..9377961 100644 --- a/doc/src/howtos/appicon.qdoc +++ b/doc/src/howtos/appicon.qdoc @@ -42,6 +42,7 @@ /*! \page appicon.html \title Setting the Application Icon + \brief How to set your application's icon. \ingroup best-practices diff --git a/doc/src/howtos/guibooks.qdoc b/doc/src/howtos/guibooks.qdoc index 1a70670..bccfbe6 100644 --- a/doc/src/howtos/guibooks.qdoc +++ b/doc/src/howtos/guibooks.qdoc @@ -43,6 +43,7 @@ \page guibooks.html \title Books about GUI Design \ingroup best-practices + \brief Some recommended books about GUI design. This is not a comprehensive list -- there are many other books worth buying. Here we mention just a few user interface books that don't diff --git a/doc/src/howtos/qtdesigner.qdoc b/doc/src/howtos/qtdesigner.qdoc index 2dd7fcf..92041f0 100644 --- a/doc/src/howtos/qtdesigner.qdoc +++ b/doc/src/howtos/qtdesigner.qdoc @@ -42,6 +42,7 @@ /*! \page qtdesigner-components.html \title Creating and Using Components for Qt Designer + \brief How to create and use custom widget plugins. \ingroup best-practices \tableofcontents diff --git a/doc/src/howtos/restoring-geometry.qdoc b/doc/src/howtos/restoring-geometry.qdoc index 36c5e4f..e72b993 100644 --- a/doc/src/howtos/restoring-geometry.qdoc +++ b/doc/src/howtos/restoring-geometry.qdoc @@ -42,7 +42,7 @@ /*! \page restoring-geometry.html \title Restoring a Window's Geometry - + \brief How to save & restore window geometry. \ingroup best-practices This document describes how to save and restore a \l{Window diff --git a/doc/src/howtos/session.qdoc b/doc/src/howtos/session.qdoc index e2e87a8..f53af04 100644 --- a/doc/src/howtos/session.qdoc +++ b/doc/src/howtos/session.qdoc @@ -42,7 +42,7 @@ /*! \page session.html \title Session Management - + \brief How to do session management with Qt. \ingroup best-practices A \e session is a group of running applications, each of which has a diff --git a/doc/src/howtos/sharedlibrary.qdoc b/doc/src/howtos/sharedlibrary.qdoc index 70fc4db..ed803ed 100644 --- a/doc/src/howtos/sharedlibrary.qdoc +++ b/doc/src/howtos/sharedlibrary.qdoc @@ -42,7 +42,7 @@ /*! \page sharedlibrary.html \title Creating Shared Libraries - + \brief How to create shared libraries. \ingroup best-practices The following sections list certain things that should be taken into diff --git a/doc/src/howtos/timers.qdoc b/doc/src/howtos/timers.qdoc index cfc2fb4..b001916 100644 --- a/doc/src/howtos/timers.qdoc +++ b/doc/src/howtos/timers.qdoc @@ -42,7 +42,7 @@ /*! \page timers.html \title Timers - \brief How to use timers in your application. + \brief How to use Qt timers in your application. \ingroup best-practices diff --git a/doc/src/sql-programming/qsqldatatype-table.qdoc b/doc/src/sql-programming/qsqldatatype-table.qdoc index fc961f5..398e659 100644 --- a/doc/src/sql-programming/qsqldatatype-table.qdoc +++ b/doc/src/sql-programming/qsqldatatype-table.qdoc @@ -41,19 +41,20 @@ /*! \page sql-types.html - \title Recommended Use of Data Types in Databases + \title Data Types for Qt-supported Database Systems + \brief Recommended data types for database systems \ingroup best-practices - \section1 Recommended Use of Types in Qt Supported Databases + \section1 Data Types for Qt Supported Database Systems - This table shows the recommended data types used when extracting data - from the databases supported in Qt. It is important to note that the - types used in Qt are not necessarily valid as input to the specific - database. One example could be that a double would work perfectly as - input for floating point records in a database, but not necessarily - as a storage format for output from the database since it would be stored - with 64-bit precision in C++. + This table shows the recommended data types for extracting data from + the databases supported in Qt. Note that types used in Qt are not + necessarily valid as input types to a specific database + system. e.g., A double might work perfectly as input for floating + point records in a particular database, but not necessarily as a + storage format for output from that database, because it would be + stored with 64-bit precision in C++. \tableofcontents -- cgit v0.12 From 23f1fa2e47f3bd4cea92510d70c2e9d0fbbcfc92 Mon Sep 17 00:00:00 2001 From: Carlos Manuel Duclos Vergara Date: Fri, 14 May 2010 10:36:27 +0200 Subject: [Regression] Build failure on Mac Carbon Including objc/runtime.h when using Carbon produced problems so I protected that include via ifdef. Task-number: QTBUG-10519 Reviewed-by: Jason Mcdonald --- src/gui/kernel/qt_mac_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index 3341ce1..ca9541a 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -57,7 +57,9 @@ #ifdef __OBJC__ #include +#ifdef QT_MAC_USE_COCOA #include +#endif // QT_MAC_USE_COCOA #endif #include -- cgit v0.12 From e0c4899b46a68b37ce743c5a1ffd17596cbaa44c Mon Sep 17 00:00:00 2001 From: Carlos Manuel Duclos Vergara Date: Fri, 14 May 2010 11:41:05 +0200 Subject: Mac: restoreGeometry() The problem here is the fact that when zooming (maximizing) a window, we should update the starting position since the window is now starting at 0,0. However when restoring the window should be placed in the original position. The bug here occurs because we kept the original position and the new size. So the window was drawn were it was using the new size. This patch introduces a boolean flag that keeps track of the maximized state. We are interested in knowing if the window was maximized but not restored, so when saving the geometry we have a way to know that we need to "move" the window to 0,0. Task-number: QTBUG-10504 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qcocoawindowdelegate_mac.mm | 21 ++++++++++++++++++--- src/gui/kernel/qwidget.cpp | 22 ++++++++++++++++++++++ src/gui/kernel/qwidget_p.h | 8 ++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 24498f8..2b9cf85 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -202,6 +202,11 @@ static void cleanupCocoaWindowDelegate() QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state & ~Qt::WindowMaximized)); qt_sendSpontaneousEvent(qwidget, &e); + } else { + widgetData->window_state = widgetData->window_state & ~Qt::WindowMaximized; + QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state + | Qt::WindowMaximized)); + qt_sendSpontaneousEvent(qwidget, &e); } NSRect rect = [[window contentView] frame]; const QSize newSize(rect.size.width, rect.size.height); @@ -305,9 +310,19 @@ static void cleanupCocoaWindowDelegate() Q_UNUSED(newFrame); // saving the current window geometry before the window is maximized QWidget *qwidget = m_windowHash->value(window); - if (qwidget->isWindow() && !(qwidget->windowState() & Qt::WindowMaximized)) { - QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); - widgetPrivate->topData()->normalGeometry = qwidget->geometry(); + QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); + if (qwidget->isWindow()) { + if(qwidget->windowState() & Qt::WindowMaximized) { + // Restoring + widgetPrivate->topData()->wasMaximized = false; + } else { + // Maximizing + widgetPrivate->topData()->normalGeometry = qwidget->geometry(); + // If the window was maximized we need to update the coordinates since now it will start at 0,0. + // We do this in a special field that is only used when not restoring but manually resizing the window. + // Since the coordinates are fixed we just set a boolean flag. + widgetPrivate->topData()->wasMaximized = true; + } } return YES; } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e39526e..420eda6 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1581,6 +1581,11 @@ void QWidgetPrivate::createTLExtra() x->inTopLevelResize = false; x->inRepaint = false; x->embedded = 0; +#ifdef Q_WS_MAC +#ifdef QT_MAC_USE_COCOA + x->wasMaximized = false; +#endif // QT_MAC_USE_COCOA +#endif // Q_WS_MAC createTLSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; @@ -6749,6 +6754,18 @@ void QWidget::setGeometry(const QRect &r) */ QByteArray QWidget::saveGeometry() const { +#ifdef QT_MAC_USE_COCOA + // We check if the window was maximized during this invocation. If so, we need to record the + // starting position as 0,0. + Q_D(const QWidget); + QRect newFramePosition = frameGeometry(); + QRect newNormalPosition = normalGeometry(); + if(d->topData()->wasMaximized) { + // Change the starting position + newFramePosition.moveTo(0, 0); + newNormalPosition.moveTo(0, 0); + } +#endif // QT_MAC_USE_COCOA QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_4_0); @@ -6758,8 +6775,13 @@ QByteArray QWidget::saveGeometry() const stream << magicNumber << majorVersion << minorVersion +#ifdef QT_MAC_USE_COCOA + << newFramePosition + << newNormalPosition +#else << frameGeometry() << normalGeometry() +#endif // QT_MAC_USE_COCOA << qint32(QApplication::desktop()->screenNumber(this)) << quint8(windowState() & Qt::WindowMaximized) << quint8(windowState() & Qt::WindowFullScreen); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index cad60b5..3f494d8 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -170,6 +170,14 @@ struct QTLWExtra { WindowGroupRef group; IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() +#ifdef QT_MAC_USE_COCOA + // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and + // manually resized. + // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the + // starting position as 0,0 instead of the normal starting position. + bool wasMaximized; +#endif // QT_MAC_USE_COCOA + #elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS #ifndef QT_NO_QWS_MANAGER QWSManager *qwsManager; -- cgit v0.12