diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-10-27 13:00:36 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-10-27 13:00:36 +0100 |
commit | 2eb26c170920d28213b71e549d5dac4663febb14 (patch) | |
tree | 8df5223ac114d758c2112a8fc787992175556418 /src/plugins | |
parent | 49ddae28e0dcd1c59dd5d742cffedd5290d1224a (diff) | |
parent | 81998b4e8e440076bd22a9164f0a93481c0e597a (diff) |
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts:
src/gui/text/qfontdatabase.cpp
Change-Id: I6ac1f55faa22b8e7b591386fb67f0333d0ea443d
Diffstat (limited to 'src/plugins')
31 files changed, 883 insertions, 1325 deletions
diff --git a/src/plugins/bearer/android/src/qandroidbearerengine.cpp b/src/plugins/bearer/android/src/qandroidbearerengine.cpp index 2d047ba612..64c1a20ecc 100644 --- a/src/plugins/bearer/android/src/qandroidbearerengine.cpp +++ b/src/plugins/bearer/android/src/qandroidbearerengine.cpp @@ -166,10 +166,7 @@ QNetworkSession::State QAndroidBearerEngine::sessionStateForId(const QString &id const QMutexLocker configLocker(&ptr->mutex); // Don't re-order... if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - return (m_connectivityManager->isActiveNetworkMetered() - || m_connectivityManager->getActiveNetworkInfo().isRoaming()) - ? QNetworkSession::Roaming - : QNetworkSession::Connected; + return QNetworkSession::Connected; } else if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) { return QNetworkSession::Disconnected; } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { @@ -267,6 +264,10 @@ void QAndroidBearerEngine::updateConfigurations() QMutexLocker locker(&mutex); QStringList oldKeys = accessPointConfigurations.keys(); + QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); + if (interfaces.isEmpty()) + interfaces = QNetworkInterface::allInterfaces(); + // Create a configuration for each of the main types (WiFi, Mobile, Bluetooth, WiMax, Ethernet) foreach (const AndroidNetworkInfo &netInfo, m_connectivityManager->getAllNetworkInfo()) { @@ -279,14 +280,13 @@ void QAndroidBearerEngine::updateConfigurations() QNetworkConfiguration::BearerType bearerType = getBearerType(netInfo); - QNetworkConfiguration::StateFlag state; QString interfaceName; + QNetworkConfiguration::StateFlag state = QNetworkConfiguration::Defined; if (netInfo.isAvailable()) { if (netInfo.isConnected()) { - state = QNetworkConfiguration::Active; // Attempt to map an interface to this configuration - const QList<QNetworkInterface> &interfaces = QNetworkInterface::allInterfaces(); - foreach (const QNetworkInterface &interface, interfaces) { + while (!interfaces.isEmpty()) { + QNetworkInterface interface = interfaces.takeFirst(); // ignore loopback interface if (!interface.isValid()) continue; @@ -297,22 +297,17 @@ void QAndroidBearerEngine::updateConfigurations() // look for an active interface... if (interface.flags() & QNetworkInterface::IsRunning && !interface.addressEntries().isEmpty()) { - interfaceName = interface.humanReadableName(); - if (interfaceName.isEmpty()) - interfaceName = interface.name(); + state = QNetworkConfiguration::Active; + interfaceName = interface.name(); + break; } } - } else if (netInfo.isConnectedOrConnecting()) { - state = QNetworkConfiguration::Undefined; - } else { - state = QNetworkConfiguration::Discovered; } - } else { - state = QNetworkConfiguration::Defined; } - const uint identifier = qHash(QLatin1String("android:") + name); - const QString id = QString::number(identifier); + const QString key = QString(QLatin1String("android:%1:%2")).arg(name).arg(interfaceName); + const QString id = QString::number(qHash(key)); + m_configurationInterface[id] = interfaceName; oldKeys.removeAll(id); if (accessPointConfigurations.contains(id)) { @@ -347,12 +342,6 @@ void QAndroidBearerEngine::updateConfigurations() ptr->state = state; changed = true; } - - QString &oldIfName = m_configurationInterface[id]; - if (oldIfName != interfaceName) { - oldIfName = interfaceName; - changed = true; - } } // Unlock configuration if (changed) { @@ -369,8 +358,6 @@ void QAndroidBearerEngine::updateConfigurations() ptr->type = QNetworkConfiguration::InternetAccessPoint; ptr->bearerType = bearerType; accessPointConfigurations.insert(id, ptr); - m_configurationInterface.insert(id, interfaceName); - locker.unlock(); Q_EMIT configurationAdded(ptr); locker.relock(); diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h index 930bde40b3..50bdab0ea6 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.h +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -83,6 +83,7 @@ public: private Q_SLOTS: void doRequestUpdate(); void networksChanged(); + void checkDisconnect(); private: bool isWifiReady(const QString &dev); @@ -95,6 +96,7 @@ private: QScanThread *scanThread; quint64 getBytes(const QString &interfaceName,bool b); + QString disconnectedInterfaceString; protected: void startNetworkChangeLoop(); diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 65e70876f2..6f9ea91799 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -62,8 +62,6 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time #include <net/if.h> #include <ifaddrs.h> -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_NA) - @interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject { NSNotificationCenter *notificationCenter; @@ -544,20 +542,44 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) QMutexLocker locker(&mutex); QString interfaceString = getInterfaceFromId(id); + if (interfaceString.isEmpty()) { + locker.unlock(); + emit connectionError(id, DisconnectionError); + return; + } NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; CWInterface *wifiInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; + disconnectedInterfaceString = interfaceString; [wifiInterface disassociate]; - if (wifiInterface.serviceActive) { - locker.unlock(); - emit connectionError(id, DisconnectionError); - locker.relock(); - } + + QTimer::singleShot(1000, this,SLOT(checkDisconnect())); [autoreleasepool release]; } +void QCoreWlanEngine::checkDisconnect() +{ + QMutexLocker locker(&mutex); + if (!disconnectedInterfaceString.isEmpty()) { + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CWInterface *wifiInterface = + [CWInterface interfaceWithName: QCFString::toNSString(disconnectedInterfaceString)]; + + const QString networkSsid = QCFString::toQString([wifiInterface ssid]); + if (!networkSsid.isEmpty()) { + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); + locker.unlock(); + emit connectionError(id, DisconnectionError); + locker.relock(); + } + [autoreleasepool release]; + disconnectedInterfaceString.clear(); + } +} + void QCoreWlanEngine::requestUpdate() { scanThread->getUserConfigurations(); @@ -862,7 +884,3 @@ quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b) } QT_END_NAMESPACE - -#else // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE -#include "qcorewlanengine_10_6.mm" -#endif diff --git a/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm b/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm deleted file mode 100644 index 6cf614cb30..0000000000 --- a/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm +++ /dev/null @@ -1,922 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <SystemConfiguration/SCNetworkConfiguration.h> - -@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject -{ - NSNotificationCenter *notificationCenter; - CWInterface *currentInterface; - QCoreWlanEngine *engine; - NSLock *locker; -} -- (void)notificationHandler:(NSNotification *)notification; -- (void)remove; -- (void)setEngine:(QCoreWlanEngine *)coreEngine; -- (QCoreWlanEngine *)engine; -- (void)dealloc; - -@property (assign) QCoreWlanEngine* engine; - -@end - -@implementation QT_MANGLE_NAMESPACE(QNSListener) - -- (id) init -{ - [locker lock]; - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - notificationCenter = [NSNotificationCenter defaultCenter]; - currentInterface = [CWInterface interfaceWithName:nil]; - [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil]; - [locker unlock]; - [autoreleasepool release]; - return self; -} - --(void)dealloc -{ - [super dealloc]; -} - --(void)setEngine:(QCoreWlanEngine *)coreEngine -{ - [locker lock]; - if(!engine) - engine = coreEngine; - [locker unlock]; -} - --(QCoreWlanEngine *)engine -{ - return engine; -} - --(void)remove -{ - [locker lock]; - [notificationCenter removeObserver:self]; - [locker unlock]; -} - -- (void)notificationHandler:(NSNotification *)notification -{ - Q_UNUSED(notification); - engine->requestUpdate(); -} -@end - -static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0; - -QT_BEGIN_NAMESPACE - -void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) -{ - for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) { - - QString changed = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i)); - if( changed.contains("/Network/Global/IPv4")) { - QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info); - wlanEngine->requestUpdate(); - } - } - return; -} - - -QScanThread::QScanThread(QObject *parent) - :QThread(parent) -{ -} - -QScanThread::~QScanThread() -{ -} - -void QScanThread::quit() -{ - wait(); -} - -void QScanThread::run() -{ - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - QStringList found; - mutex.lock(); - CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)]; - mutex.unlock(); - - if([currentInterface power]) { - NSError *err = nil; - NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], kCWScanKeyMerge, - [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, - [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; - - NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; - CWNetwork *apNetwork; - - if (!err) { - - for(uint row=0; row < [apArray count]; row++ ) { - apNetwork = [apArray objectAtIndex:row]; - - const QString networkSsid = QCFString::toQString([apNetwork ssid]); - const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); - found.append(id); - - QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; - bool known = isKnownSsid(networkSsid); - if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - if( networkSsid == QCFString::toQString( [currentInterface ssid])) { - state = QNetworkConfiguration::Active; - } - } - if(state == QNetworkConfiguration::Undefined) { - if(known) { - state = QNetworkConfiguration::Discovered; - } else { - state = QNetworkConfiguration::Undefined; - } - } - QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose; - if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) { - purpose = QNetworkConfiguration::PublicPurpose; - } else { - purpose = QNetworkConfiguration::PrivatePurpose; - } - - found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose)); - - } - } - } - // add known configurations that are not around. - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - - QString networkName = i.key(); - const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); - - if(!found.contains(id)) { - QString networkSsid = getSsidFromNetworkName(networkName); - const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); - QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; - QString interfaceName; - QMapIterator<QString, QString> ij(i.value()); - while (ij.hasNext()) { - ij.next(); - interfaceName = ij.value(); - } - - if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - if( networkSsid == QCFString::toQString([currentInterface ssid])) { - state = QNetworkConfiguration::Active; - } - } - if(state == QNetworkConfiguration::Undefined) { - if( userProfiles.contains(networkName) - && found.contains(ssidId)) { - state = QNetworkConfiguration::Discovered; - } - } - - if(state == QNetworkConfiguration::Undefined) { - state = QNetworkConfiguration::Defined; - } - - found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose)); - } - } - emit networksChanged(); - [autoreleasepool release]; -} - -QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose) -{ - QStringList found; - QMutexLocker locker(&mutex); - QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate; - - ptr->name = name; - ptr->isValid = true; - ptr->id = id; - ptr->state = state; - ptr->type = QNetworkConfiguration::InternetAccessPoint; - ptr->bearerType = QNetworkConfiguration::BearerWLAN; - ptr->purpose = purpose; - - fetchedConfigurations.append( ptr); - configurationInterface.insert(ptr->id, interfaceName); - - locker.unlock(); - locker.relock(); - found.append(id); - return found; -} - -QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations() -{ - QMutexLocker locker(&mutex); - - QList<QNetworkConfigurationPrivate *> foundConfigurations = fetchedConfigurations; - fetchedConfigurations.clear(); - - return foundConfigurations; -} - -void QScanThread::getUserConfigurations() -{ - QMutexLocker locker(&mutex); - - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - userProfiles.clear(); - - NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; - for(uint row=0; row < [wifiInterfaces count]; row++ ) { - - CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; - if ( ![wifiInterface power] ) - continue; - - NSString *nsInterfaceName = [wifiInterface name]; -// add user configured system networks - SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); - NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); - CFRelease(dynRef); - if(airportPlist != nil) { - NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; - - NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; - for(NSString *ssidkey in thisSsidarray) { - QString thisSsid = QCFString::toQString(ssidkey); - if(!userProfiles.contains(thisSsid)) { - QMap <QString,QString> map; - map.insert(thisSsid, QCFString::toQString(nsInterfaceName)); - userProfiles.insert(thisSsid, map); - } - } - CFRelease(airportPlist); - } - - // 802.1X user profiles - QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; - NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile: QCFString::toNSString(userProfilePath)] autorelease]; - if(eapDict != nil) { - NSString *profileStr= @"Profiles"; - NSString *nameStr = @"UserDefinedName"; - NSString *networkSsidStr = @"Wireless Network"; - for (id profileKey in eapDict) { - if ([profileStr isEqualToString:profileKey]) { - NSDictionary *itemDict = [eapDict objectForKey:profileKey]; - for (id itemKey in itemDict) { - - NSInteger dictSize = [itemKey count]; - id objects[dictSize]; - id keys[dictSize]; - - [itemKey getObjects:objects andKeys:keys]; - QString networkName; - QString ssid; - for(int i = 0; i < dictSize; i++) { - if([nameStr isEqualToString:keys[i]]) { - networkName = QCFString::toQString(objects[i]); - } - if([networkSsidStr isEqualToString:keys[i]]) { - ssid = QCFString::toQString(objects[i]); - } - if(!userProfiles.contains(networkName) - && !ssid.isEmpty()) { - QMap<QString,QString> map; - map.insert(ssid, QCFString::toQString(nsInterfaceName)); - userProfiles.insert(networkName, map); - } - } - } - } - } - } - } - [autoreleasepool release]; -} - -QString QScanThread::getSsidFromNetworkName(const QString &name) -{ - QMutexLocker locker(&mutex); - - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - QMap<QString,QString> map = i.value(); - QMapIterator<QString, QString> ij(i.value()); - while (ij.hasNext()) { - ij.next(); - const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); - if(name == i.key() || name == networkNameHash) { - return ij.key(); - } - } - } - return QString(); -} - -QString QScanThread::getNetworkNameFromSsid(const QString &ssid) -{ - QMutexLocker locker(&mutex); - - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - QMap<QString,QString> map = i.value(); - QMapIterator<QString, QString> ij(i.value()); - while (ij.hasNext()) { - ij.next(); - if(ij.key() == ssid) { - return i.key(); - } - } - } - return QString(); -} - -bool QScanThread::isKnownSsid(const QString &ssid) -{ - QMutexLocker locker(&mutex); - - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - QMap<QString,QString> map = i.value(); - if(map.keys().contains(ssid)) { - return true; - } - } - return false; -} - - -QCoreWlanEngine::QCoreWlanEngine(QObject *parent) -: QBearerEngineImpl(parent), scanThread(0) -{ - scanThread = new QScanThread(this); - connect(scanThread, SIGNAL(networksChanged()), - this, SLOT(networksChanged())); -} - -QCoreWlanEngine::~QCoreWlanEngine() -{ - scanThread->terminate(); - scanThread->wait(); - - while (!foundConfigurations.isEmpty()) - delete foundConfigurations.takeFirst(); - [listener remove]; - [listener release]; -} - -void QCoreWlanEngine::initialize() -{ - QMutexLocker locker(&mutex); - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - if([[CWInterface supportedInterfaces] count] > 0 && !listener) { - listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init]; - listener.engine = this; - hasWifi = true; - } else { - hasWifi = false; - } - storeSession = NULL; - - startNetworkChangeLoop(); - [autoreleasepool release]; -} - - -QString QCoreWlanEngine::getInterfaceFromId(const QString &id) -{ - QMutexLocker locker(&mutex); - - return scanThread->configurationInterface.value(id); -} - -bool QCoreWlanEngine::hasIdentifier(const QString &id) -{ - QMutexLocker locker(&mutex); - - return scanThread->configurationInterface.contains(id); -} - -void QCoreWlanEngine::connectToId(const QString &id) -{ - QMutexLocker locker(&mutex); - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - QString interfaceString = getInterfaceFromId(id); - - CWInterface *wifiInterface = - [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; - - if ([wifiInterface power]) { - NSError *err = nil; - NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; - - QString wantedSsid; - - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - - const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); - const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name))); - - bool using8021X = false; - if (idHash2 != id) { - NSArray *array = [CW8021XProfile allUser8021XProfiles]; - - for (NSUInteger i = 0; i < [array count]; ++i) { - const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] userDefinedName]))); - - const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] ssid]))); - - if (id == networkNameHashCheck || id == ssidHash) { - const QString thisName = scanThread->getSsidFromNetworkName(id); - if (thisName.isEmpty()) - wantedSsid = id; - else - wantedSsid = thisName; - - [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; - using8021X = true; - break; - } - } - } - - if (!using8021X) { - QString wantedNetwork; - QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles); - while (i.hasNext()) { - i.next(); - wantedNetwork = i.key(); - const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); - if (id == networkNameHash) { - wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); - break; - } - } - } - NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], kCWScanKeyMerge, - [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, - [NSNumber numberWithInteger:100], kCWScanKeyRestTime, - QCFString::toNSString(wantedSsid), kCWScanKeySSID, - nil]; - - NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:scanParameters error:&err]; - - if(!err) { - for(uint row=0; row < [scanArray count]; row++ ) { - CWNetwork *apNetwork = [scanArray objectAtIndex:row]; - - if(wantedSsid == QCFString::toQString([apNetwork ssid])) { - - if(!using8021X) { - SecKeychainAttribute attributes[3]; - - NSString *account = [apNetwork ssid]; - NSString *keyKind = @"AirPort network password"; - NSString *keyName = account; - - attributes[0].tag = kSecAccountItemAttr; - attributes[0].data = (void *)[account UTF8String]; - attributes[0].length = [account length]; - - attributes[1].tag = kSecDescriptionItemAttr; - attributes[1].data = (void *)[keyKind UTF8String]; - attributes[1].length = [keyKind length]; - - attributes[2].tag = kSecLabelItemAttr; - attributes[2].data = (void *)[keyName UTF8String]; - attributes[2].length = [keyName length]; - - SecKeychainAttributeList attributeList = {3,attributes}; - - SecKeychainSearchRef searchRef; - SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); - - NSString *password = @""; - SecKeychainItemRef searchItem; - - if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) { - UInt32 realPasswordLength; - SecKeychainAttribute attributesW[8]; - attributesW[0].tag = kSecAccountItemAttr; - SecKeychainAttributeList listW = {1,attributesW}; - char *realPassword; - OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); - - if (status == noErr) { - if (realPassword != NULL) { - - QByteArray pBuf; - pBuf.resize(realPasswordLength); - pBuf.prepend(realPassword); - pBuf.insert(realPasswordLength,'\0'); - - password = [NSString stringWithUTF8String:pBuf]; - } - SecKeychainItemFreeContent(&listW, realPassword); - } - - CFRelease(searchItem); - } else { - qDebug() << "SecKeychainSearchCopyNext error"; - } - [params setValue: password forKey: kCWAssocKeyPassphrase]; - } // end using8021X - - - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; - - if(!err) { - if(!result) { - emit connectionError(id, ConnectError); - } else { - return; - } - } else { - qDebug() <<"associate ERROR"<< QCFString::toQString([err localizedDescription ]); - } - } - } //end scan network - } else { - qDebug() <<"scan ERROR"<< QCFString::toQString([err localizedDescription ]); - } - emit connectionError(id, InterfaceLookupError); - } - - locker.unlock(); - emit connectionError(id, InterfaceLookupError); - [autoreleasepool release]; -} - -void QCoreWlanEngine::disconnectFromId(const QString &id) -{ - QMutexLocker locker(&mutex); - - QString interfaceString = getInterfaceFromId(id); - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - CWInterface *wifiInterface = - [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; - - [wifiInterface disassociate]; - if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { - locker.unlock(); - emit connectionError(id, DisconnectionError); - locker.relock(); - } - [autoreleasepool release]; -} - -void QCoreWlanEngine::requestUpdate() -{ - scanThread->getUserConfigurations(); - doRequestUpdate(); -} - -void QCoreWlanEngine::doRequestUpdate() -{ - QMutexLocker locker(&mutex); - - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; - for (uint row = 0; row < [wifiInterfaces count]; ++row) { - scanThread->interfaceName = QCFString::toQString([wifiInterfaces objectAtIndex:row]); - scanThread->start(); - } - locker.unlock(); - if ([wifiInterfaces count] == 0) - networksChanged(); - [autoreleasepool release]; -} - -bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) -{ - QMutexLocker locker(&mutex); - bool haswifi = false; - if(hasWifi) { - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)]; - if([defaultInterface power]) { - haswifi = true; - } - [autoreleasepool release]; - } - return haswifi; -} - - -QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id) -{ - QMutexLocker locker(&mutex); - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - - if (!ptr) - return QNetworkSession::Invalid; - - if (!ptr->isValid) { - return QNetworkSession::Invalid; - } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - return QNetworkSession::Connected; - } else if ((ptr->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { - return QNetworkSession::Disconnected; - } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { - return QNetworkSession::NotAvailable; - } else if ((ptr->state & QNetworkConfiguration::Undefined) == - QNetworkConfiguration::Undefined) { - return QNetworkSession::NotAvailable; - } - - return QNetworkSession::Invalid; -} - -QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const -{ - return QNetworkConfigurationManager::ForcedRoaming; -} - -void QCoreWlanEngine::startNetworkChangeLoop() -{ - - SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; - storeSession = SCDynamicStoreCreate(NULL, - CFSTR("networkChangeCallback"), - networkChangeCallback, - &dynStoreContext); - if (!storeSession ) { - qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError()); - return; - } - - CFMutableArrayRef notificationKeys; - notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFMutableArrayRef patternsArray; - patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - CFStringRef storeKey; - storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, - kSCDynamicStoreDomainState, - kSCEntNetIPv4); - CFArrayAppendValue(notificationKeys, storeKey); - CFRelease(storeKey); - - storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, - kSCDynamicStoreDomainState, - kSCCompAnyRegex, - kSCEntNetIPv4); - CFArrayAppendValue(patternsArray, storeKey); - CFRelease(storeKey); - - if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { - qWarning() << "register notification error:"<< SCErrorString(SCError()); - CFRelease(storeSession ); - CFRelease(notificationKeys); - CFRelease(patternsArray); - return; - } - CFRelease(notificationKeys); - CFRelease(patternsArray); - - runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); - if (!runloopSource) { - qWarning() << "runloop source error:"<< SCErrorString(SCError()); - CFRelease(storeSession ); - return; - } - - CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); - return; -} - -QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend() -{ - return new QNetworkSessionPrivateImpl; -} - -QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration() -{ - return QNetworkConfigurationPrivatePointer(); -} - -bool QCoreWlanEngine::requiresPolling() const -{ - return true; -} - -void QCoreWlanEngine::networksChanged() -{ - QMutexLocker locker(&mutex); - - QStringList previous = accessPointConfigurations.keys(); - - QList<QNetworkConfigurationPrivate *> foundConfigurations = scanThread->getConfigurations(); - while (!foundConfigurations.isEmpty()) { - QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst(); - - previous.removeAll(cpPriv->id); - - if (accessPointConfigurations.contains(cpPriv->id)) { - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); - - bool changed = false; - - ptr->mutex.lock(); - - if (ptr->isValid != cpPriv->isValid) { - ptr->isValid = cpPriv->isValid; - changed = true; - } - - if (ptr->name != cpPriv->name) { - ptr->name = cpPriv->name; - changed = true; - } - - if (ptr->bearerType != cpPriv->bearerType) { - ptr->bearerType = cpPriv->bearerType; - changed = true; - } - - if (ptr->state != cpPriv->state) { - ptr->state = cpPriv->state; - changed = true; - } - - ptr->mutex.unlock(); - - if (changed) { - locker.unlock(); - emit configurationChanged(ptr); - locker.relock(); - } - - delete cpPriv; - } else { - QNetworkConfigurationPrivatePointer ptr(cpPriv); - - accessPointConfigurations.insert(ptr->id, ptr); - - locker.unlock(); - emit configurationAdded(ptr); - locker.relock(); - } - } - - while (!previous.isEmpty()) { - QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.take(previous.takeFirst()); - - locker.unlock(); - emit configurationRemoved(ptr); - locker.relock(); - } - - locker.unlock(); - emit updateCompleted(); - -} - -quint64 QCoreWlanEngine::bytesWritten(const QString &id) -{ - QMutexLocker locker(&mutex); - const QString interfaceStr = getInterfaceFromId(id); - return getBytes(interfaceStr,false); -} - -quint64 QCoreWlanEngine::bytesReceived(const QString &id) -{ - QMutexLocker locker(&mutex); - const QString interfaceStr = getInterfaceFromId(id); - return getBytes(interfaceStr,true); -} - -quint64 QCoreWlanEngine::startTime(const QString &identifier) -{ - QMutexLocker locker(&mutex); - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - quint64 timestamp = 0; - - NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"; - NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease]; - if(plistDict == nil) - return timestamp; - NSString *input = @"KnownNetworks"; - NSString *timeStampStr = @"_timeStamp"; - - NSString *ssidStr = @"SSID_STR"; - - for (id key in plistDict) { - if ([input isEqualToString:key]) { - - NSDictionary *knownNetworksDict = [plistDict objectForKey:key]; - if(knownNetworksDict == nil) - return timestamp; - for (id networkKey in knownNetworksDict) { - bool isFound = false; - NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey]; - if(itemDict == nil) - return timestamp; - NSInteger dictSize = [itemDict count]; - id objects[dictSize]; - id keys[dictSize]; - - [itemDict getObjects:objects andKeys:keys]; - bool ok = false; - for(int i = 0; i < dictSize; i++) { - if([ssidStr isEqualToString:keys[i]]) { - const QString ident = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString(objects[i]))); - if(ident == identifier) { - ok = true; - } - } - if(ok && [timeStampStr isEqualToString:keys[i]]) { - timestamp = (quint64)[objects[i] timeIntervalSince1970]; - isFound = true; - break; - } - } - if(isFound) - break; - } - } - } - [autoreleasepool release]; - return timestamp; -} - -quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b) -{ - struct ifaddrs *ifAddressList, *ifAddress; - struct if_data *if_data; - - quint64 bytes = 0; - ifAddressList = nil; - if(getifaddrs(&ifAddressList) == 0) { - for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) { - if(interfaceName == ifAddress->ifa_name) { - if_data = (struct if_data*)ifAddress->ifa_data; - if(b) { - bytes = if_data->ifi_ibytes; - break; - } else { - bytes = if_data->ifi_obytes; - break; - } - } - } - freeifaddrs(ifAddressList); - } - return bytes; -} - -QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index 08a0bb4c63..5f49ea0b6d 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -55,25 +55,21 @@ QT_BEGIN_NAMESPACE QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) : QBearerEngineImpl(parent), - interface(new QNetworkManagerInterface(this)), - systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_SYSTEM_SETTINGS, this)), - userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_USER_SETTINGS, this)) + managerInterface(new QNetworkManagerInterface(this)), + systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)), + userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)) { - if (!interface->isValid()) + if (!managerInterface->isValid()) return; - interface->setConnections(); - connect(interface, SIGNAL(deviceAdded(QDBusObjectPath)), + managerInterface->setConnections(); + connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)), this, SLOT(deviceAdded(QDBusObjectPath))); - connect(interface, SIGNAL(deviceRemoved(QDBusObjectPath)), + connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)), this, SLOT(deviceRemoved(QDBusObjectPath))); -#if 0 - connect(interface, SIGNAL(stateChanged(QString,quint32)), - this, SIGNAL(configurationsChanged())); -#endif - connect(interface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), + connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), this, SLOT(activationFinished(QDBusPendingCallWatcher*))); - connect(interface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), + connect(managerInterface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), this, SLOT(interfacePropertiesChanged(QString,QMap<QString,QVariant>))); qDBusRegisterMetaType<QNmSettingsMap>(); @@ -100,52 +96,56 @@ void QNetworkManagerEngine::initialize() QMutexLocker locker(&mutex); // Get current list of access points. - foreach (const QDBusObjectPath &devicePath, interface->getDevices()) { + foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { locker.unlock(); - deviceAdded(devicePath); + deviceAdded(devicePath); //add all accesspoints locker.relock(); } // Get connections. + foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) { locker.unlock(); - newConnection(settingsPath, systemSettings); + if (!hasIdentifier(settingsPath.path())) + newConnection(settingsPath, systemSettings); //add system connection configs locker.relock(); } + foreach (const QDBusObjectPath &settingsPath, userSettings->listConnections()) { locker.unlock(); - newConnection(settingsPath, userSettings); + if (!hasIdentifier(settingsPath.path())) + newConnection(settingsPath, userSettings); locker.relock(); } // Get active connections. - foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { QNetworkManagerConnectionActive *activeConnection = - new QNetworkManagerConnectionActive(acPath.path()); + new QNetworkManagerConnectionActive(acPath.path(),this); activeConnections.insert(acPath.path(), activeConnection); activeConnection->setConnections(); connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>))); } + Q_EMIT updateCompleted(); } bool QNetworkManagerEngine::networkManagerAvailable() const { QMutexLocker locker(&mutex); - return interface->isValid(); + return managerInterface->isValid(); } QString QNetworkManagerEngine::getInterfaceFromId(const QString &id) { QMutexLocker locker(&mutex); - foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { QNetworkManagerConnectionActive activeConnection(acPath.path()); - const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' + - activeConnection.connection().path())); + const QString identifier = activeConnection.connection().path(); if (id == identifier) { QList<QDBusObjectPath> devices = activeConnection.devices(); @@ -161,24 +161,11 @@ QString QNetworkManagerEngine::getInterfaceFromId(const QString &id) return QString(); } + bool QNetworkManagerEngine::hasIdentifier(const QString &id) { QMutexLocker locker(&mutex); - - if (connectionFromId(id)) - return true; - - for (int i = 0; i < accessPoints.count(); ++i) { - QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i); - - const QString identifier = - QString::number(qHash(accessPoint->connectionInterface()->path())); - - if (id == identifier) - return true; - } - - return false; + return accessPointConfigurations.contains(id); } void QNetworkManagerEngine::connectToId(const QString &id) @@ -194,18 +181,17 @@ void QNetworkManagerEngine::connectToId(const QString &id) const QString connectionType = map.value("connection").value("type").toString(); QString dbusDevicePath; - foreach (const QDBusObjectPath &devicePath, interface->getDevices()) { + foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { QNetworkManagerInterfaceDevice device(devicePath.path()); - if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET && + if (device.deviceType() == DEVICE_TYPE_ETHERNET && connectionType == QLatin1String("802-3-ethernet")) { dbusDevicePath = devicePath.path(); break; - } else if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS && + } else if (device.deviceType() == DEVICE_TYPE_WIFI && connectionType == QLatin1String("802-11-wireless")) { dbusDevicePath = devicePath.path(); break; - } - else if (device.deviceType() == DEVICE_TYPE_GSM && + } else if (device.deviceType() == DEVICE_TYPE_MODEM && connectionType == QLatin1String("gsm")) { dbusDevicePath = devicePath.path(); break; @@ -214,23 +200,34 @@ void QNetworkManagerEngine::connectToId(const QString &id) const QString service = connection->connectionInterface()->service(); const QString settingsPath = connection->connectionInterface()->path(); + QString specificPath = configuredAccessPoints.key(settingsPath); + + if (specificPath.isEmpty()) + specificPath = "/"; - interface->activateConnection(service, QDBusObjectPath(settingsPath), - QDBusObjectPath(dbusDevicePath), QDBusObjectPath("/")); + managerInterface->activateConnection(service, QDBusObjectPath(settingsPath), + QDBusObjectPath(dbusDevicePath), QDBusObjectPath(specificPath)); } void QNetworkManagerEngine::disconnectFromId(const QString &id) { QMutexLocker locker(&mutex); - foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerSettingsConnection *connection = connectionFromId(id); + QNmSettingsMap map = connection->getSettings(); + bool connectionAutoconnect = map.value("connection").value("autoconnect",true).toBool(); //if not present is true !! + if (connectionAutoconnect) { //autoconnect connections will simply be reconnected by nm + emit connectionError(id, QBearerEngineImpl::OperationNotSupported); + return; + } + + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { QNetworkManagerConnectionActive activeConnection(acPath.path()); - const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' + - activeConnection.connection().path())); + const QString identifier = activeConnection.connection().path(); if (id == identifier && accessPointConfigurations.contains(id)) { - interface->deactivateConnection(acPath); + managerInterface->deactivateConnection(acPath); break; } } @@ -238,15 +235,26 @@ void QNetworkManagerEngine::disconnectFromId(const QString &id) void QNetworkManagerEngine::requestUpdate() { + if (managerInterface->wirelessEnabled()) { + QHashIterator<QString, QNetworkManagerInterfaceDeviceWireless *> i(wirelessDevices); + while (i.hasNext()) { + i.next(); + i.value()->requestScan(); + } + } + QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection); +} + +void QNetworkManagerEngine::scanFinished() +{ QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection); } void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, const QMap<QString, QVariant> &properties) { - QMutexLocker locker(&mutex); - Q_UNUSED(path) + QMutexLocker locker(&mutex); QMapIterator<QString, QVariant> i(properties); while (i.hasNext()) { @@ -269,7 +277,7 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, QNetworkManagerConnectionActive *activeConnection = this->activeConnections.value(acPath.path()); if (!activeConnection) { - activeConnection = new QNetworkManagerConnectionActive(acPath.path()); + activeConnection = new QNetworkManagerConnectionActive(acPath.path(),this); this->activeConnections.insert(acPath.path(), activeConnection); activeConnection->setConnections(); @@ -277,15 +285,14 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>))); } - const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' + - activeConnection->connection().path())); + const QString id = activeConnection->connection().path(); identifiers.removeOne(id); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { ptr->mutex.lock(); - if (activeConnection->state() == 2 && + if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && ptr->state != QNetworkConfiguration::Active) { ptr->state = QNetworkConfiguration::Active; ptr->mutex.unlock(); @@ -303,13 +310,13 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, delete this->activeConnections.take(priorActiveConnections.takeFirst()); while (!identifiers.isEmpty()) { - // These configurations are not active QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(identifiers.takeFirst()); ptr->mutex.lock(); if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - ptr->state = QNetworkConfiguration::Discovered; + QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; + ptr->state = (flag | QNetworkConfiguration::Discovered); ptr->mutex.unlock(); locker.unlock(); @@ -335,15 +342,14 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat if (!activeConnection) return; - const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' + - activeConnection->connection().path())); + const QString id = activeConnection->connection().path(); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { ptr->mutex.lock(); - if (activeConnection->state() == 2 && + if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && ptr->state != QNetworkConfiguration::Active) { - ptr->state = QNetworkConfiguration::Active; + ptr->state |= QNetworkConfiguration::Active; ptr->mutex.unlock(); locker.unlock(); @@ -355,34 +361,63 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat } } -void QNetworkManagerEngine::devicePropertiesChanged(const QString &path, - const QMap<QString, QVariant> &properties) +void QNetworkManagerEngine::devicePropertiesChanged(const QString &/*path*/,quint32 /*state*/) +{ +// Q_UNUSED(path); +// Q_UNUSED(state) +} + +void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &activeConnectionsList) { - Q_UNUSED(path); - Q_UNUSED(properties); + QMutexLocker locker(&mutex); + for (int i = 0; i < connections.count(); ++i) { + if (activeConnectionsList.contains(connections.at(i)->connectionInterface()->path())) + continue; + + const QString settingsPath = connections.at(i)->connectionInterface()->path(); + + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.value(settingsPath); + ptr->mutex.lock(); + QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; + ptr->state = (flag | QNetworkConfiguration::Discovered); + ptr->mutex.unlock(); + + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + Q_EMIT updateCompleted(); + } } void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path) { - QNetworkManagerInterfaceDevice device(path.path()); - if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS) { + QMutexLocker locker(&mutex); + QNetworkManagerInterfaceDevice *iDevice; + iDevice = new QNetworkManagerInterfaceDevice(path.path(),this); + connect(iDevice,SIGNAL(connectionsChanged(QStringList)), + this,SLOT(deviceConnectionsChanged(QStringList))); + + connect(iDevice,SIGNAL(stateChanged(QString,quint32)), + this,SLOT(devicePropertiesChanged(QString,quint32))); + iDevice->setConnections(); + interfaceDevices.insert(path.path(),iDevice); + + if (iDevice->deviceType() == DEVICE_TYPE_WIFI) { QNetworkManagerInterfaceDeviceWireless *wirelessDevice = - new QNetworkManagerInterfaceDeviceWireless(device.connectionInterface()->path()); + new QNetworkManagerInterfaceDeviceWireless(iDevice->connectionInterface()->path(),this); wirelessDevice->setConnections(); - connect(wirelessDevice, SIGNAL(accessPointAdded(QString,QDBusObjectPath)), - this, SLOT(newAccessPoint(QString,QDBusObjectPath))); - connect(wirelessDevice, SIGNAL(accessPointRemoved(QString,QDBusObjectPath)), - this, SLOT(removeAccessPoint(QString,QDBusObjectPath))); - connect(wirelessDevice, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), - this, SLOT(devicePropertiesChanged(QString,QMap<QString,QVariant>))); + connect(wirelessDevice, SIGNAL(accessPointAdded(QString)), + this, SLOT(newAccessPoint(QString))); + connect(wirelessDevice, SIGNAL(accessPointRemoved(QString)), + this, SLOT(removeAccessPoint(QString))); + connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished())); foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints()) - newAccessPoint(QString(), apPath); + newAccessPoint(apPath.path()); - mutex.lock(); wirelessDevices.insert(path.path(), wirelessDevice); - mutex.unlock(); } } @@ -390,47 +425,73 @@ void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path) { QMutexLocker locker(&mutex); - delete wirelessDevices.take(path.path()); + if (interfaceDevices.contains(path.path())) { + locker.unlock(); + delete interfaceDevices.take(path.path()); + locker.relock(); + } + if (wirelessDevices.contains(path.path())) { + locker.unlock(); + delete wirelessDevices.take(path.path()); + locker.relock(); + } } void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings) { QMutexLocker locker(&mutex); - if (!settings) settings = qobject_cast<QNetworkManagerSettings *>(sender()); if (!settings) return; + settings->deleteLater(); QNetworkManagerSettingsConnection *connection = new QNetworkManagerSettingsConnection(settings->connectionInterface()->service(), - path.path()); + path.path(),this); + QString apPath; + for (int i = 0; i < accessPoints.count(); ++i) { + if (connection->getSsid() == accessPoints.at(i)->ssid()) { + // remove the corresponding accesspoint from configurations + apPath = accessPoints.at(i)->connectionInterface()->path(); + + QNetworkConfigurationPrivatePointer ptr + = accessPointConfigurations.take(apPath); + if (ptr) { + locker.unlock(); + emit configurationRemoved(ptr); + locker.relock(); + } + } + } connections.append(connection); - connect(connection, SIGNAL(removed(QString)), this, SLOT(removeConnection(QString))); - connect(connection, SIGNAL(updated(QNmSettingsMap)), - this, SLOT(updateConnection(QNmSettingsMap))); + connect(connection,SIGNAL(removed(QString)),this,SLOT(removeConnection(QString))); + connect(connection,SIGNAL(updated()),this,SLOT(updateConnection())); + connection->setConnections(); - const QString service = connection->connectionInterface()->service(); const QString settingsPath = connection->connectionInterface()->path(); + if (connection->getType() == DEVICE_TYPE_WIFI + && !configuredAccessPoints.contains(settingsPath)) + configuredAccessPoints.insert(apPath,settingsPath); + QNetworkConfigurationPrivate *cpPriv = - parseConnection(service, settingsPath, connection->getSettings()); + parseConnection(settingsPath, connection->getSettings()); // Check if connection is active. - foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { QNetworkManagerConnectionActive activeConnection(acPath.path()); - if (activeConnection.serviceName() == service && + if (activeConnection.defaultRoute() && activeConnection.connection().path() == settingsPath && - activeConnection.state() == 2) { + activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { cpPriv->state |= QNetworkConfiguration::Active; break; } } - QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ptr->id, ptr); @@ -442,27 +503,34 @@ void QNetworkManagerEngine::removeConnection(const QString &path) { QMutexLocker locker(&mutex); - Q_UNUSED(path) - QNetworkManagerSettingsConnection *connection = qobject_cast<QNetworkManagerSettingsConnection *>(sender()); if (!connection) return; + connection->deleteLater(); connections.removeAll(connection); - const QString id = QString::number(qHash(connection->connectionInterface()->service() + ' ' + - connection->connectionInterface()->path())); + const QString id = path; QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id); - connection->deleteLater(); - - locker.unlock(); - emit configurationRemoved(ptr); + if (ptr) { + locker.unlock(); + emit configurationRemoved(ptr); + locker.relock(); + } + // add base AP back into configurations + QMapIterator<QString, QString> i(configuredAccessPoints); + while (i.hasNext()) { + i.next(); + if (i.value() == path) { + newAccessPoint(i.key()); + } + } } -void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings) +void QNetworkManagerEngine::updateConnection() { QMutexLocker locker(&mutex); @@ -471,17 +539,16 @@ void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings) if (!connection) return; - const QString service = connection->connectionInterface()->service(); + connection->deleteLater(); const QString settingsPath = connection->connectionInterface()->path(); - QNetworkConfigurationPrivate *cpPriv = parseConnection(service, settingsPath, settings); + QNetworkConfigurationPrivate *cpPriv = parseConnection(settingsPath, connection->getSettings()); // Check if connection is active. - foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { QNetworkManagerConnectionActive activeConnection(acPath.path()); - if (activeConnection.serviceName() == service && - activeConnection.connection().path() == settingsPath && + if (activeConnection.connection().path() == settingsPath && activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { cpPriv->state |= QNetworkConfiguration::Active; break; @@ -501,6 +568,7 @@ void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings) locker.unlock(); emit configurationChanged(ptr); + locker.relock(); delete cpPriv; } @@ -508,21 +576,22 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) { QMutexLocker locker(&mutex); + watcher->deleteLater(); + QDBusPendingReply<QDBusObjectPath> reply(*watcher); if (!reply.isError()) { QDBusObjectPath result = reply.value(); QNetworkManagerConnectionActive activeConnection(result.path()); - const QString id = QString::number(qHash(activeConnection.serviceName() + ' ' + - activeConnection.connection().path())); + const QString id = activeConnection.connection().path(); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { ptr->mutex.lock(); - if (activeConnection.state() == 2 && + if (activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && ptr->state != QNetworkConfiguration::Active) { - ptr->state = QNetworkConfiguration::Active; + ptr->state |= QNetworkConfiguration::Active; ptr->mutex.unlock(); locker.unlock(); @@ -535,42 +604,41 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) } } -void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjectPath &objectPath) +void QNetworkManagerEngine::newAccessPoint(const QString &path) { QMutexLocker locker(&mutex); - Q_UNUSED(path) - QNetworkManagerInterfaceAccessPoint *accessPoint = - new QNetworkManagerInterfaceAccessPoint(objectPath.path()); - accessPoints.append(accessPoint); - - accessPoint->setConnections(); - connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)), - this, SLOT(updateAccessPoint(QMap<QString,QVariant>))); + new QNetworkManagerInterfaceAccessPoint(path,this); - // Check if configuration for this SSID already exists. + bool okToAdd = true; for (int i = 0; i < accessPoints.count(); ++i) { - if (accessPoint != accessPoints.at(i) && - accessPoint->ssid() == accessPoints.at(i)->ssid()) { - return; + if (accessPoints.at(i)->connectionInterface()->path() == path) { + okToAdd = false; } } + if (okToAdd) { + accessPoints.append(accessPoint); + accessPoint->setConnections(); + connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)), + this, SLOT(updateAccessPoint(QMap<QString,QVariant>))); + } // Check if configuration exists for connection. if (!accessPoint->ssid().isEmpty()) { for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); - + const QString settingsPath = connection->connectionInterface()->path(); if (accessPoint->ssid() == connection->getSsid()) { - const QString service = connection->connectionInterface()->service(); - const QString settingsPath = connection->connectionInterface()->path(); - const QString connectionId = QString::number(qHash(service + ' ' + settingsPath)); + if (!configuredAccessPoints.contains(path)) { + configuredAccessPoints.insert(path,settingsPath); + } QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.value(connectionId); + accessPointConfigurations.value(settingsPath); ptr->mutex.lock(); - ptr->state = QNetworkConfiguration::Discovered; + QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; + ptr->state = (flag | QNetworkConfiguration::Discovered); ptr->mutex.unlock(); locker.unlock(); @@ -585,9 +653,9 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec ptr->name = accessPoint->ssid(); ptr->isValid = true; - ptr->id = QString::number(qHash(objectPath.path())); + ptr->id = path; ptr->type = QNetworkConfiguration::InternetAccessPoint; - if(accessPoint->flags() == NM_802_11_AP_FLAGS_PRIVACY) { + if (accessPoint->flags() == NM_802_11_AP_FLAGS_PRIVACY) { ptr->purpose = QNetworkConfiguration::PrivatePurpose; } else { ptr->purpose = QNetworkConfiguration::PublicPurpose; @@ -601,30 +669,24 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec emit configurationAdded(ptr); } -void QNetworkManagerEngine::removeAccessPoint(const QString &path, - const QDBusObjectPath &objectPath) +void QNetworkManagerEngine::removeAccessPoint(const QString &path) { QMutexLocker locker(&mutex); - - Q_UNUSED(path) - for (int i = 0; i < accessPoints.count(); ++i) { QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i); - if (accessPoint->connectionInterface()->path() == objectPath.path()) { + if (accessPoint->connectionInterface()->path() == path) { accessPoints.removeOne(accessPoint); - if (configuredAccessPoints.contains(accessPoint)) { + if (configuredAccessPoints.contains(accessPoint->connectionInterface()->path())) { // find connection and change state to Defined - configuredAccessPoints.removeOne(accessPoint); + configuredAccessPoints.remove(accessPoint->connectionInterface()->path()); for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); - if (accessPoint->ssid() == connection->getSsid()) { - const QString service = connection->connectionInterface()->service(); + if (accessPoint->ssid() == connection->getSsid()) {//might not have bssid yet const QString settingsPath = connection->connectionInterface()->path(); - const QString connectionId = - QString::number(qHash(service + ' ' + settingsPath)); + const QString connectionId = settingsPath; QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(connectionId); @@ -640,17 +702,17 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path, } } else { QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.take(QString::number(qHash(objectPath.path()))); + accessPointConfigurations.take(path); if (ptr) { locker.unlock(); + + locker.unlock(); emit configurationRemoved(ptr); locker.relock(); } } - delete accessPoint; - break; } } @@ -666,19 +728,19 @@ void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map qobject_cast<QNetworkManagerInterfaceAccessPoint *>(sender()); if (!accessPoint) return; - + accessPoint->deleteLater(); for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); if (accessPoint->ssid() == connection->getSsid()) { - const QString service = connection->connectionInterface()->service(); const QString settingsPath = connection->connectionInterface()->path(); - const QString connectionId = QString::number(qHash(service + ' ' + settingsPath)); + const QString connectionId = settingsPath; QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(connectionId); ptr->mutex.lock(); - ptr->state = QNetworkConfiguration::Discovered; + QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; + ptr->state = (flag | QNetworkConfiguration::Discovered); ptr->mutex.unlock(); locker.unlock(); @@ -688,14 +750,16 @@ void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map } } -QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &service, - const QString &settingsPath, +QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &settingsPath, const QNmSettingsMap &map) { + // Q_UNUSED(service); + QMutexLocker locker(&mutex); QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; cpPriv->name = map.value("connection").value("id").toString(); + cpPriv->isValid = true; - cpPriv->id = QString::number(qHash(service + ' ' + settingsPath)); + cpPriv->id = settingsPath; cpPriv->type = QNetworkConfiguration::InternetAccessPoint; cpPriv->purpose = QNetworkConfiguration::PublicPurpose; @@ -708,15 +772,14 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri cpPriv->bearerType = QNetworkConfiguration::BearerEthernet; cpPriv->purpose = QNetworkConfiguration::PublicPurpose; - foreach (const QDBusObjectPath &devicePath, interface->getDevices()) { + foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { QNetworkManagerInterfaceDevice device(devicePath.path()); - if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET) { + if (device.deviceType() == DEVICE_TYPE_ETHERNET) { QNetworkManagerInterfaceDeviceWired wiredDevice(device.connectionInterface()->path()); if (wiredDevice.carrier()) { cpPriv->state |= QNetworkConfiguration::Discovered; break; } - } } } else if (connectionType == QLatin1String("802-11-wireless")) { @@ -724,35 +787,57 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri const QString connectionSsid = map.value("802-11-wireless").value("ssid").toString(); const QString connectionSecurity = map.value("802-11-wireless").value("security").toString(); - if(!connectionSecurity.isEmpty()) { + if (!connectionSecurity.isEmpty()) { cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; } else { cpPriv->purpose = QNetworkConfiguration::PublicPurpose; } for (int i = 0; i < accessPoints.count(); ++i) { - if (connectionSsid == accessPoints.at(i)->ssid()) { + if (connectionSsid == accessPoints.at(i)->ssid() + && map.value("802-11-wireless").value("seen-bssids").toStringList().contains(accessPoints.at(i)->hwAddress())) { cpPriv->state |= QNetworkConfiguration::Discovered; - if (!configuredAccessPoints.contains(accessPoints.at(i))) { - configuredAccessPoints.append(accessPoints.at(i)); + if (!configuredAccessPoints.contains(accessPoints.at(i)->connectionInterface()->path())) { + configuredAccessPoints.insert(accessPoints.at(i)->connectionInterface()->path(),settingsPath); - const QString accessPointId = - QString::number(qHash(accessPoints.at(i)->connectionInterface()->path())); + const QString accessPointId = accessPoints.at(i)->connectionInterface()->path(); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(accessPointId); if (ptr) { - mutex.unlock(); + locker.unlock(); emit configurationRemoved(ptr); - mutex.lock(); + locker.relock(); } } break; } } - } else if (connectionType == "gsm") { - cpPriv->bearerType = QNetworkConfiguration::Bearer2G; - } else if (connectionType == "cdma") { - cpPriv->bearerType = QNetworkConfiguration::BearerCDMA2000; + } else if (connectionType == QLatin1String("gsm")) { + + foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { + QNetworkManagerInterfaceDevice device(devicePath.path()); + + if (device.deviceType() == DEVICE_TYPE_MODEM) { + QNetworkManagerInterfaceDeviceModem deviceModem(device.connectionInterface()->path(),this); + switch (deviceModem.currentCapabilities()) { + case 2: + cpPriv->bearerType = QNetworkConfiguration::Bearer2G; + break; + case 4: + cpPriv->bearerType = QNetworkConfiguration::Bearer3G; + break; + case 8: + cpPriv->bearerType = QNetworkConfiguration::Bearer4G; + break; + default: + cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; + break; + }; + } + } + + cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; + cpPriv->state |= QNetworkConfiguration::Discovered; } return cpPriv; @@ -762,12 +847,7 @@ QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const { for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); - const QString service = connection->connectionInterface()->service(); - const QString settingsPath = connection->connectionInterface()->path(); - - const QString identifier = QString::number(qHash(service + ' ' + settingsPath)); - - if (id == identifier) + if (id == connection->connectionInterface()->path()) return connection; } @@ -789,8 +869,7 @@ QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &i foreach (const QString &acPath, activeConnections.keys()) { QNetworkManagerConnectionActive *activeConnection = activeConnections.value(acPath); - const QString identifier = QString::number(qHash(activeConnection->serviceName() + ' ' + - activeConnection->connection().path())); + const QString identifier = activeConnection->connection().path(); if (id == identifier) { switch (activeConnection->state()) { @@ -884,7 +963,8 @@ quint64 QNetworkManagerEngine::startTime(const QString &id) QNetworkConfigurationManager::Capabilities QNetworkManagerEngine::capabilities() const { return QNetworkConfigurationManager::ForcedRoaming | - QNetworkConfigurationManager::CanStartAndStopInterfaces; + QNetworkConfigurationManager::DataStatistics | + QNetworkConfigurationManager::CanStartAndStopInterfaces; } QNetworkSessionPrivate *QNetworkManagerEngine::createSessionBackend() diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h index 19a569d01e..ab1cfea71e 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h @@ -93,36 +93,37 @@ private Q_SLOTS: const QMap<QString, QVariant> &properties); void activeConnectionPropertiesChanged(const QString &path, const QMap<QString, QVariant> &properties); - void devicePropertiesChanged(const QString &path, - const QMap<QString, QVariant> &properties); + void devicePropertiesChanged(const QString &path, quint32); void deviceAdded(const QDBusObjectPath &path); void deviceRemoved(const QDBusObjectPath &path); void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0); void removeConnection(const QString &path); - void updateConnection(const QNmSettingsMap &settings); + void updateConnection(); void activationFinished(QDBusPendingCallWatcher *watcher); + void deviceConnectionsChanged(const QStringList &activeConnectionsList); - void newAccessPoint(const QString &path, const QDBusObjectPath &objectPath); - void removeAccessPoint(const QString &path, const QDBusObjectPath &objectPath); + void newAccessPoint(const QString &path); + void removeAccessPoint(const QString &path); void updateAccessPoint(const QMap<QString, QVariant> &map); + void scanFinished(); private: - QNetworkConfigurationPrivate *parseConnection(const QString &service, - const QString &settingsPath, + QNetworkConfigurationPrivate *parseConnection(const QString &settingsPath, const QNmSettingsMap &map); QNetworkManagerSettingsConnection *connectionFromId(const QString &id) const; -private: - QNetworkManagerInterface *interface; + QNetworkManagerInterface *managerInterface; QNetworkManagerSettings *systemSettings; QNetworkManagerSettings *userSettings; QHash<QString, QNetworkManagerInterfaceDeviceWireless *> wirelessDevices; QHash<QString, QNetworkManagerConnectionActive *> activeConnections; QList<QNetworkManagerSettingsConnection *> connections; QList<QNetworkManagerInterfaceAccessPoint *> accessPoints; - QList<QNetworkManagerInterfaceAccessPoint *> configuredAccessPoints; + QHash<QString, QNetworkManagerInterfaceDevice *> interfaceDevices; + + QMap<QString,QString> configuredAccessPoints; //ap, settings path }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp index d249d85c4d..f249ac6100 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -97,21 +97,21 @@ bool QNetworkManagerInterface::setConnections() QDBusConnection dbusConnection = QDBusConnection::systemBus(); bool allOk = false; - if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("PropertiesChanged"), nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>)))) { allOk = true; } - if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("DeviceAdded"), this,SIGNAL(deviceAdded(QDBusObjectPath)))) { allOk = true; } - if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("DeviceRemoved"), @@ -133,18 +133,17 @@ QList <QDBusObjectPath> QNetworkManagerInterface::getDevices() const return reply.value(); } -void QNetworkManagerInterface::activateConnection( const QString &serviceName, +void QNetworkManagerInterface::activateConnection( const QString &, QDBusObjectPath connectionPath, QDBusObjectPath devicePath, QDBusObjectPath specificObject) { QDBusPendingCall pendingCall = d->connectionInterface->asyncCall(QLatin1String("ActivateConnection"), - QVariant(serviceName), QVariant::fromValue(connectionPath), QVariant::fromValue(devicePath), QVariant::fromValue(specificObject)); - QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall, this); + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall); connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SIGNAL(activationFinished(QDBusPendingCallWatcher*))); } @@ -323,18 +322,31 @@ bool QNetworkManagerInterfaceDevice::setConnections() if(!isValid() ) return false; - bool allOk = false; + bool allOk = true; delete nmDBusHelper; nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper,SIGNAL(pathForStateChanged(QString,quint32)), this, SIGNAL(stateChanged(QString,quint32))); + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE), QLatin1String("StateChanged"), nmDBusHelper,SLOT(deviceStateChanged(quint32)))) { - allOk = true; + allOk = false; } + + connect(nmDBusHelper, SIGNAL(pathForConnectionsChanged(QStringList)), + this,SIGNAL(connectionsChanged(QStringList))); + + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), + QLatin1String("PropertiesChanged"), + nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) { + allOk = false; + } + return allOk; } @@ -415,18 +427,18 @@ bool QNetworkManagerInterfaceDeviceWired::setConnections() if(!isValid() ) return false; - bool allOk = false; + bool allOk = true; delete nmDBusHelper; nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)), this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>))); - if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED), QLatin1String("PropertiesChanged"), nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) { - allOk = true; + allOk = false; } return allOk; } @@ -492,44 +504,50 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections() return false; QDBusConnection dbusConnection = QDBusConnection::systemBus(); - bool allOk = false; + bool allOk = true; delete nmDBusHelper; nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)), this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>))); - connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(QString,QDBusObjectPath)), - this,SIGNAL(accessPointAdded(QString,QDBusObjectPath))); + connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(QString)), + this,SIGNAL(accessPointAdded(QString))); - connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(QString,QDBusObjectPath)), - this,SIGNAL(accessPointRemoved(QString,QDBusObjectPath))); + connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(QString)), + this,SIGNAL(accessPointRemoved(QString))); - if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), QLatin1String("AccessPointAdded"), nmDBusHelper, SLOT(slotAccessPointAdded(QDBusObjectPath)))) { - allOk = true; + allOk = false; } - if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), QLatin1String("AccessPointRemoved"), nmDBusHelper, SLOT(slotAccessPointRemoved(QDBusObjectPath)))) { - allOk = true; + allOk = false; } - if(!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), QLatin1String("PropertiesChanged"), nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>)))) { - allOk = true; + allOk = false; + } + if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), + QLatin1String("ScanDone"), + this, SLOT(scanIsDone()))) { + allOk = false; } - return allOk; } @@ -569,6 +587,89 @@ quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const return d->connectionInterface->property("WirelelessCapabilities").toUInt(); } +void QNetworkManagerInterfaceDeviceWireless::scanIsDone() +{ + Q_EMIT scanDone(); +} + +void QNetworkManagerInterfaceDeviceWireless::requestScan() +{ + d->connectionInterface->asyncCall(QLatin1String("RequestScan")); +} + + +class QNetworkManagerInterfaceDeviceModemPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfaceDeviceModemPrivate(); + d->path = ifaceDevicePath; + d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM), + QDBusConnection::systemBus(), parent); + if (!d->connectionInterface->isValid()) { + d->valid = false; + return; + } + d->valid = true; +} + +QNetworkManagerInterfaceDeviceModem::~QNetworkManagerInterfaceDeviceModem() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDeviceModem::isValid() +{ + + return d->valid; +} + +bool QNetworkManagerInterfaceDeviceModem::setConnections() +{ + if (!isValid() ) + return false; + + bool allOk = true; + + delete nmDBusHelper; + nmDBusHelper = new QNmDBusHelper(this); + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>))); + if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM), + QLatin1String("PropertiesChanged"), + nmDBusHelper,SLOT(slotDevicePropertiesChanged(QMap<QString,QVariant>))) ) { + allOk = false; + } + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceDeviceModem::connectionInterface() const +{ + return d->connectionInterface; +} + +quint32 QNetworkManagerInterfaceDeviceModem::modemCapabilities() const +{ + return d->connectionInterface->property("ModemCapabilities").toUInt(); +} + +quint32 QNetworkManagerInterfaceDeviceModem::currentCapabilities() const +{ + return d->connectionInterface->property("CurrentCapabilities").toUInt(); +} + class QNetworkManagerSettingsPrivate { public: @@ -606,12 +707,14 @@ bool QNetworkManagerSettings::isValid() bool QNetworkManagerSettings::setConnections() { - bool allOk = false; + bool allOk = true; - if (!QDBusConnection::systemBus().connect(d->path, QLatin1String(NM_DBUS_PATH_SETTINGS), - QLatin1String(NM_DBUS_IFACE_SETTINGS), QLatin1String("NewConnection"), - this, SIGNAL(newConnection(QDBusObjectPath)))) { - allOk = true; + if (!QDBusConnection::systemBus().connect(d->path, + QLatin1String(NM_DBUS_PATH_SETTINGS), + QLatin1String(NM_DBUS_IFACE_SETTINGS), + QLatin1String("NewConnection"), + this, SIGNAL(newConnection(QDBusObjectPath)))) { + allOk = false; } return allOk; @@ -623,6 +726,14 @@ QList <QDBusObjectPath> QNetworkManagerSettings::listConnections() return reply.value(); } +QString QNetworkManagerSettings::getConnectionByUuid(const QString &uuid) +{ + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(uuid); + QDBusReply<QDBusObjectPath > reply = d->connectionInterface->callWithArgumentList(QDBus::Block,QLatin1String("GetConnectionByUuid"), argumentList); + return reply.value().path(); +} + QDBusInterface *QNetworkManagerSettings::connectionInterface() const { return d->connectionInterface; @@ -676,13 +787,13 @@ bool QNetworkManagerSettingsConnection::setConnections() return false; QDBusConnection dbusConnection = QDBusConnection::systemBus(); - bool allOk = false; - if(!dbusConnection.connect(d->service, d->path, - QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Updated"), - this, SIGNAL(updated(QNmSettingsMap)))) { - allOk = true; - } else { - QDBusError error = dbusConnection.lastError(); + bool allOk = true; + if (!dbusConnection.connect(d->service, + d->path, + QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), + QLatin1String("Updated"), + this, SIGNAL(updated()))) { + allOk = false; } delete nmDBusHelper; @@ -690,12 +801,13 @@ bool QNetworkManagerSettingsConnection::setConnections() connect(nmDBusHelper, SIGNAL(pathForSettingsRemoved(QString)), this,SIGNAL(removed(QString))); - if (!dbusConnection.connect(d->service, d->path, - QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Removed"), - nmDBusHelper, SIGNAL(slotSettingsRemoved()))) { - allOk = true; + if (!dbusConnection.connect(d->service, + d->path, + QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), + QLatin1String("Removed"), + nmDBusHelper, SIGNAL(slotSettingsRemoved()))) { + allOk = false; } - return allOk; } @@ -717,9 +829,9 @@ NMDeviceType QNetworkManagerSettingsConnection::getType() d->settingsMap.value(QLatin1String("connection")).value(QLatin1String("type")).toString(); if (devType == QLatin1String("802-3-ethernet")) - return DEVICE_TYPE_802_3_ETHERNET; + return DEVICE_TYPE_ETHERNET; else if (devType == QLatin1String("802-11-wireless")) - return DEVICE_TYPE_802_11_WIRELESS; + return DEVICE_TYPE_WIFI; else return DEVICE_TYPE_UNKNOWN; } @@ -766,10 +878,10 @@ QString QNetworkManagerSettingsConnection::getMacAddress() { NMDeviceType type = getType(); - if (type == DEVICE_TYPE_802_3_ETHERNET) { + if (type == DEVICE_TYPE_ETHERNET) { return d->settingsMap.value(QLatin1String("802-3-ethernet")) .value(QLatin1String("mac-address")).toString(); - } else if (type == DEVICE_TYPE_802_11_WIRELESS) { + } else if (type == DEVICE_TYPE_WIFI) { return d->settingsMap.value(QLatin1String("802-11-wireless")) .value(QLatin1String("mac-address")).toString(); } else { @@ -779,7 +891,7 @@ QString QNetworkManagerSettingsConnection::getMacAddress() QStringList QNetworkManagerSettingsConnection::getSeenBssids() { - if (getType() == DEVICE_TYPE_802_11_WIRELESS) { + if (getType() == DEVICE_TYPE_WIFI) { return d->settingsMap.value(QLatin1String("802-11-wireless")) .value(QLatin1String("seen-bssids")).toStringList(); } else { @@ -795,7 +907,7 @@ public: bool valid; }; -QNetworkManagerConnectionActive::QNetworkManagerConnectionActive( const QString &activeConnectionObjectPath, QObject *parent) +QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString &activeConnectionObjectPath, QObject *parent) : QObject(parent), nmDBusHelper(0) { d = new QNetworkManagerConnectionActivePrivate(); @@ -827,17 +939,18 @@ bool QNetworkManagerConnectionActive::setConnections() if(!isValid() ) return false; - bool allOk = false; + bool allOk = true; delete nmDBusHelper; nmDBusHelper = new QNmDBusHelper(this); connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap<QString,QVariant>)), this,SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>))); - if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + + if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION), QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap<QString,QVariant>))) ) { - allOk = true; + nmDBusHelper,SLOT(activeConnectionPropertiesChanged(QMap<QString,QVariant>))) ) { + allOk = false; } return allOk; @@ -848,11 +961,6 @@ QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const return d->connectionInterface; } -QString QNetworkManagerConnectionActive::serviceName() const -{ - return d->connectionInterface->property("ServiceName").toString(); -} - QDBusObjectPath QNetworkManagerConnectionActive::connection() const { QVariant prop = d->connectionInterface->property("Connection"); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h index 6b15642386..11ddaf7088 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -64,31 +64,32 @@ typedef enum NMDeviceType { DEVICE_TYPE_UNKNOWN = 0, - DEVICE_TYPE_802_3_ETHERNET, - DEVICE_TYPE_802_11_WIRELESS, - DEVICE_TYPE_GSM, - DEVICE_TYPE_CDMA + DEVICE_TYPE_ETHERNET, + DEVICE_TYPE_WIFI, + DEVICE_TYPE_MODEM = 8 } NMDeviceType; typedef enum { NM_DEVICE_STATE_UNKNOWN = 0, - NM_DEVICE_STATE_UNMANAGED, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_PREPARE, - NM_DEVICE_STATE_CONFIG, - NM_DEVICE_STATE_NEED_AUTH, - NM_DEVICE_STATE_IP_CONFIG, - NM_DEVICE_STATE_ACTIVATED, - NM_DEVICE_STATE_FAILED + NM_DEVICE_STATE_UNMANAGED = 10, + NM_DEVICE_STATE_UNAVAILABLE = 20, + NM_DEVICE_STATE_DISCONNECTED = 30, + NM_DEVICE_STATE_PREPARE = 40, + NM_DEVICE_STATE_CONFIG = 50, + NM_DEVICE_STATE_NEED_AUTH = 60, + NM_DEVICE_STATE_IP_CONFIG = 70, + NM_DEVICE_STATE_ACTIVATED = 100, + NM_DEVICE_STATE_DEACTIVATING = 110, + NM_DEVICE_STATE_FAILED = 120 } NMDeviceState; typedef enum { NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0, NM_ACTIVE_CONNECTION_STATE_ACTIVATING, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED } NMActiveConnectionState; #define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" @@ -98,13 +99,14 @@ typedef enum #define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device" #define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" #define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" +#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" #define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" #define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" -#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManagerSettings" +#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" -#define NM_DBUS_IFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManagerSettings.Connection" -#define NM_DBUS_IFACE_SETTINGS "org.freedesktop.NetworkManagerSettings" +#define NM_DBUS_IFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection" +#define NM_DBUS_IFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" #define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" #define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" @@ -256,7 +258,8 @@ public: Q_SIGNALS: void stateChanged(const QString &, quint32); - + void propertiesChanged(const QString &, QMap<QString,QVariant>); + void connectionsChanged(QStringList); private: QNetworkManagerInterfaceDevicePrivate *d; QNmDBusHelper *nmDBusHelper; @@ -320,15 +323,55 @@ public: bool setConnections(); bool isValid(); + void requestScan(); Q_SIGNALS: void propertiesChanged( const QString &, QMap<QString,QVariant>); - void accessPointAdded(const QString &,QDBusObjectPath); - void accessPointRemoved(const QString &,QDBusObjectPath); + void accessPointAdded(const QString &); + void accessPointRemoved(const QString &); + void scanDone(); +private Q_SLOTS: + void scanIsDone(); private: QNetworkManagerInterfaceDeviceWirelessPrivate *d; QNmDBusHelper *nmDBusHelper; }; +class QNetworkManagerInterfaceDeviceModemPrivate; +class QNetworkManagerInterfaceDeviceModem : public QObject +{ + Q_OBJECT + +public: + + enum ModemCapability { + None = 0x0, + Pots = 0x1, + Cmda_Edvo = 0x2, + Gsm_Umts = 0x4, + Lte = 0x08 + }; + + explicit QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath, + QObject *parent = 0); + ~QNetworkManagerInterfaceDeviceModem(); + + QDBusObjectPath path() const; + QDBusInterface *connectionInterface() const; + + bool setConnections(); + bool isValid(); + + quint32 modemCapabilities() const; + quint32 currentCapabilities() const; + +Q_SIGNALS: + void propertiesChanged( const QString &, QMap<QString,QVariant>); +private: + QNetworkManagerInterfaceDeviceModemPrivate *d; + QNmDBusHelper *nmDBusHelper; +}; + + class QNetworkManagerSettingsPrivate; class QNetworkManagerSettings : public QObject { @@ -341,6 +384,7 @@ public: QDBusInterface *connectionInterface() const; QList <QDBusObjectPath> listConnections(); + QString getConnectionByUuid(const QString &uuid); bool setConnections(); bool isValid(); @@ -375,7 +419,7 @@ public: Q_SIGNALS: - void updated(const QNmSettingsMap &settings); + void updated(); void removed(const QString &path); private: diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp index a2e055d784..0decfd78b9 100644 --- a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp +++ b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp @@ -60,7 +60,7 @@ QNmDBusHelper::~QNmDBusHelper() void QNmDBusHelper::deviceStateChanged(quint32 state) { QDBusMessage msg = this->message(); - if(state == NM_DEVICE_STATE_ACTIVATED + if (state == NM_DEVICE_STATE_ACTIVATED || state == NM_DEVICE_STATE_DISCONNECTED || state == NM_DEVICE_STATE_UNAVAILABLE || state == NM_DEVICE_STATE_FAILED) { @@ -70,18 +70,14 @@ void QNmDBusHelper::deviceStateChanged(quint32 state) void QNmDBusHelper::slotAccessPointAdded(QDBusObjectPath path) { - if(path.path().length() > 2) { - QDBusMessage msg = this->message(); - emit pathForAccessPointAdded(msg.path(), path); - } + if (path.path().length() > 2) + emit pathForAccessPointAdded(path.path()); } void QNmDBusHelper::slotAccessPointRemoved(QDBusObjectPath path) { - if(path.path().length() > 2) { - QDBusMessage msg = this->message(); - emit pathForAccessPointRemoved(msg.path(), path); - } + if (path.path().length() > 2) + emit pathForAccessPointRemoved(path.path()); } void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map) @@ -90,23 +86,29 @@ void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map) QMapIterator<QString, QVariant> i(map); while (i.hasNext()) { i.next(); - if( i.key() == "State") { //state only applies to device interfaces + if (i.key() == QStringLiteral("State")) { quint32 state = i.value().toUInt(); - if( state == NM_DEVICE_STATE_ACTIVATED + if (state == NM_DEVICE_STATE_ACTIVATED || state == NM_DEVICE_STATE_DISCONNECTED || state == NM_DEVICE_STATE_UNAVAILABLE || state == NM_DEVICE_STATE_FAILED) { - emit pathForPropertiesChanged( msg.path(), map); + emit pathForPropertiesChanged(msg.path(), map); } - } else if( i.key() == "ActiveAccessPoint") { + } else if (i.key() == QStringLiteral("ActiveAccessPoint")) { emit pathForPropertiesChanged(msg.path(), map); - // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().value<QDBusObjectPath>().path(); - // } else if( i.key() == "Strength") - // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().toUInt(); - // else - // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value(); - } else if (i.key() == "ActiveConnections") { + } else if (i.key() == QStringLiteral("ActiveConnections")) { emit pathForPropertiesChanged(msg.path(), map); + } else if (i.key() == QStringLiteral("AvailableConnections")) { + const QDBusArgument &dbusArgs = i.value().value<QDBusArgument>(); + QDBusObjectPath path; + QStringList paths; + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) { + dbusArgs >> path; + paths << path.path(); + } + dbusArgs.endArray(); + emit pathForConnectionsChanged(paths); } } } @@ -117,6 +119,22 @@ void QNmDBusHelper::slotSettingsRemoved() emit pathForSettingsRemoved(msg.path()); } +void QNmDBusHelper::activeConnectionPropertiesChanged(QMap<QString,QVariant> map) +{ + QDBusMessage msg = this->message(); + QMapIterator<QString, QVariant> i(map); + while (i.hasNext()) { + i.next(); + if (i.key() == QStringLiteral("State")) { + quint32 state = i.value().toUInt(); + if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED + || state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + emit pathForPropertiesChanged(msg.path(), map); + } + } + } +} + QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.h b/src/plugins/bearer/networkmanager/qnmdbushelper.h index cd5e8a3494..e224af87f1 100644 --- a/src/plugins/bearer/networkmanager/qnmdbushelper.h +++ b/src/plugins/bearer/networkmanager/qnmdbushelper.h @@ -51,17 +51,19 @@ class QNmDBusHelper: public QObject, protected QDBusContext public slots: void deviceStateChanged(quint32); - void slotAccessPointAdded( QDBusObjectPath ); - void slotAccessPointRemoved( QDBusObjectPath ); - void slotPropertiesChanged( QMap<QString,QVariant>); + void slotAccessPointAdded(QDBusObjectPath); + void slotAccessPointRemoved(QDBusObjectPath); + void slotPropertiesChanged(QMap<QString,QVariant>); void slotSettingsRemoved(); + void activeConnectionPropertiesChanged(QMap<QString,QVariant>); Q_SIGNALS: void pathForStateChanged(const QString &, quint32); - void pathForAccessPointAdded(const QString &, QDBusObjectPath ); - void pathForAccessPointRemoved(const QString &, QDBusObjectPath ); + void pathForAccessPointAdded(const QString &); + void pathForAccessPointRemoved(const QString &); void pathForPropertiesChanged(const QString &, QMap<QString,QVariant>); void pathForSettingsRemoved(const QString &); + void pathForConnectionsChanged(const QStringList &pathsList); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h index 96dbd23695..3d1c95a0b4 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h @@ -70,6 +70,7 @@ namespace QCocoaAccessible { */ NSString *macRole(QAccessibleInterface *interface); +NSString *macSubrole(QAccessibleInterface *interface); bool shouldBeIgnored(QAccessibleInterface *interface); NSArray *unignoredChildren(QAccessibleInterface *interface); NSString *getTranslatedAction(const QString &qtAction); diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 1ade985b79..00baeddb39 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -162,7 +162,7 @@ static void populateRoleMap() } /* - Returns a Mac accessibility role for the given interface, or + Returns a Cocoa accessibility role for the given interface, or NSAccessibilityUnknownRole if no role mapping is found. */ NSString *macRole(QAccessibleInterface *interface) @@ -190,13 +190,24 @@ NSString *macRole(QAccessibleInterface *interface) } /* - Mac accessibility supports ignoring elements, which means that + Returns a Cocoa sub role for the given interface. +*/ +NSString *macSubrole(QAccessibleInterface *interface) +{ + QAccessible::State s = interface->state(); + if (s.searchEdit) + return NSAccessibilitySearchFieldSubrole; + return nil; +} + +/* + Cocoa accessibility supports ignoring elements, which means that the elements are still present in the accessibility tree but is not used by the screen reader. */ bool shouldBeIgnored(QAccessibleInterface *interface) { - // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen + // Cocoa accessibility does not have an attribute that corresponds to the Invisible/Offscreen // state. Ignore interfaces with those flags set. const QAccessible::State state = interface->state(); if (state.invisible || diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 9f803e411d..dd76852b62 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -135,6 +135,7 @@ defaultAttributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, NSAccessibilityRoleDescriptionAttribute, + NSAccessibilitySubroleAttribute, NSAccessibilityChildrenAttribute, NSAccessibilityFocusedAttribute, NSAccessibilityParentAttribute, @@ -221,6 +222,8 @@ if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) { return role; + } else if ([attribute isEqualToString:NSAccessibilitySubroleAttribute]) { + return QCocoaAccessible::macSubrole(iface); } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { return NSAccessibilityRoleDescription(role, nil); } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 326628a261..9f7609f24c 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -396,7 +396,7 @@ static void cleanupCocoaApplicationDelegate() */ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/); - return NO; + return YES; } - (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 2c8d391d2b..47b52c9fdd 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); - dragBoard.setMimeData(m_drag->mimeData()); + dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest); NSPoint event_location = [m_lastEvent locationInWindow]; NSPoint local_point = [m_lastView convertPoint:event_location fromView:nil]; diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index 7322025df6..2101b68769 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -391,6 +391,9 @@ void QCocoaPrintDevice::loadDuplexModes() const // If still no result, or not added in PPD, then add None if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) m_duplexModes.append(QPrint::DuplexNone); + // If have both modes, then can support DuplexAuto + if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide)) + m_duplexModes.append(QPrint::DuplexAuto); m_haveDuplexModes = true; } diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index 83c960d931..e449fd37d6 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -187,6 +187,14 @@ void QCocoaSystemTrayIcon::cleanup() m_sys = 0; } +static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); } +static QList<QSize> sortByHeight(const QList<QSize> sizes) +{ + QList<QSize> sorted = sizes; + std::sort(sorted.begin(), sorted.end(), heightCompareFunction); + return sorted; +} + void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) { if (!m_sys) @@ -196,16 +204,62 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; + // The reccomended maximum title bar icon height is 18 points + // (device independent pixels). The menu height on past and + // current OS X versions is 22 points. Provide some future-proofing + // by deriving the icon height from the menu height. + const int padding = 4; + const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + const int maxImageHeight = menuHeight - padding; + + // Select pixmap based on the device pixel height. Ideally we would use + // the devicePixelRatio of the target screen, but that value is not + // known until draw time. Use qApp->devicePixelRatio, which returns the + // devicePixelRatio for the "best" screen on the system. + qreal devicePixelRatio = qApp->devicePixelRatio(); + const int maxPixmapHeight = maxImageHeight * devicePixelRatio; + const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal; + QSize selectedSize; + Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) { + // Select a pixmap based on the height. We want the largest pixmap + // with a height smaller or equal to maxPixmapHeight. The pixmap + // may rectangular; assume it has a reasonable size. If there is + // not suitable pixmap use the smallest one the icon can provide. + if (size.height() <= maxPixmapHeight) { + selectedSize = size; + } else { + if (!selectedSize.isValid()) + selectedSize = size; + break; + } + } - QPixmap pm = m_sys->item->icon.pixmap(QSize(scale, scale), - menuVisible ? QIcon::Selected : QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); + QPixmap pixmap = icon.pixmap(selectedSize, mode); + + // Draw a low-resolution icon if there is not enough pixels for a retina + // icon. This prevents showing a small icon on retina displays. + if (devicePixelRatio > 1.0 && selectedSize.height() < maxPixmapHeight / 2) + devicePixelRatio = 1.0; + + // Scale large pixmaps to fit the available menu bar area. + if (pixmap.height() > maxPixmapHeight) + pixmap = pixmap.scaledToHeight(maxPixmapHeight, Qt::SmoothTransformation); + + // The icon will be stretched over the full height of the menu bar + // therefore we create a second pixmap which has the full height + QSize fullHeightSize(!pixmap.isNull() ? pixmap.width(): + menuHeight * devicePixelRatio, + menuHeight * devicePixelRatio); + QPixmap fullHeightPixmap(fullHeightSize); + fullHeightPixmap.fill(Qt::transparent); + if (!pixmap.isNull()) { + QPainter p(&fullHeightPixmap); + QRect r = pixmap.rect(); + r.moveCenter(fullHeightPixmap.rect().center()); + p.drawPixmap(r, pixmap); } - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); + + NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap)); [(NSImageView*)[[m_sys->item item] view] setImage: nsimage]; [nsimage release]; } @@ -327,18 +381,7 @@ QT_END_NAMESPACE Q_UNUSED(notification); down = NO; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; - - QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); - } - NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); - [self setImage: nsaltimage]; - [nsaltimage release]; - + parent->systray->updateIcon(parent->icon); parent->menuVisible = false; [self setNeedsDisplay:YES]; @@ -350,18 +393,7 @@ QT_END_NAMESPACE int clickCount = [mouseEvent clickCount]; [self setNeedsDisplay:YES]; - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; - - QPixmap pm = parent->icon.pixmap(QSize(scale, scale), - parent->menuVisible ? QIcon::Selected : QIcon::Normal); - if (pm.isNull()) { - pm = QPixmap(scale, scale); - pm.fill(Qt::transparent); - } - NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); - [self setImage: nsaltimage]; - [nsaltimage release]; + parent->systray->updateIcon(parent->icon); if (clickCount == 2) { [self menuTrackingDone:nil]; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 9259c2c772..3366e5bc3c 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -699,7 +699,7 @@ void QCocoaWindow::setVisible(bool visible) exposeWindow(); if (m_nsWindow) { - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // setWindowState might have been called while the window was hidden and // will not change the NSWindow state in that case. Sync up here: @@ -1009,9 +1009,12 @@ void QCocoaWindow::raise() [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; } else { [m_nsWindow orderFront: m_nsWindow]; - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); + static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); + if (raiseProcess) { + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); + } } } } diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h index ba7a2e1aac..c5b6224545 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.h +++ b/src/plugins/platforms/cocoa/qmacclipboard.h @@ -43,15 +43,25 @@ QT_BEGIN_NAMESPACE +class QMacMimeData; class QMacPasteboard { +public: + enum DataRequestType { EagerRequest, LazyRequest }; +private: struct Promise { Promise() : itemId(0), convertor(0) { } - Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { } + + static Promise eagerPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0); + static Promise lazyPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0); + Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt); + int itemId, offset; QMacInternalPasteboardMime *convertor; QString mime; - QVariant data; + QPointer<QMacMimeData> mimeData; + QVariant variantData; + DataRequestType dataRequestType; }; QList<Promise> promises; @@ -72,7 +82,8 @@ public: PasteboardRef pasteBoard() const; QMimeData *mimeData() const; - void setMimeData(QMimeData *mime); + + void setMimeData(QMimeData *mime, DataRequestType dataRequestType = EagerRequest); QStringList formats() const; bool hasFormat(const QString &format) const; diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index 65665ef790..b235625921 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -64,6 +64,26 @@ QT_BEGIN_NAMESPACE QMacPasteboard code *****************************************************************************/ +class QMacMimeData : public QMimeData +{ +public: + QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); } +private: + QMacMimeData(); +}; + +QMacPasteboard::Promise::Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt) + : itemId(itemId), offset(o), convertor(c), mime(m), dataRequestType(drt) +{ + // Request the data from the application immediately for eager requests. + if (dataRequestType == QMacPasteboard::EagerRequest) { + variantData = md->variantData(m); + mimeData = 0; + } else { + mimeData = md; + } +} + QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt) { mac_mime_source = false; @@ -103,6 +123,11 @@ QMacPasteboard::~QMacPasteboard() // commit all promises for paste after exit close for (int i = 0; i < promises.count(); ++i) { const Promise &promise = promises.at(i); + // At this point app teardown has started and control is somewhere in the Q[Core]Application + // destructor. Skip "lazy" promises where the application has not provided data; + // the application will generally not be in a state to provide it. + if (promise.dataRequestType == LazyRequest) + continue; QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime)); NSInteger pbItemId = promise.itemId; promiseKeeper(paste, reinterpret_cast<PasteboardItemID>(pbItemId), flavor, this); @@ -155,7 +180,17 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset); #endif - QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString); + // Get the promise data. If this is a "lazy" promise call variantData() + // to request the data from the application. + QVariant promiseData; + if (promise.dataRequestType == LazyRequest) { + if (!promise.mimeData.isNull()) + promiseData = promise.mimeData->variantData(promise.mime); + } else { + promiseData = promise.variantData; + } + + QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promiseData, flavorAsQString); if (md.size() <= promise.offset) return cantGetFlavorErr; const QByteArray &ba = md[promise.offset]; @@ -266,16 +301,8 @@ QMimeData return mime; } -class QMacMimeData : public QMimeData -{ -public: - QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); } -private: - QMacMimeData(); -}; - void -QMacPasteboard::setMimeData(QMimeData *mime_src) +QMacPasteboard::setMimeData(QMimeData *mime_src, DataRequestType dataRequestType) { if (!paste) return; @@ -312,12 +339,17 @@ QMacPasteboard::setMimeData(QMimeData *mime_src) continue; QString flavor(c->flavorFor(mimeType)); if (!flavor.isEmpty()) { - QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType); + QMacMimeData *mimeData = static_cast<QMacMimeData*>(mime_src); int numItems = c->count(mime_src); for (int item = 0; item < numItems; ++item) { const NSInteger itemID = item+1; //id starts at 1 - promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item)); + //QMacPasteboard::Promise promise = (dataRequestType == QMacPasteboard::EagerRequest) ? + // QMacPasteboard::Promise::eagerPromise(itemID, c, mimeType, mimeData, item) : + // QMacPasteboard::Promise::lazyPromise(itemID, c, mimeType, mimeData, item); + + QMacPasteboard::Promise promise(itemID, c, mimeType, mimeData, item, dataRequestType); + promises.append(promise); PasteboardPutItemFlavor(paste, reinterpret_cast<PasteboardItemID>(itemID), QCFString(flavor), 0, kPasteboardFlavorNoFlags); #ifdef DEBUG_PASTEBOARD qDebug(" - adding %d %s [%s] <%s> [%d]", diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 06680228bc..ca98f6cec3 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -361,8 +361,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; // Send a geometry change event to Qt, if it's ready to handle events if (!m_platformWindow->m_inConstructor) { QWindowSystemInterface::handleGeometryChange(m_window, geometry); - m_platformWindow->updateExposedGeometry(); - QWindowSystemInterface::flushWindowSystemEvents(); + // Do not send incorrect exposes in case the window is not even visible yet. + // We might get here as a result of a resize() from QWidget's show(), for instance. + if (m_platformWindow->window()->isVisible()) { + m_platformWindow->updateExposedGeometry(); + QWindowSystemInterface::flushWindowSystemEvents(); + } } } @@ -420,10 +424,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; #pragma clang diagnostic ignored "-Wobjc-method-access" enum { NSWindowOcclusionStateVisible = 1UL << 1 }; #endif + // Older versions managed in -[QNSView viewDidMoveToWindow]. + // Support QWidgetAction in NSMenu. Mavericks only sends this notification. + // Ideally we should support this in Qt as well, in order to disable animations + // when the window is occluded. if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) m_platformWindow->exposeWindow(); - else - m_platformWindow->obscureWindow(); #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 #pragma clang diagnostic pop #endif @@ -686,7 +692,23 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_platformWindow->m_forwardWindow = 0; } - [targetView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; + NSPoint globalPos = [NSEvent mouseLocation]; + + if ([self.window parentWindow] + && (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) { + // QToolBar can be implemented as a child window on top of its main window + // (with a borderless NSWindow). If an option "unified toolbar" set on the main window, + // it's possible to drag such a window using this toolbar. + // While handling mouse drag events, QToolBar moves the window (QWidget::move). + // In such a combination [NSEvent mouseLocation] is very different from the + // real event location and as a result a window will move chaotically. + NSPoint winPoint = [theEvent locationInWindow]; + NSRect tmpRect = NSMakeRect(winPoint.x, winPoint.y, 1., 1.); + tmpRect = [[theEvent window] convertRectToScreen:tmpRect]; + globalPos = tmpRect.origin; + } + + [targetView convertFromScreen:globalPos toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; ulong timestamp = [theEvent timestamp] * 1000; QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); @@ -699,6 +721,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; - (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent { // get m_buttons in sync + // Don't send frme strut events if we are in the middle of a mouse drag. + if (m_buttons != Qt::NoButton) + return; + NSEventType ty = [theEvent type]; switch (ty) { case NSLeftMouseDown: @@ -710,6 +736,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; case NSRightMouseDown: m_frameStrutButtons |= Qt::RightButton; break; + case NSLeftMouseDragged: + m_frameStrutButtons |= Qt::LeftButton; + break; + case NSRightMouseDragged: + m_frameStrutButtons |= Qt::RightButton; + break; case NSRightMouseUp: m_frameStrutButtons &= ~Qt::RightButton; break; @@ -1337,10 +1369,6 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph); - - if (momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled || momentumPhase == NSEventPhaseNone) { - currentWheelModifiers = Qt::NoModifier; - } } else #endif { @@ -1806,6 +1834,19 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin return NO; } +- (BOOL)wantsPeriodicDraggingUpdates +{ + // From the documentation: + // + // "If the destination returns NO, these messages are sent only when the mouse moves + // or a modifier flag changes. Otherwise the destination gets the default behavior, + // where it receives periodic dragging-updated messages even if nothing changes." + // + // We do not want these constant drag update events while mouse is stationary, + // since we do all animations (autoscroll) with timers. + return NO; +} + - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender { return [self handleDrag : sender]; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index fb968f31e9..f684fef233 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -457,9 +457,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; case PPK_CustomBase: break; - case PPK_Duplex: - // TODO Add support using PMSetDuplex / PMGetDuplex - break; case PPK_FontEmbedding: break; case PPK_PageOrder: @@ -503,6 +500,29 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_DocumentName: PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString())); break; + case PPK_Duplex: { + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); + if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode)) + break; + switch (mode) { + case QPrinter::DuplexNone: + PMSetDuplex(d->settings(), kPMDuplexNone); + break; + case QPrinter::DuplexAuto: + PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble); + break; + case QPrinter::DuplexLongSide: + PMSetDuplex(d->settings(), kPMDuplexNoTumble); + break; + case QPrinter::DuplexShortSide: + PMSetDuplex(d->settings(), kPMDuplexTumble); + break; + default: + // Don't change + break; + } + break; + } case PPK_FullPage: if (value.toBool()) d->m_pageLayout.setMode(QPageLayout::FullPageMode); @@ -602,10 +622,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CustomBase: // Special case, leave null break; - case PPK_Duplex: - // TODO Add support using PMSetDuplex / PMGetDuplex - ret = QPrinter::DuplexNone; - break; case PPK_FontEmbedding: ret = false; break; @@ -647,6 +663,23 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const ret = QCFString::toQString(name); break; } + case PPK_Duplex: { + PMDuplexMode mode = kPMDuplexNone; + PMGetDuplex(d->settings(), &mode); + switch (mode) { + case kPMDuplexNoTumble: + ret = QPrinter::DuplexLongSide; + break; + case kPMDuplexTumble: + ret = QPrinter::DuplexShortSide; + break; + case kPMDuplexNone: + default: + ret = QPrinter::DuplexNone; + break; + } + break; + } case PPK_FullPage: ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index 821599d113..ce7dfe2606 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -259,10 +259,16 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline() NSArray *arguments = [[NSProcessInfo processInfo] arguments]; int argc = arguments.count; char **argv = new char*[argc]; + for (int i = 0; i < argc; ++i) { NSString *arg = [arguments objectAtIndex:i]; - argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]])); - strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]); + + NSStringEncoding cStringEncoding = [NSString defaultCStringEncoding]; + unsigned int bufferSize = [arg lengthOfBytesUsingEncoding:cStringEncoding] + 1; + argv[i] = reinterpret_cast<char *>(malloc(bufferSize)); + + if (![arg getCString:argv[i] maxLength:bufferSize encoding:cStringEncoding]) + qFatal("Could not convert argv[%d] to C string", i); } int exitCode = qtmn(argc, argv); diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm index 331c38460c..63b6827ad3 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.mm +++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm @@ -152,6 +152,9 @@ if (state.disabled) traits |= UIAccessibilityTraitNotEnabled; + if (state.searchEdit) + traits |= UIAccessibilityTraitSearchField; + if (iface->role() == QAccessible::Button) traits |= UIAccessibilityTraitButton; diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index d2460e0640..f5d6c140bf 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -48,6 +48,13 @@ #include <QtCore/QDebug> #include <QtCore/QScopedArrayPointer> +static void initResources() +{ +#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG) + Q_INIT_RESOURCE(cursors); +#endif +} + QT_BEGIN_NAMESPACE Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0); @@ -568,6 +575,11 @@ QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c) return it.value(); } +QWindowsCursor::QWindowsCursor() +{ + initResources(); +} + /*! \brief Set a cursor on a window. diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index c8e1df3f4d..a024646553 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -91,7 +91,7 @@ public: CursorSuppressed // Cursor suppressed by touch interaction (Windows 8). }; - QWindowsCursor() {} + QWindowsCursor(); void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE; QPoint pos() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index dd9b9de0b6..8a80729354 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1149,6 +1149,13 @@ void QWindowsWindow::updateTransientParent() const #endif // !Q_OS_WINCE } +static inline bool testShowWithoutActivating(const QWindow *window) +{ + // QWidget-attribute Qt::WA_ShowWithoutActivating . + const QVariant showWithoutActivating = window->property("_q_showWithoutActivating"); + return showWithoutActivating.isValid() && showWithoutActivating.toBool(); +} + // partially from QWidgetPrivate::show_sys() void QWindowsWindow::show_sys() const { @@ -1180,7 +1187,7 @@ void QWindowsWindow::show_sys() const } // Qt::WindowMaximized } // !Qt::WindowMinimized } - if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool) + if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w)) sm = SW_SHOWNOACTIVATE; if (w->windowState() & Qt::WindowMaximized) diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index fc3443aba5..dae3a79628 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -910,6 +910,18 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const if (qtKey == baseQtKey || qtKey == 0) continue; + // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +, + // but Ctrl++ is more specific than +, so we should skip the last one + bool ambiguous = false; + foreach (int shortcut, result) { + if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) { + ambiguous = true; + break; + } + } + if (ambiguous) + continue; + result += (qtKey + mods); } } diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 724ff5b98b..d7cd18f1d1 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -85,6 +85,12 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v // Get the named page size from the printer if supported d->setPageSize(d->m_printDevice.supportedPageSize(value.toString())); break; + case PPK_Duplex: { + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); + if (mode != d->duplex && d->m_printDevice.supportedDuplexModes().contains(mode)) + d->duplex = mode; + break; + } case PPK_PrinterName: d->changePrinter(value.toString()); break; diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index 75e8a8bf26..7a6acf8b78 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -387,6 +387,9 @@ void QPpdPrintDevice::loadDuplexModes() const // If still no result, or not added in PPD, then add None if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) m_duplexModes.append(QPrint::DuplexNone); + // If have both modes, then can support DuplexAuto + if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide)) + m_duplexModes.append(QPrint::DuplexAuto); m_haveDuplexModes = true; } diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index 1a6f40722d..a0a549da6f 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -271,7 +271,7 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, const qreal rightMargin = physicalWidth - leftMargin - printableWidth; const qreal bottomMargin = physicalHeight - topMargin - printableHeight; margins = QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin); - ReleaseDC(NULL, pDC); + DeleteDC(pDC); } return margins; } @@ -280,11 +280,11 @@ void QWindowsPrintDevice::loadResolutions() const { DWORD resCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, NULL, NULL); if (int(resCount) > 0) { - QScopedArrayPointer<LONG> resolutions(new LONG[resCount*sizeof(LONG)]); + QScopedArrayPointer<LONG> resolutions(new LONG[resCount*2]); // Get the details and match the default paper size if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, (LPWSTR)resolutions.data(), NULL) == resCount) { - for (int i = 0; i < int(resCount); ++i) - m_resolutions.append(resolutions[i]); + for (int i = 0; i < int(resCount * 2); i += 2) + m_resolutions.append(resolutions[i+1]); } } m_haveResolutions = true; @@ -378,6 +378,7 @@ void QWindowsPrintDevice::loadDuplexModes() const DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL); if (int(duplex) == 1) { // TODO Assume if duplex flag supports both modes + m_duplexModes.append(QPrint::DuplexAuto); m_duplexModes.append(QPrint::DuplexLongSide); m_duplexModes.append(QPrint::DuplexShortSide); } |