src/systeminfo/qsysteminfo_mac.mm
changeset 0 876b1a06bc25
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/systeminfo/qsysteminfo_mac.mm	Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,1803 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qsysteminfo.h"
+#include "qsysteminfo_mac_p.h"
+
+#include <QStringList>
+#include <QSize>
+#include <QFile>
+#include <QTextStream>
+#include <QLocale>
+#include <QLibraryInfo>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QDebug>
+#include <QSettings>
+#include <QSysInfo>
+#include <QNetworkInterface>
+#include <QList>
+#include <QSettings>
+#include <QDir>
+#include <QNetworkInterface>
+#include <QString>
+#include <QHostInfo>
+
+#include <locale.h>
+
+#include <IOBluetooth/IOBluetooth.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <CoreFoundation/CFArray.h>
+#include <CoreFoundation/CFArray.h>
+#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFNotificationCenter.h>
+#include <IOKit/graphics/IOGraphicsLib.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFLocale.h>
+#include <ScreenSaver/ScreenSaverDefaults.h>
+#include <dns_sd.h>
+
+#include <QTKit/QTKit.h>
+
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/pwr_mgt/IOPM.h>
+#include <IOKit/ps/IOPSKeys.h>
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/IOTypes.h>
+
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IOCDMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+#include <IOKit/storage/IOBlockStorageDevice.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/hid/IOHIDLib.h>
+
+#include <CoreServices/CoreServices.h>
+
+#include <qabstracteventdispatcher.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QEventLoop>
+
+#ifdef MAC_SDK_10_6
+#include <CoreLocation/CLLocation.h>
+#include <CoreLocation/CLLocationManager.h>
+#include <CoreWLAN/CWInterface.h>
+#include <CoreWLAN/CWGlobals.h>
+#else
+// 10.5 sdk is broken for this:
+#include </Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/OSServices.framework/Headers/Power.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <math.h>
+#include <net/if.h>
+
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+
+static QString stringFromCFString(CFStringRef value) {
+    QString retVal;
+    if(CFStringGetLength(value) > 1) {
+        CFIndex maxLength = 2 * CFStringGetLength(value) + 1/*zero term*/; // max UTF8
+        char *cstring = new char[maxLength];
+        if (CFStringGetCString(CFStringRef(value), cstring, maxLength, kCFStringEncodingUTF8)) {
+            retVal = QString::fromUtf8(cstring);
+        }
+        delete cstring;
+    }
+    return retVal;
+}
+
+inline CFStringRef qstringToCFStringRef(const QString &string)
+{
+    return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+                                        string.length());
+}
+
+inline QString nsstringToQString(const NSString *nsstr)
+{ return QString([nsstr UTF8String]);}
+
+inline NSString *qstringToNSString(const QString &qstr)
+{ return [reinterpret_cast<const NSString *>(qstringToCFStringRef(qstr)) autorelease]; }
+
+inline QStringList nsarrayToQStringList(void *nsarray)
+{
+    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+    QStringList result;
+    NSArray *array = static_cast<NSArray *>(nsarray);
+    for (NSUInteger i=0; i<[array count]; ++i)
+        result << nsstringToQString([array objectAtIndex:i]);
+    [autoreleasepool release];
+    return result;
+}
+
+bool hasIOServiceMatching(const QString &classstr)
+{
+    io_iterator_t ioIterator = NULL;
+    IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceNameMatching(classstr.toAscii()), &ioIterator);
+    if(ioIterator) {
+        return true;
+    }
+    return false;
+}
+
+
+
+#ifdef MAC_SDK_10_6
+
+@interface QtMNSListener : NSObject
+{
+    NSNotificationCenter *center;
+    CWInterface * currentInterface;
+}
+- (void)notificationHandler:(NSNotification *)notification;
+- (void)remove;
+@end
+
+@implementation QtMNSListener
+- (id) init
+{
+   [super init];
+    center = [NSNotificationCenter defaultCenter];
+    currentInterface = [CWInterface interfaceWithName:nil];
+
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWModeDidChangeNotification object:nil];
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWSSIDDidChangeNotification object:nil];
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWBSSIDDidChangeNotification object:nil];
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWCountryCodeDidChangeNotification object:nil];
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil];
+    [center addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil];
+
+
+    return self;
+}
+
+-(void)dealloc
+{
+   [center release];
+   [super dealloc];
+}
+
+-(void)remove
+{
+    [center removeObserver:self];
+}
+
+- (void)notificationHandler:(NSNotification *)notification
+{
+    QTM_NAMESPACE::QSystemNetworkInfoPrivate::instance()->wifiNetworkChanged( nsstringToQString([notification name]), nsstringToQString([[notification object]name]));
+}
+@end
+
+
+@interface QtMLangListener : NSObject
+{
+    NSNotificationCenter *center;
+    QString currentLanguage;
+}
+- (void)languageHandler;//:(NSNotification *)notification;
+- (void)remove;
+- (void)getCurrentLanguage;
+@end
+
+
+
+@implementation QtMLangListener
+- (id) init
+{
+    [super init];
+    center = [NSNotificationCenter defaultCenter];
+    [center addObserver:self selector:@selector(languageHandler:) name:NSCurrentLocaleDidChangeNotification object:nil];
+    [self getCurrentLanguage];
+    return self;
+}
+
+-(void)dealloc
+{
+    [center release];
+    [super dealloc];
+}
+
+-(void)remove
+{
+    [center removeObserver:self];
+}
+
+- (void)getCurrentLanguage
+{
+    NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
+    NSArray* languages = [defs objectForKey:@"AppleLanguages"];
+    NSString* language = [languages objectAtIndex:0];
+
+    QString langString = nsstringToQString(language);
+    if(langString != currentLanguage) {
+        if(!currentLanguage.isEmpty())
+            QTM_NAMESPACE::QSystemInfoPrivate::instance()->languageChanged(currentLanguage);
+        currentLanguage = langString;
+    }
+}
+
+- (void)languageHandler;//:(NSNotification *)notification
+{
+    [self getCurrentLanguage];
+}
+@end
+
+
+@interface RemoteDeviceRSSIHostControllerDelegate : NSObject
+{
+}
+// See IOBluetoothHostControllerDelegate
+- (void)readRSSIForDeviceComplete:(id)controller device:(IOBluetoothDevice*)device info:(BluetoothHCIRSSIInfo*)info error:(IOReturn)error;
+@end
+
+@implementation RemoteDeviceRSSIHostControllerDelegate
+- (id) init
+{
+   [super init];
+   return self;
+}
+
+- (void)readRSSIForDeviceComplete:(id)controller device:(IOBluetoothDevice*)device info:(BluetoothHCIRSSIInfo*)info error:(IOReturn)error
+{
+    Q_UNUSED(controller);
+    Q_UNUSED(device);
+
+    if ((error != kIOReturnSuccess) || (info == NULL)) {
+        qWarning() << "ERROR: readRSSIForDeviceComplete return error";
+
+    } else if (info->handle == kBluetoothConnectionHandleNone) {
+        qWarning() << "ERROR: readRSSIForDeviceComplete no connection";
+    } else {
+        NSLog(@"Rssi value: %@", info->RSSIValue);
+    }
+}
+@end
+#endif
+NSObject* delegate;
+
+QTM_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QSystemDeviceInfoPrivate, qsystemDeviceInfoPrivate)
+
+QSystemInfoPrivate *QSystemInfoPrivate::self = 0;
+
+QSystemInfoPrivate::QSystemInfoPrivate(QObject *parent)
+ : QObject(parent),langloopThread(0),langThreadOk(0)
+{
+    if(!self)
+        self = this;
+}
+
+QSystemInfoPrivate::~QSystemInfoPrivate()
+{
+    if(langThreadOk && langloopThread->isRunning()) {
+        langloopThread->stop();
+    }
+}
+
+QString QSystemInfoPrivate::currentLanguage() const
+{
+ QString lang = QLocale::system().name().left(2);
+    if(lang.isEmpty() || lang == QLatin1String("C")) {
+        lang = QLatin1String("en");
+    }
+    return lang;
+}
+
+QStringList QSystemInfoPrivate::availableLanguages() const
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
+    NSArray* languages = [defs objectForKey:@"AppleLanguages"];
+    QStringList langList = nsarrayToQStringList(languages);
+
+    QStringList returnList;
+    for(int i = 0; i < langList.count(); i++) {
+     QString language = langList.at(i).left(2);
+     if(!returnList.contains(language))
+         returnList << language;
+    }
+    [pool drain];
+    return returnList;
+}
+
+void QSystemInfoPrivate::languageChanged(const QString &lang)
+{
+    Q_EMIT currentLanguageChanged(lang);
+}
+
+void QSystemInfoPrivate::connectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(currentLanguageChanged(QString))) {
+        langloopThread = new QLangLoopThread(this);
+        langloopThread->start();
+        langThreadOk = true;
+    }
+}
+
+void QSystemInfoPrivate::disconnectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(currentLanguageChanged(QString))) {
+        if(langloopThread->isRunning()) {
+            langloopThread->stop();
+        }
+    }
+}
+
+QString QSystemInfoPrivate::version(QSystemInfo::Version type,  const QString &parameter)
+{
+    Q_UNUSED(parameter);
+    QString errorStr = "Not Available";
+    bool useDate = false;
+    if(parameter == QLatin1String("versionDate")) {
+        useDate = true;
+    }
+    switch(type) {
+    case QSystemInfo::Os:
+        {
+            return nsstringToQString([[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]);
+        }
+        break;
+    case QSystemInfo::QtCore:
+       return  qVersion();
+       break;
+   case QSystemInfo::Firmware:
+       {
+           return QSystemDeviceInfoPrivate::model();
+       }
+       break;
+    };
+  return errorStr;
+}
+
+
+QString QSystemInfoPrivate::currentCountryCode() const
+{
+    return QLocale::system().name().mid(3,2);
+}
+
+
+bool QSystemInfoPrivate::hasFeatureSupported(QSystemInfo::Feature feature)
+{
+    bool featureSupported = false;
+    switch (feature) {
+    case QSystemInfo::BluetoothFeature:
+        {
+#ifdef  MAC_SDK_10_6
+            IOBluetoothHostController* controller = [IOBluetoothHostController defaultController];
+            if (controller != NULL) {
+                featureSupported = true;
+            }
+#endif
+        }
+        break;
+    case QSystemInfo::CameraFeature:
+        {
+
+           NSArray * videoDevices;
+           videoDevices = [[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]];
+           if([videoDevices count] > 0) {
+               featureSupported = true;
+           }
+        }
+        break;
+    case QSystemInfo::FmradioFeature:
+        break;
+    case QSystemInfo::IrFeature:
+        {
+            if(hasIOServiceMatching("AppleIRController")) {
+                featureSupported = true;
+            }
+        }
+        break;
+    case QSystemInfo::LedFeature:
+        {
+//kHIDPage_LEDs
+        }
+        break;
+    case QSystemInfo::MemcardFeature:
+        {
+// IOSCSIPeripheralDeviceType0E
+            if(hasIOServiceMatching("IOUSBMassStorageClass")) {
+                featureSupported = true;
+            }
+        }
+        break;
+    case QSystemInfo::UsbFeature:
+        {
+            if(hasIOServiceMatching("AppleUSBOHCI")) {
+                featureSupported = true;
+            }
+            if(hasIOServiceMatching("AppleUSBEHCI")) {
+                featureSupported = true;
+            }
+        }
+        break;
+    case QSystemInfo::VibFeature:
+        {
+        }
+        break;
+    case QSystemInfo::WlanFeature:
+        {
+            if(!QSystemNetworkInfoPrivate::instance()->interfaceForMode(QSystemNetworkInfo::WlanMode).name().isEmpty()) {
+                featureSupported = true;
+            }
+        }
+        break;
+    case QSystemInfo::SimFeature:
+        {
+        }
+        break;
+    case QSystemInfo::LocationFeature:
+        {
+#ifdef MAC_SDK_10_6
+            CLLocationManager *locationManager = [[CLLocationManager alloc] init];
+            if ([locationManager locationServicesEnabled]) {
+                featureSupported = true;
+            }
+            [locationManager release];
+#endif
+        }
+        break;
+    case QSystemInfo::VideoOutFeature:
+        {
+            ComponentDescription description = {'vout', 0, 0, 0L, 1L << 0};
+            if( ::CountComponents(&description) > 0) {
+                featureSupported = true;
+            }
+        }
+        break;
+    case QSystemInfo::HapticsFeature:
+        break;
+    default:
+        featureSupported = false;
+        break;
+    };
+    return featureSupported;
+}
+
+QSystemNetworkInfoPrivate *QSystemNetworkInfoPrivate::self = 0;
+
+
+void networkChangeCallback(SCDynamicStoreRef /*dynamicStore*/, CFArrayRef changedKeys, void */*networkConfigurationManagerPrivate*/)
+{
+// NSLog(@"changed keys %@", changedKeys);
+    QStringList keyList = nsarrayToQStringList((void*)changedKeys);
+    if(keyList.contains("State:/Network/Global/DNS")) {
+    }
+    if(keyList.contains("State:/Network/Global/IPv4")) {
+        QTM_NAMESPACE::QSystemNetworkInfoPrivate::instance()->ethernetChanged();
+        QTM_NAMESPACE::QSystemNetworkInfoPrivate::instance()->getDefaultInterface();
+    }
+
+    return;
+}
+
+#ifdef MAC_SDK_10_6
+QtMLangListener *langListener;
+#endif
+
+
+QLangLoopThread::QLangLoopThread(QObject *parent)
+    :QThread(parent)
+{
+}
+
+QLangLoopThread::~QLangLoopThread()
+{
+}
+
+void QLangLoopThread::stop()
+{
+    QMutexLocker locker(&mutex);
+    locker.unlock();
+    keepRunning = false;
+    locker.relock();
+#ifdef MAC_SDK_10_6
+    [langListener release];
+#endif
+    if(currentThread() != this) {
+        QMetaObject::invokeMethod(this, "quit",
+                                  Qt::QueuedConnection);
+    } else {
+        quit();
+    }
+    wait();
+}
+
+void QLangLoopThread::run()
+{
+#ifdef MAC_SDK_10_6
+    QMutexLocker locker(&mutex);
+    locker.unlock();
+    keepRunning = true;
+    locker.relock();
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    langListener = [[QtMLangListener alloc] init];
+    SInt32 result;
+    while (keepRunning &&
+           (result = CFRunLoopRunInMode(kCFRunLoopDefaultMode ,5, YES))) {
+    }
+    CFRunLoopStop(CFRunLoopGetCurrent());
+    [pool release];
+#endif
+}
+
+#ifdef MAC_SDK_10_6
+QtMNSListener *listener;
+#endif
+
+QRunLoopThread::QRunLoopThread(QObject *parent)
+    :QThread(parent)
+{
+}
+
+QRunLoopThread::~QRunLoopThread()
+{
+}
+
+void QRunLoopThread::stop()
+{
+    QMutexLocker locker(&mutex);
+    locker.unlock();
+    keepRunning = false;
+    locker.relock();
+#ifdef MAC_SDK_10_6
+    [listener release];
+    [delegate release];
+#endif
+    if(currentThread() != this) {
+        QMetaObject::invokeMethod(this, "quit",
+                                  Qt::QueuedConnection);
+    } else {
+        quit();
+    }
+    wait();
+}
+
+
+void QRunLoopThread::run()
+{
+#ifdef MAC_SDK_10_6
+
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    startNetworkChangeLoop();
+    delegate = [[RemoteDeviceRSSIHostControllerDelegate alloc] init];
+
+    mutex.lock();
+    keepRunning = true;
+    mutex.unlock();
+
+    listener = [[QtMNSListener alloc] init];
+
+    SInt32 result;
+    while (keepRunning &&
+           (result = CFRunLoopRunInMode(kCFRunLoopDefaultMode ,5, YES))) {
+    }
+    CFRunLoopStop(CFRunLoopGetCurrent());
+    [pool release];
+#endif
+}
+
+void QRunLoopThread::startNetworkChangeLoop()
+{
+    storeSession = NULL;
+
+    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,
+                                                     kSCEntNetLink);
+    CFArrayAppendValue(notificationKeys, storeKey);
+    CFRelease(storeKey);
+
+    storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                      kSCDynamicStoreDomainState,
+                                                      kSCCompAnyRegex,
+                                                      kSCEntNetLink);
+    CFArrayAppendValue(patternsArray, storeKey);
+    CFRelease(storeKey);
+
+    storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                     kSCDynamicStoreDomainState,
+                                                     kSCEntNetDNS);
+    CFArrayAppendValue(notificationKeys, storeKey);
+    CFRelease(storeKey);
+
+    storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                      kSCDynamicStoreDomainState,
+                                                      kSCCompAnyRegex,
+                                                      kSCEntNetDNS);
+    CFArrayAppendValue(patternsArray, storeKey);
+    CFRelease(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);
+    CFRelease(runloopSource);
+    CFRelease(storeSession);
+    return;
+}
+
+
+static bool isBtPowerOn()
+{
+    //depreciated yes, but what's the replacement?
+    BluetoothHCIPowerState powerState;
+    IOBluetoothLocalDeviceGetPowerState(&powerState);
+    if(powerState == kBluetoothHCIPowerStateON)
+        return true;
+    return false;
+}
+
+void btPowerStateChange(void *ref, io_service_t /*service*/, natural_t messageType, void */*info*/)
+{
+    QBluetoothListenerThread * thread = reinterpret_cast< QBluetoothListenerThread *>(ref);
+    switch (messageType) {
+    case kIOMessageDeviceWillPowerOff:
+        {
+            if(!isBtPowerOn())
+                thread->emitBtPower(false);
+        }
+        break;
+    case kIOMessageDeviceHasPoweredOn:
+        {
+            if(isBtPowerOn())
+                thread->emitBtPower(true);
+        }
+        break;
+    }
+}
+
+QBluetoothListenerThread::QBluetoothListenerThread(QObject *parent)
+    :QThread(parent)
+{
+    setTerminationEnabled(true);
+}
+
+QBluetoothListenerThread::~QBluetoothListenerThread()
+{
+    if(isRunning()) {
+        terminate();
+        wait();
+    }
+}
+
+void QBluetoothListenerThread::stop()
+{
+    mutex.lock();
+    keepRunning = false;
+    mutex.unlock();
+
+    if(CFRunLoopContainsSource(rl,rls,kCFRunLoopDefaultMode)) {
+        CFRunLoopRemoveSource(rl,
+                              rls,
+                              kCFRunLoopDefaultMode);
+        CFRunLoopStop(rl);
+    }
+    if(currentThread() != this) {
+        QMetaObject::invokeMethod(this, "quit",
+                                  Qt::QueuedConnection);
+    } else {
+        quit();
+    }
+    mutex.lock();
+    IONotificationPortDestroy(port);
+    mutex.unlock();
+}
+
+void QBluetoothListenerThread::run()
+{
+#ifdef MAC_SDK_10_6
+    mutex.lock();
+    keepRunning = true;
+    mutex.unlock();
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    io_object_t notifyObject;
+    io_service_t bluetoothservice;
+
+    io_iterator_t ioIterator;
+    mach_port_t masterPort;
+    CFMutableDictionaryRef serviceMatchDict;
+
+    if (0 != IOMasterPort(MACH_PORT_NULL, &masterPort)) {
+        qDebug() << "IOMasterPort failed";
+    }
+
+    serviceMatchDict = IOServiceMatching("IOBluetoothHCIController");
+    if (NULL == serviceMatchDict) {
+        qDebug() << "IOServiceMatching failed";
+    }
+
+    if (0 != IOServiceGetMatchingServices(masterPort, serviceMatchDict, &ioIterator)) {
+        qDebug() << "IOServiceGetMatchingServices failed";
+    }
+
+    IOReturn ret;
+
+    bluetoothservice = IOIteratorNext(ioIterator);
+    if (0 == bluetoothservice) {
+        IOObjectRelease(ioIterator);
+        qDebug() << "IOIteratorNext failed";
+    }
+    IOObjectRelease(ioIterator);
+
+    port = IONotificationPortCreate(masterPort);
+    if (0 == port) {
+        qDebug() << "IONotificationPortCreate failed";
+    }
+
+    ret = IOServiceAddInterestNotification(port, bluetoothservice,
+                                           kIOGeneralInterest, btPowerStateChange,
+                                           this, &notifyObject);
+    if(ret != kIOReturnSuccess) {
+        qDebug() << "IOServiceAddInterestNotification failed";
+        return;
+    }
+
+    rl = CFRunLoopGetCurrent();
+    rls = IONotificationPortGetRunLoopSource(port);
+
+    CFRunLoopAddSource(rl,
+                       rls,
+                       kCFRunLoopDefaultMode);
+    SInt32 result;
+    while (keepRunning &&
+           (result = CFRunLoopRunInMode(kCFRunLoopDefaultMode ,1, NO))) {
+    }
+
+    CFRunLoopStop(rl);
+
+    IOObjectRelease(bluetoothservice);
+    CFRunLoopRemoveSource(rl,
+                          rls,
+                          kCFRunLoopDefaultMode);
+    [pool release];
+#endif
+}
+
+void QBluetoothListenerThread::emitBtPower(bool b)
+{
+    Q_EMIT bluetoothPower(b);
+}
+
+
+QSystemNetworkInfoPrivate::QSystemNetworkInfoPrivate(QObject *parent)
+        : QObject(parent), signalStrengthCache(0)
+{
+     defaultInterface = "";
+    qRegisterMetaType<QSystemNetworkInfo::NetworkMode>("QSystemNetworkInfo::NetworkMode");
+    qRegisterMetaType<QSystemNetworkInfo::NetworkStatus>("QSystemNetworkInfo::NetworkStatus");
+
+#ifdef MAC_SDK_10_6
+if([[CWInterface supportedInterfaces] count] > 0 ) {
+        hasWifi = true;
+    } else {
+        hasWifi = false;
+    }
+#endif
+    rssiTimer = new QTimer(this);
+
+    if(!self)
+        self = this;
+    QTimer::singleShot(200, this, SLOT(primaryInterface()));
+}
+
+QSystemNetworkInfoPrivate::~QSystemNetworkInfoPrivate()
+{
+#ifdef MAC_SDK_10_6
+    if(hasWifi && runloopThread->isRunning()) {
+        runloopThread->stop();
+    }
+#endif
+}
+
+void QSystemNetworkInfoPrivate::primaryInterface()
+{
+    defaultInterface = getDefaultInterface();
+}
+
+void QSystemNetworkInfoPrivate::connectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(networkSignalStrengthChanged(QSystemNetworkInfo::NetworkMode,int))) {
+        connect(rssiTimer, SIGNAL(timeout()), this, SLOT(rssiTimeout()));
+        rssiTimer->start(5000);
+    }
+    if (QLatin1String(signal) == SIGNAL(networkNameChanged(QSystemNetworkInfo::NetworkMode,QString))
+        || QLatin1String(signal) == SIGNAL(networkStatusChanged(QSystemNetworkInfo::NetworkMode, QSystemNetworkInfo::NetworkStatus))) {
+#ifdef MAC_SDK_10_6
+        if(hasWifi) {
+            runloopThread = new QRunLoopThread(this);
+            runloopThread->start();
+        }
+#endif
+    }
+}
+
+void QSystemNetworkInfoPrivate::disconnectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(networkSignalStrengthChanged(QSystemNetworkInfo::NetworkMode,int))) {
+        rssiTimer->stop();
+        disconnect(rssiTimer, SIGNAL(timeout()), this, SLOT(rssiTimeout()));
+    }
+    if (QLatin1String(signal) == SIGNAL(networkNameChanged(QSystemNetworkInfo::NetworkMode,QString))
+        || QLatin1String(signal) == SIGNAL(networkStatusChanged(QSystemNetworkInfo::NetworkMode, QSystemNetworkInfo::NetworkStatus))) {
+#ifdef MAC_SDK_10_6
+        if(hasWifi && runloopThread->isRunning()) {
+            runloopThread->quit();
+            runloopThread->wait();
+            [delegate release];
+        }
+#endif
+    }
+}
+
+QSystemNetworkInfo::NetworkMode QSystemNetworkInfoPrivate::modeForInterface(QString interfaceName)
+{
+    QSystemNetworkInfo::NetworkMode mode = QSystemNetworkInfo::UnknownMode;
+    CFArrayRef interfaceArray = SCNetworkInterfaceCopyAll(); //10.4
+    CFStringRef iName;
+    CFStringRef type;
+
+    for ( long i = 0; i < CFArrayGetCount(interfaceArray); i++) {
+        SCNetworkInterfaceRef thisInterface =  (SCNetworkInterfaceRef ) CFArrayGetValueAtIndex(interfaceArray, i);
+        type = SCNetworkInterfaceGetInterfaceType(thisInterface);
+        iName = SCNetworkInterfaceGetBSDName(thisInterface);
+        if( interfaceName == stringFromCFString(iName)) {
+            if (type != NULL) {
+                if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) {
+                    mode = QSystemNetworkInfo::BluetoothMode;
+                    break;
+                } else if (CFEqual(type, kSCNetworkInterfaceTypeEthernet)) {
+                    mode = QSystemNetworkInfo::EthernetMode;
+                    break;
+                } else if (CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) {
+                    mode = QSystemNetworkInfo::WlanMode;
+                    break;
+                }
+            }
+        }
+    }
+    CFRelease(interfaceArray);
+    return mode;
+}
+
+QString QSystemNetworkInfoPrivate::getDefaultInterface()
+{
+    SCDynamicStoreRef storeSession2;
+    CFStringRef key;
+    CFDictionaryRef	globalDict;
+    CFStringRef primaryInterface = NULL;
+    QString interfaceName;
+
+    storeSession2 = SCDynamicStoreCreate(NULL, CFSTR("getPrimary"), NULL, NULL);
+    if (!storeSession2) {
+    }
+    key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState,kSCEntNetIPv4);
+    globalDict = (const __CFDictionary*)SCDynamicStoreCopyValue(storeSession2, key);
+    CFRelease(key);
+    if (globalDict) {
+
+        primaryInterface = (CFStringRef )CFDictionaryGetValue(globalDict,
+                                                                   kSCDynamicStorePropNetPrimaryInterface);
+        if (primaryInterface) {
+            CFRetain(primaryInterface);
+        }
+        CFRelease(globalDict);
+    }
+
+    CFRelease(storeSession2);
+    if (primaryInterface) {
+        interfaceName = stringFromCFString(primaryInterface);
+        if(interfaceName != defaultInterface) {
+            Q_EMIT networkModeChanged(modeForInterface(interfaceName));
+             defaultInterface = interfaceName;
+        }
+    }
+
+    return interfaceName;
+}
+
+void QSystemNetworkInfoPrivate::rssiTimeout()
+{
+    networkSignalStrength(QSystemNetworkInfo::WlanMode);
+}
+
+bool QSystemNetworkInfoPrivate::isInterfaceActive(const char* netInterface)
+{
+    struct ifmediareq ifm;
+
+    memset(&ifm, 0, sizeof(struct ifmediareq));
+    strncpy(ifm.ifm_name, netInterface, IFNAMSIZ);
+    int s = socket(AF_INET, SOCK_DGRAM, 0);
+    ioctl(s, SIOCGIFMEDIA, &ifm);
+    if (ifm.ifm_status & IFM_ACTIVE) {
+        return true;
+    }
+    return false;
+}
+
+void QSystemNetworkInfoPrivate::ethernetChanged()
+{
+    QSystemNetworkInfo::NetworkStatus status = QSystemNetworkInfo::NoNetworkAvailable;
+    int carrier = 0;
+
+    if(isInterfaceActive(interfaceForMode(QSystemNetworkInfo::EthernetMode).name().toLocal8Bit())) {
+        status = QSystemNetworkInfo::Connected;
+        carrier = 100;
+    }
+    Q_EMIT networkStatusChanged(QSystemNetworkInfo::EthernetMode,status);
+    Q_EMIT networkSignalStrengthChanged(QSystemNetworkInfo::EthernetMode,carrier);
+    Q_EMIT networkNameChanged(QSystemNetworkInfo::EthernetMode, networkName(QSystemNetworkInfo::EthernetMode));
+    Q_EMIT networkModeChanged(modeForInterface(getDefaultInterface()));
+}
+
+QSystemNetworkInfo::NetworkStatus QSystemNetworkInfoPrivate::networkStatus(QSystemNetworkInfo::NetworkMode mode)
+{
+    QSystemNetworkInfo::NetworkStatus status = QSystemNetworkInfo::NoNetworkAvailable;
+    switch(mode) {
+        case QSystemNetworkInfo::GsmMode:
+        break;
+        case QSystemNetworkInfo::CdmaMode:
+        break;
+        case QSystemNetworkInfo::WcdmaMode:
+        break;
+    case QSystemNetworkInfo::WlanMode:
+        {
+#ifdef MAC_SDK_10_6
+            if(hasWifi) {
+                NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+                CWInterface *wifiInterface = [CWInterface interfaceWithName:  qstringToNSString(interfaceForMode(mode).name())];
+
+                if([wifiInterface power]) {
+                    if(!rssiTimer->isActive())
+                        rssiTimer->start(5000);
+                }  else {
+                    if(rssiTimer->isActive())
+                        rssiTimer->stop();
+                }
+
+                switch([[wifiInterface interfaceState]intValue]) {
+                case  kCWInterfaceStateInactive:
+                    status = QSystemNetworkInfo::NoNetworkAvailable;
+                    break;
+                case kCWInterfaceStateScanning:
+                case kCWInterfaceStateAuthenticating:
+                case kCWInterfaceStateAssociating:
+                    status = QSystemNetworkInfo::Searching;
+                    break;
+                case kCWInterfaceStateRunning:
+                    status = QSystemNetworkInfo::Connected;
+                    break;
+                };
+                [autoreleasepool release];
+            }
+
+#else
+            if(isInterfaceActive(interfaceForMode(mode).name().toLatin1())) {
+                status = QSystemNetworkInfo::Connected;
+            }
+#endif
+        }
+        break;
+    case QSystemNetworkInfo::EthernetMode:
+        {
+            if(isInterfaceActive(interfaceForMode(mode).name().toLatin1())) {
+                return QSystemNetworkInfo::Connected;
+            } else {
+                return QSystemNetworkInfo::NoNetworkAvailable;
+            }
+        }
+        break;
+        case QSystemNetworkInfo::BluetoothMode:
+        {
+
+        }
+        break;
+    case QSystemNetworkInfo::WimaxMode:
+        break;
+        default:
+        break;
+    };
+    return status;
+}
+
+int QSystemNetworkInfoPrivate::networkSignalStrength(QSystemNetworkInfo::NetworkMode mode)
+{
+    switch(mode) {
+        case QSystemNetworkInfo::GsmMode:
+        break;
+        case QSystemNetworkInfo::CdmaMode:
+        break;
+        case QSystemNetworkInfo::WcdmaMode:
+        break;
+    case QSystemNetworkInfo::WlanMode:
+        {
+            int signalQuality = 0;
+            if(hasWifi) {
+#ifdef MAC_SDK_10_6
+                NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+                QString name = interfaceForMode(mode).name();
+                CWInterface *wifiInterface = [CWInterface interfaceWithName:qstringToNSString(name)];
+
+                if([wifiInterface power]) {
+                    if(!rssiTimer->isActive())
+                        rssiTimer->start(5000);
+                }  else {
+                    if(rssiTimer->isActive())
+                        rssiTimer->stop();
+                }
+
+                int rssiSignal = [[wifiInterface rssi] intValue];
+
+                if(rssiSignal !=0 ) {
+                    int maxRssi = -40;
+                    int minRssi = [[wifiInterface noise] intValue];
+                    signalQuality = ( 100 * (maxRssi - minRssi) * (maxRssi - minRssi) - (maxRssi - rssiSignal) *
+                                      (15 * (maxRssi - minRssi) + 62 * (maxRssi - rssiSignal)) ) /
+                                    ((maxRssi - minRssi) * (maxRssi - minRssi));
+
+                } else {
+                    signalQuality = 0;
+                }
+
+                if(signalStrengthCache != signalQuality) {
+                    if(signalStrengthCache == 0) {
+                        networkStatus(QSystemNetworkInfo::WlanMode);
+                    }
+                    signalStrengthCache = signalQuality;
+                    Q_EMIT networkSignalStrengthChanged(mode, signalQuality);
+                }
+                [autoreleasepool release];
+#endif
+            }
+            return signalQuality;
+        }
+        break;
+    case QSystemNetworkInfo::EthernetMode:
+        {
+            int percent = (isInterfaceActive(interfaceForMode(mode).name().toLatin1())) ? 100 : 0;
+            return percent;
+        }
+        break;
+    case QSystemNetworkInfo::BluetoothMode:
+        {
+#ifdef  MAC_SDK_10_6
+            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+            IOBluetoothHostController* controller = IOBluetoothHostController.defaultController;
+            if (controller != NULL) {
+
+                NSArray *devices = [IOBluetoothDevice recentDevices:0];
+                for ( IOBluetoothDevice *btDevice in devices ) {
+                    if([btDevice isConnected]) {
+                        qWarning() <<"IOBluetoothDevice connected"<< nsstringToQString([btDevice getName]);
+//                        delegate = [[RemoteDeviceRSSIHostControllerDelegate alloc] init];
+                        [delegate retain];
+                        [controller setDelegate:delegate];
+                        IOReturn rc = [controller readRSSIForDevice:btDevice];
+                        if (rc != noErr) {
+                            qWarning() << "ERROR: call readRSSIForDevice failed";
+                        }
+//[delegate release];
+                    }
+                }
+//              [devices release];
+  //  [controller release];
+            }
+            [pool release];
+#endif
+        }
+    case QSystemNetworkInfo::WimaxMode:
+        break;
+    default:
+        break;
+    };
+    return -1;
+}
+
+int QSystemNetworkInfoPrivate::cellId()
+{
+    return -1;
+}
+
+int QSystemNetworkInfoPrivate::locationAreaCode()
+{
+    return -1;
+}
+
+QString QSystemNetworkInfoPrivate::currentMobileCountryCode()
+{
+    QString cmcc;
+#if defined(MAC_SDK_10_6)
+    if(hasWifi) {
+        CWInterface *primary = [CWInterface interfaceWithName:nil];
+        if([primary power]) {
+            cmcc = nsstringToQString([primary countryCode]);
+        }
+    }
+#endif
+    return cmcc;
+}
+
+QString QSystemNetworkInfoPrivate::currentMobileNetworkCode()
+{
+    return "";
+}
+
+QString QSystemNetworkInfoPrivate::homeMobileCountryCode()
+{
+    return "";
+}
+
+QString QSystemNetworkInfoPrivate::homeMobileNetworkCode()
+{
+    return "";
+}
+
+QString QSystemNetworkInfoPrivate::networkName(QSystemNetworkInfo::NetworkMode mode)
+{
+    if(networkStatus(mode) == QSystemNetworkInfo::NoNetworkAvailable) {
+        return "";
+    }
+    switch(mode) {
+        case QSystemNetworkInfo::GsmMode:
+        break;
+        case QSystemNetworkInfo::CdmaMode:
+        break;
+        case QSystemNetworkInfo::WcdmaMode:
+        break;
+    case QSystemNetworkInfo::WlanMode:
+        {
+            QString name = interfaceForMode(mode).name();
+#ifdef MAC_SDK_10_6
+            if(hasWifi) {
+                CWInterface *wifiInterface = [CWInterface interfaceWithName:qstringToNSString(name)];
+                return nsstringToQString([wifiInterface ssid]);
+            }
+#else
+            SCDynamicStoreRef theDynamicStore;
+            theDynamicStore = SCDynamicStoreCreate(nil, CFSTR("FindCurrentInterfaceAndIP"), nil, nil);
+
+            NSMutableString *interfaceName = [NSMutableString string];
+            NSString *airportPath = [NSString stringWithFormat:@"State:/Network/Interface/%@/AirPort", qstringToNSString(name)];
+
+            CFDictionaryRef airportPlist = (const __CFDictionary*)SCDynamicStoreCopyValue(theDynamicStore, (CFStringRef)airportPath);
+
+            CFRelease(theDynamicStore);
+
+            return nsstringToQString([(NSDictionary *)airportPlist valueForKey:@"SSID_STR"]);
+#endif
+        }
+        break;
+    case QSystemNetworkInfo::EthernetMode:
+        {
+            if(isInterfaceActive(interfaceForMode(mode).name().toLocal8Bit())) {
+                return QHostInfo::localDomainName();
+            }
+        }
+        break;
+    case QSystemNetworkInfo::BluetoothMode:
+        break;
+    case QSystemNetworkInfo::WimaxMode:
+        break;
+    default:
+        break;
+    };
+    return "";
+}
+
+QString QSystemNetworkInfoPrivate::macAddress(QSystemNetworkInfo::NetworkMode mode)
+{
+    return interfaceForMode(mode).hardwareAddress();
+}
+
+QNetworkInterface QSystemNetworkInfoPrivate::interfaceForMode(QSystemNetworkInfo::NetworkMode mode)
+{
+    QNetworkInterface netInterface;
+    CFArrayRef interfaceArray = SCNetworkInterfaceCopyAll(); //10.4
+    CFStringRef iName;
+    CFStringRef type;
+    for ( long i = 0; i < CFArrayGetCount(interfaceArray); i++) {
+        SCNetworkInterfaceRef thisInterface =  (SCNetworkInterfaceRef ) CFArrayGetValueAtIndex(interfaceArray, i);
+        type = SCNetworkInterfaceGetInterfaceType(thisInterface);
+        iName = SCNetworkInterfaceGetBSDName(thisInterface);
+
+        if (type != NULL) {
+            if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth) && mode == QSystemNetworkInfo::BluetoothMode) {
+                netInterface = QNetworkInterface::interfaceFromName(stringFromCFString(iName));
+                // workaround for null MAC from SCNetworkInterfaceGetHardwareAddressString and bogus BSD name here
+#ifdef  MAC_SDK_10_6
+                IOBluetoothHostController* controller = IOBluetoothHostController.defaultController;
+                QString macbtMac = nsstringToQString([controller addressAsString]).replace("-",":").toUpper();
+                if(!macbtMac.isEmpty()) {
+                    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+                    foreach(const QNetworkInterface thisNetInterface, interfaces) {
+                        if( thisNetInterface.hardwareAddress() == macbtMac) {
+                            netInterface = thisNetInterface;
+                            break;
+                        }
+                    }
+                }
+#endif
+            } else if (CFEqual(type, kSCNetworkInterfaceTypeEthernet) && mode == QSystemNetworkInfo::EthernetMode) {
+                netInterface = QNetworkInterface::interfaceFromName(stringFromCFString(iName));
+                break;
+            } else if (CFEqual(type, kSCNetworkInterfaceTypeIEEE80211) && mode == QSystemNetworkInfo::WlanMode) {
+                netInterface = QNetworkInterface::interfaceFromName(stringFromCFString(iName));
+                break;
+            }
+        }
+    }
+    CFRelease(interfaceArray);
+    return netInterface;
+}
+
+void QSystemNetworkInfoPrivate::wifiNetworkChanged(const QString &notification, const QString interfaceName)
+{
+    getDefaultInterface();
+
+    if(notification == QLatin1String("SSID_CHANGED_NOTIFICATION")) {
+        Q_EMIT networkNameChanged(QSystemNetworkInfo::WlanMode, networkName(QSystemNetworkInfo::WlanMode));
+    }
+
+    if(notification == QLatin1String("BSSID_CHANGED_NOTIFICATION")) {
+        QSystemNetworkInfo::NetworkStatus status =  networkStatus(QSystemNetworkInfo::WlanMode);
+        Q_EMIT networkStatusChanged( QSystemNetworkInfo::WlanMode, status);
+    }
+    if(notification == QLatin1String("POWER_CHANGED_NOTIFICATION")) {
+#ifdef MAC_SDK_10_6
+        CWInterface *wifiInterface = [CWInterface interfaceWithName:  qstringToNSString(interfaceName)];
+        if([wifiInterface power]) {
+            if(!rssiTimer->isActive()) {
+                rssiTimer->start(5000);
+
+            }
+        }  else {
+            if(rssiTimer->isActive()) {
+                rssiTimer->stop();
+            }
+            Q_EMIT networkSignalStrengthChanged(QSystemNetworkInfo::WlanMode, 0);
+        }
+#endif
+    }
+}
+
+QSystemNetworkInfo::NetworkMode QSystemNetworkInfoPrivate::currentMode()
+{
+    return modeForInterface(getDefaultInterface());
+}
+
+
+QSystemDisplayInfoPrivate::QSystemDisplayInfoPrivate(QObject *parent)
+        : QObject(parent)
+{
+}
+
+QSystemDisplayInfoPrivate::~QSystemDisplayInfoPrivate()
+{
+}
+
+int QSystemDisplayInfoPrivate::displayBrightness(int screen)
+{
+    int macScreens = 4;
+    CGDisplayErr dErr;
+    io_service_t service;
+    CFStringRef key = CFSTR(kIODisplayBrightnessKey);
+
+    float brightness = HUGE_VALF;
+    int displayBrightness = -1;
+    CGDirectDisplayID screensArray[macScreens]; //support 4 screens
+    CGDisplayCount numberScreens;
+    CGGetActiveDisplayList(macScreens, screensArray, &numberScreens);
+    if(numberScreens >= (uint)screen) {
+        service = CGDisplayIOServicePort(screensArray[screen]);
+        dErr = IODisplayGetFloatParameter(service, kNilOptions, key, &brightness);
+        if (dErr == kIOReturnSuccess) {
+            displayBrightness = (int)(brightness * 100);
+        }
+    }
+    return displayBrightness;
+}
+
+int QSystemDisplayInfoPrivate::colorDepth(int screen)
+{
+    int macScreens = 4;
+    CGDirectDisplayID screensArray[macScreens]; //support 4 screens
+    CGDisplayCount numberScreens;
+    long bitsPerPixel = 0;
+    CGGetActiveDisplayList(macScreens, screensArray, &numberScreens);
+    if(numberScreens >= (uint)screen) {
+        bitsPerPixel = CGDisplayBitsPerPixel (screensArray[screen]);
+    }
+    return (int)bitsPerPixel;
+}
+
+QSystemStorageInfoPrivate::QSystemStorageInfoPrivate(QObject *parent)
+        : QObject(parent)
+{
+}
+
+
+QSystemStorageInfoPrivate::~QSystemStorageInfoPrivate()
+{
+}
+
+bool QSystemStorageInfoPrivate::updateVolumesMap()
+{
+    struct statfs64 *buf = NULL;
+    unsigned i, count = 0;
+
+    count = getmntinfo64(&buf, 0);
+    for (i=0; i<count; i++) {
+        char *volName = buf[i].f_mntonname;
+        mountEntriesHash.insert(buf[i].f_mntfromname,volName);
+    }
+    return true;
+}
+
+
+qint64 QSystemStorageInfoPrivate::availableDiskSpace(const QString &driveVolume)
+{
+    qint64 totalFreeBytes=0;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSDictionary *attr = [ [NSFileManager defaultManager] attributesOfFileSystemForPath:qstringToNSString(driveVolume) error:nil];
+    totalFreeBytes = [[attr objectForKey:NSFileSystemFreeSize] doubleValue];
+    [pool release];
+
+    return  totalFreeBytes;
+}
+
+qint64 QSystemStorageInfoPrivate::totalDiskSpace(const QString &driveVolume)
+{
+    qint64 totalBytes=0;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSDictionary *attr = [ [NSFileManager defaultManager] attributesOfFileSystemForPath:qstringToNSString(driveVolume) error:nil];
+    totalBytes = [[attr objectForKey:NSFileSystemSize] doubleValue];
+    [pool release];
+
+    return totalBytes;
+}
+
+QSystemStorageInfo::DriveType QSystemStorageInfoPrivate::typeForDrive(const QString &driveVolume)
+{
+    updateVolumesMap();
+    OSStatus osstatusResult = noErr;
+    ItemCount volumeIndex;
+
+    for (volumeIndex = 1; osstatusResult == noErr || osstatusResult != nsvErr; volumeIndex++) {
+        FSVolumeRefNum actualVolume;
+        HFSUniStr255 volumeName;
+        FSVolumeInfo	volumeInfo;
+
+        bzero((void *) &volumeInfo, sizeof(volumeInfo));
+
+        osstatusResult = FSGetVolumeInfo(kFSInvalidVolumeRefNum, volumeIndex, &actualVolume, kFSVolInfoFSInfo,
+                                         &volumeInfo, &volumeName, NULL);
+
+        if (osstatusResult == noErr) {
+            GetVolParmsInfoBuffer volumeParmeters;
+            osstatusResult = FSGetVolumeParms(actualVolume, &volumeParmeters, sizeof(volumeParmeters));
+
+            QString devId = QString((char *)volumeParmeters.vMDeviceID);
+            devId = devId.prepend(QLatin1String("/dev/"));
+            if(mountEntriesHash.value(devId) == driveVolume) {
+                if (volumeParmeters.vMServerAdr == 0) { //local drive
+                    io_service_t ioService;
+                    ioService = IOServiceGetMatchingService(kIOMasterPortDefault,
+                                                            IOBSDNameMatching(kIOMasterPortDefault,
+                                                            0,
+                                                            (char *)volumeParmeters.vMDeviceID));
+
+                    if (IOObjectConformsTo(ioService, kIOMediaClass)) {
+                        CFTypeRef wholeMedia;
+
+                        wholeMedia = IORegistryEntryCreateCFProperty(ioService,
+                                                                     CFSTR(kIOMediaContentKey),
+                                                                     kCFAllocatorDefault,
+                                                                     0);
+
+                        if((volumeParmeters.vMExtendedAttributes & (1L << bIsRemovable))) {
+                            IOObjectRelease(ioService);
+                            CFRelease(wholeMedia);
+                            return QSystemStorageInfo::RemovableDrive;
+                        } else {
+                            IOObjectRelease(ioService);
+                            CFRelease(wholeMedia);
+                            return QSystemStorageInfo::InternalDrive;
+                        }
+                    }
+                    IOObjectRelease(ioService);
+                } else {
+                    return QSystemStorageInfo::RemoteDrive;
+                }
+            }
+        }
+    }
+    return QSystemStorageInfo::NoDrive;
+}
+
+QStringList QSystemStorageInfoPrivate::logicalDrives()
+{
+    QStringList drivesList;
+
+    struct statfs64 *buf = NULL;
+    unsigned i, count = 0;
+
+    count = getmntinfo64(&buf, 0);
+    for (i=0; i<count; i++) {
+        char *volName = buf[i].f_mntonname;
+        if(buf[i].f_type != 19
+           && buf[i].f_type != 20) {
+            drivesList << volName;
+        }
+    }
+    return drivesList;
+}
+
+void powerInfoChanged(void* context)
+{
+    QSystemDeviceInfoPrivate *sys = reinterpret_cast<QSystemDeviceInfoPrivate *>(context);
+    sys->batteryLevel();
+    sys->currentPowerState();
+}
+
+QSystemDeviceInfoPrivate::QSystemDeviceInfoPrivate(QObject *parent)
+        : QObject(parent),btThread(0), btThreadOk(0)
+{
+    batteryLevelCache = 0;
+    currentPowerStateCache = QSystemDeviceInfo::UnknownPower;
+    batteryStatusCache = QSystemDeviceInfo::NoBatteryLevel;
+}
+
+QSystemDeviceInfoPrivate::~QSystemDeviceInfoPrivate()
+{
+    if( btThreadOk && btThread->isRunning())
+        btThread->stop();
+}
+
+QSystemDeviceInfoPrivate *QSystemDeviceInfoPrivate::instance()
+{
+    return qsystemDeviceInfoPrivate();
+}
+
+void QSystemDeviceInfoPrivate::connectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(bluetoothStateChanged(bool))) {
+        if(!btThread) {
+            btThread = new QBluetoothListenerThread(this);
+            btThread->start();
+            connect(btThread,SIGNAL(bluetoothPower(bool)), this, SIGNAL(bluetoothStateChanged(bool)));
+             btThreadOk = true;
+        }
+    }
+
+    if (QLatin1String(signal) == SIGNAL(powerStateChanged(QSystemDeviceInfo::PowerState))) {
+        CFRunLoopSourceRef runLoopSource = (CFRunLoopSourceRef)IOPSNotificationCreateRunLoopSource(powerInfoChanged, this);
+        if (runLoopSource) {
+            CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+            CFRelease(runLoopSource);
+        }
+    }
+}
+
+void QSystemDeviceInfoPrivate::disconnectNotify(const char *signal)
+{
+    if (QLatin1String(signal) == SIGNAL(bluetoothStateChanged(bool))) {
+        if(btThread->isRunning()) {
+            btThread->stop();
+        }
+    }
+}
+
+
+QSystemDeviceInfo::Profile QSystemDeviceInfoPrivate::currentProfile()
+{
+    return QSystemDeviceInfo::UnknownProfile;
+}
+
+
+QSystemDeviceInfo::InputMethodFlags QSystemDeviceInfoPrivate::inputMethodType()
+{
+    QSystemDeviceInfo::InputMethodFlags methods = 0;
+
+    if(hasIOServiceMatching("AppleUSBTCButtons")) {
+        methods = (methods | QSystemDeviceInfo::Keys);
+    }
+    if(hasIOServiceMatching("AppleUSBTCKeyboard")) {
+        methods = (methods | QSystemDeviceInfo::Keyboard);
+    }
+    if(hasIOServiceMatching("AppleUSBMultitouchDriver")) {
+        methods = (methods | QSystemDeviceInfo::MultiTouch);
+    }
+    if(hasIOServiceMatching("IOHIDPointing")) {
+        methods = (methods | QSystemDeviceInfo::Mouse);
+    }
+    return methods;
+}
+
+
+QSystemDeviceInfo::PowerState QSystemDeviceInfoPrivate::currentPowerState()
+{
+    QSystemDeviceInfo::PowerState state = QSystemDeviceInfo::UnknownPower;
+
+    CFDictionaryRef powerSourceDict = NULL;
+    CFStringRef powerStateString;
+
+    CFTypeRef powerSourcesInfoBlob = IOPSCopyPowerSourcesInfo();
+    CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(powerSourcesInfoBlob);
+    int i;
+    for (i=0; i<CFArrayGetCount(powerSourcesList); i++) {
+        powerSourceDict = IOPSGetPowerSourceDescription(powerSourcesInfoBlob, /* [powerSourcesList objectAtIndex:0]*/ CFArrayGetValueAtIndex(powerSourcesList, i));
+        if(!powerSourceDict) {
+            state = QSystemDeviceInfo::UnknownPower;
+            break;
+        }
+
+        powerStateString = (CFStringRef)CFDictionaryGetValue(powerSourceDict, CFSTR(kIOPSPowerSourceStateKey));
+        if(CFStringCompare(powerStateString,CFSTR(kIOPSBatteryPowerValue),0)==kCFCompareEqualTo) {
+            //has battery
+            state = QSystemDeviceInfo::BatteryPower;
+        } else {
+
+            NSDictionary *powerSourceInfo = nil;
+            powerSourceInfo = [NSDictionary dictionaryWithDictionary:(NSDictionary*)powerSourceDict];
+            bool charging = (bool)[[powerSourceInfo valueForKey:[NSString stringWithUTF8String:kIOPSIsChargingKey]] boolValue];
+            if (charging ) {
+                state = QSystemDeviceInfo::WallPowerChargingBattery;
+            } else {
+                state = QSystemDeviceInfo::WallPower;
+            }
+        }
+    }
+
+    CFRelease(powerSourcesInfoBlob);
+    CFRelease(powerSourcesList);
+
+    if( currentPowerStateCache != state) {
+        currentPowerStateCache = state;
+        Q_EMIT powerStateChanged(state);
+    }
+    return state;
+}
+
+QString QSystemDeviceInfoPrivate::imei()
+{
+    return "";
+}
+
+QString QSystemDeviceInfoPrivate::imsi()
+{
+    return "";
+}
+
+QString QSystemDeviceInfoPrivate::manufacturer()
+{
+    return QString("Apple"); //pretty sure we can hardcode this one
+}
+
+QString QSystemDeviceInfoPrivate::model()
+{
+    char modelBuffer[256];
+    QString model;
+      size_t sz = sizeof(modelBuffer);
+      if (0 == sysctlbyname("hw.model", modelBuffer, &sz, NULL, 0)) {
+          model = QLatin1String(modelBuffer);
+      }
+    return  model;
+}
+
+QString QSystemDeviceInfoPrivate::productName()
+{
+    return nsstringToQString([[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductName"]);
+}
+
+int QSystemDeviceInfoPrivate::batteryLevel()
+{
+    float level = 0;
+    CFDictionaryRef powerSourceDict = NULL;
+    CFTypeRef powerSourcesInfoBlob = IOPSCopyPowerSourcesInfo();
+    CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(powerSourcesInfoBlob);
+    int i;
+    for (i=0; i<CFArrayGetCount(powerSourcesList); i++) {
+        powerSourceDict = IOPSGetPowerSourceDescription(powerSourcesInfoBlob, /* [powerSourcesList objectAtIndex:0]*/ CFArrayGetValueAtIndex(powerSourcesList, i));
+        if(!powerSourceDict) {
+            break;
+        }
+
+        float currentLevel = 0;
+        float maxLevel = 0;
+        const void *powerStateValue;
+
+        powerStateValue = CFDictionaryGetValue(powerSourceDict, CFSTR(kIOPSCurrentCapacityKey));
+        CFNumberGetValue((CFNumberRef)powerStateValue, kCFNumberSInt32Type, &currentLevel);
+
+        powerStateValue = CFDictionaryGetValue(powerSourceDict, CFSTR(kIOPSMaxCapacityKey));
+        CFNumberGetValue((CFNumberRef)powerStateValue, kCFNumberSInt32Type, &maxLevel);
+        level = (currentLevel/maxLevel) * 100;
+    }
+
+    CFRelease(powerSourcesInfoBlob);
+    CFRelease(powerSourcesList);
+
+    if(batteryLevelCache != level) {
+        batteryLevelCache = level;
+        Q_EMIT batteryLevelChanged(level);
+    }
+
+    if(batteryLevelCache < 4 && batteryStatusCache != QSystemDeviceInfo::BatteryCritical) {
+        batteryStatusCache = QSystemDeviceInfo::BatteryCritical;
+        Q_EMIT batteryStatusChanged(batteryStatusCache);
+    } else if((batteryLevelCache > 3 && batteryLevelCache < 11) && batteryStatusCache != QSystemDeviceInfo::BatteryVeryLow) {
+        batteryStatusCache = QSystemDeviceInfo::BatteryVeryLow;
+        Q_EMIT batteryStatusChanged(batteryStatusCache);
+    } else if((batteryLevelCache > 10 && batteryLevelCache < 41) && batteryStatusCache != QSystemDeviceInfo::BatteryLow) {
+        batteryStatusCache = QSystemDeviceInfo::BatteryLow;
+        Q_EMIT batteryStatusChanged(batteryStatusCache);
+    } else if(batteryLevelCache > 40 && batteryStatusCache != QSystemDeviceInfo::BatteryNormal) {
+        batteryStatusCache = QSystemDeviceInfo::BatteryNormal;
+        Q_EMIT batteryStatusChanged(batteryStatusCache);
+    }
+
+    return (int)level;
+}
+
+QSystemDeviceInfo::SimStatus QSystemDeviceInfoPrivate::simStatus()
+{
+    return QSystemDeviceInfo::SimNotAvailable;
+}
+
+bool QSystemDeviceInfoPrivate::isDeviceLocked()
+{
+    // find out if auto login is being used.
+    QSettings loginSettings("/Library/Preferences/com.apple.loginwindow.plist", QSettings::NativeFormat);
+    QString autologinname = loginSettings.value("autoLoginUser").toString();
+
+// find out if locked screensaver is used.
+    int passWordProtected = 0;
+#if defined(QT_ARCH_X86_64)  && !defined(MAC_SDK_10_6)
+    ScreenSaverDefaults *ssDefaults;
+    ssDefaults = [ScreenSaverDefaults defaultsForModuleWithName:@"com.apple.screensaver"];
+    passWordProtected = [ssDefaults integerForKey:@"askForPassword"];
+#endif
+
+    if(autologinname.isEmpty() || passWordProtected == 1) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+QSystemScreenSaverPrivate::QSystemScreenSaverPrivate(QObject *parent)
+        : QObject(parent), isInhibited(0)
+{
+    ssTimer = new QTimer(this);
+    connect(ssTimer, SIGNAL(timeout()), this, SLOT(activityTimeout()));
+}
+
+QSystemScreenSaverPrivate::~QSystemScreenSaverPrivate()
+{
+    if(ssTimer->isActive())
+        ssTimer->stop();
+}
+
+bool QSystemScreenSaverPrivate::setScreenSaverInhibit()
+{
+    activityTimeout();
+    ssTimer->start(1000 * 60);
+    if(ssTimer->isActive()) {
+        isInhibited = true;
+        return isInhibited;
+    }
+
+    return false;
+}
+
+
+bool QSystemScreenSaverPrivate::screenSaverInhibited()
+{
+    return isInhibited;
+}
+
+void QSystemScreenSaverPrivate::activityTimeout()
+{
+    UpdateSystemActivity(OverallAct);
+}
+
+#include "moc_qsysteminfo_mac_p.cpp"
+
+QTM_END_NAMESPACE