Sophie

Sophie

distrib > Mandriva > 2010.1 > i586 > media > main-testing-src > by-pkgid > 357e0466909645e33fa8bfa6e2222a8a > files > 4

kdebase4-runtime-4.4.5-0.1mdv2010.2.src.rpm

Index: runtime/kioslave/network/ioslave/networkuri.h
===================================================================
--- runtime/kioslave/network/ioslave/networkuri.h	(revision 1079783)
+++ runtime/kioslave/network/ioslave/networkuri.h	(revision 1079784)
@@ -40,7 +40,7 @@
     explicit NetworkUri( const KUrl& url );
 
   public:
-    const QString& hostName() const;
+    const QString& hostAddress() const;
     const QString& serviceName() const;
     const QString& serviceType() const;
     NetworkUri::Type type() const;
@@ -48,7 +48,7 @@
   private:
 
   private: // data
-    QString mHostName;
+    QString mHostAddress;
     QString mServiceName;
     QString mServiceType;
 };
@@ -56,28 +56,28 @@
 
 inline NetworkUri::NetworkUri( const KUrl& url )
 {
-    mHostName = url.path().mid( 1 );
-    const int slashIndex = mHostName.indexOf( '/' );
+    mHostAddress = url.path().mid( 1 );
+    const int slashIndex = mHostAddress.indexOf( '/' );
     if( slashIndex != -1 )
     {
         // servicetype is currently appended as .type to the name
-        const int serviceTypeIndex = mHostName.lastIndexOf( '.' ) + 1;
-        mServiceType = mHostName.mid( serviceTypeIndex );
+        const int serviceTypeIndex = mHostAddress.lastIndexOf( '.' ) + 1;
+        mServiceType = mHostAddress.mid( serviceTypeIndex );
 
         const int serviceNameLength = (serviceTypeIndex-1) - (slashIndex+1);
-        mServiceName = mHostName.mid( slashIndex + 1, serviceNameLength );
-        mHostName.resize( slashIndex );
+        mServiceName = mHostAddress.mid( slashIndex + 1, serviceNameLength );
+        mHostAddress.resize( slashIndex );
     }
 }
 
-inline const QString& NetworkUri::hostName()    const { return mHostName; }
+inline const QString& NetworkUri::hostAddress()    const { return mHostAddress; }
 inline const QString& NetworkUri::serviceName() const { return mServiceName; }
 inline const QString& NetworkUri::serviceType() const { return mServiceType; }
 
 inline NetworkUri::Type NetworkUri::type() const
 {
     Type result =
-        mHostName.isEmpty() ?    Domain :
+        mHostAddress.isEmpty() ?    Domain :
         mServiceName.isEmpty() ? Device :
         /*else*/                 Service;
 
@@ -87,7 +87,7 @@
 /*
 inline QDataStream& operator<<( QDataStream& stream, const NetworkUri& networkUri )
 {
-    stream << "NetworkUri(host:"<<networkUri.mHostName
+    stream << "NetworkUri(host:"<<networkUri.mHostAddress
            << ",service:"<<networkUri.mServiceName
            << ",type:"<<static_cast<int>(networkUri.type())<<")";
     return stream;
Index: runtime/kioslave/network/ioslave/networkslave.cpp
===================================================================
--- runtime/kioslave/network/ioslave/networkslave.cpp	(revision 1079783)
+++ runtime/kioslave/network/ioslave/networkslave.cpp	(revision 1079784)
@@ -52,13 +52,13 @@
     bool successfulGetting = false;
 
     const NetworkUri::Type type = networkUri.type();
-kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostName()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
+kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostAddress()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
     if( type == NetworkUri::Service )
     {
-        const QString hostName =    networkUri.hostName();
+        const QString hostAddress =    networkUri.hostAddress();
         const QString serviceName = networkUri.serviceName();
         const QString serviceType = networkUri.serviceType();
-        QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostName, serviceName, serviceType );
+        QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostAddress, serviceName, serviceType );
 
 kDebug()<<reply.isValid();
         if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -84,7 +84,7 @@
 
     bool successfulMimetyping = false;
     NetworkUri::Type type = networkUri.type();
-kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostName()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
+kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostAddress()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
 
     if( type == NetworkUri::Domain )
     {
@@ -94,10 +94,10 @@
     }
     else
     {
-        const QString hostName = networkUri.hostName();
+        const QString hostAddress = networkUri.hostAddress();
         if( type == NetworkUri::Device )
         {
-            QDBusReply<Mollet::NetDevice> reply = mNetworkDBusProxy->deviceData( hostName );
+            QDBusReply<Mollet::NetDevice> reply = mNetworkDBusProxy->deviceData( hostAddress );
 
 kDebug()<<reply.isValid();
             if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -113,7 +113,7 @@
         {
             const QString serviceName = networkUri.serviceName();
             const QString serviceType = networkUri.serviceType();
-            QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostName, serviceName, serviceType );
+            QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostAddress, serviceName, serviceType );
 
 kDebug()<<reply.isValid();
             if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -142,7 +142,7 @@
 
     bool successfulStating = false;
     NetworkUri::Type type = networkUri.type();
-kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostName()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
+kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostAddress()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
 
     if( type == NetworkUri::Domain )
     {
@@ -154,10 +154,10 @@
     }
     else
     {
-        const QString hostName = networkUri.hostName();
+        const QString hostAddress = networkUri.hostAddress();
         if( type == NetworkUri::Device )
         {
-            QDBusReply<Mollet::NetDevice> reply = mNetworkDBusProxy->deviceData( hostName );
+            QDBusReply<Mollet::NetDevice> reply = mNetworkDBusProxy->deviceData( hostAddress );
 
 kDebug()<<reply.isValid();
             if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -175,7 +175,7 @@
         {
             const QString serviceName = networkUri.serviceName();
             const QString serviceType = networkUri.serviceType();
-            QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostName, serviceName, serviceType );
+            QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostAddress, serviceName, serviceType );
 
 kDebug()<<reply.isValid();
             if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -205,7 +205,7 @@
 
     bool successfulListing = false;
     NetworkUri::Type networkUriType = networkUri.type();
-kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostName()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
+kDebug()<<"type="<<networkUri.type()<<"host="<<networkUri.hostAddress()<<"service="<<networkUri.serviceName()<<"stype="<<networkUri.serviceType();
 
     if( networkUriType != NetworkUri::InvalidUrl )
     {
@@ -232,10 +232,10 @@
         }
         else
         {
-            const QString hostName = networkUri.hostName();
+            const QString hostAddress = networkUri.hostAddress();
             if( networkUriType == NetworkUri::Device )
             {
-                QDBusReply<Mollet::NetServiceList> reply = mNetworkDBusProxy->serviceDataList( hostName );
+                QDBusReply<Mollet::NetServiceList> reply = mNetworkDBusProxy->serviceDataList( hostAddress );
 
 kDebug()<<reply.isValid();
                 if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -258,7 +258,7 @@
             {
                 const QString serviceName = networkUri.serviceName();
                 const QString serviceType = networkUri.serviceType();
-                QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostName, serviceName, serviceType );
+                QDBusReply<Mollet::NetService> reply = mNetworkDBusProxy->serviceData( hostAddress, serviceName, serviceType );
 
 kDebug()<<reply.isValid();
                 if( reply.isValid() ) // TODO: find how a not found service can be expressed in the reply
@@ -291,7 +291,7 @@
 
 void NetworkSlave::feedEntryAsDevice( KIO::UDSEntry* entry, const Mollet::NetDevice& deviceData )
 {
-    entry->insert( KIO::UDSEntry::UDS_NAME,         deviceData.hostName() );
+    entry->insert( KIO::UDSEntry::UDS_NAME,         deviceData.hostAddress() );
     entry->insert( KIO::UDSEntry::UDS_DISPLAY_NAME, deviceData.name() );
     entry->insert( KIO::UDSEntry::UDS_FILE_TYPE,    S_IFDIR );
 //     entry->insert( KIO::UDSEntry::UDS_ICON_NAME,    NetDevice::iconName(deviceData.type()) );
Index: runtime/kioslave/network/ioslave/networkdbusinterface.h
===================================================================
--- runtime/kioslave/network/ioslave/networkdbusinterface.h	(revision 1079783)
+++ runtime/kioslave/network/ioslave/networkdbusinterface.h	(revision 1079784)
@@ -41,33 +41,33 @@
     virtual ~NetworkDBusInterface();
 
   public Q_SLOTS:
-    QDBusReply<Mollet::NetDevice> deviceData( const QString& hostName );
-    QDBusReply<Mollet::NetService> serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType );
+    QDBusReply<Mollet::NetDevice> deviceData( const QString& hostAddress );
+    QDBusReply<Mollet::NetService> serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType );
     QDBusReply<Mollet::NetDeviceList> deviceDataList();
-    QDBusReply<Mollet::NetServiceList> serviceDataList( const QString& hostName );
+    QDBusReply<Mollet::NetServiceList> serviceDataList( const QString& hostAddress );
 };
 
 // TODO: is QDBus::Block the right solution here?
-inline QDBusReply<Mollet::NetDevice> NetworkDBusInterface::deviceData( const QString& hostName )
+inline QDBusReply<Mollet::NetDevice> NetworkDBusInterface::deviceData( const QString& hostAddress )
 {
     QList<QVariant> argumentList;
-    argumentList << qVariantFromValue(hostName);
+    argumentList << qVariantFromValue(hostAddress);
     return callWithArgumentList( QDBus::Block, QString::fromLatin1("deviceData"), argumentList );
 }
-inline QDBusReply<Mollet::NetService> NetworkDBusInterface::serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType )
+inline QDBusReply<Mollet::NetService> NetworkDBusInterface::serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType )
 {
     QList<QVariant> argumentList;
-    argumentList << qVariantFromValue(hostName) << qVariantFromValue(serviceName) << qVariantFromValue(serviceType);
+    argumentList << qVariantFromValue(hostAddress) << qVariantFromValue(serviceName) << qVariantFromValue(serviceType);
     return callWithArgumentList( QDBus::Block, QString::fromLatin1("serviceData"), argumentList );
 }
 inline QDBusReply<Mollet::NetDeviceList> NetworkDBusInterface::deviceDataList()
 {
     return call( QString::fromLatin1("deviceDataList") );
 }
-inline QDBusReply<Mollet::NetServiceList> NetworkDBusInterface::serviceDataList( const QString& hostName )
+inline QDBusReply<Mollet::NetServiceList> NetworkDBusInterface::serviceDataList( const QString& hostAddress )
 {
     QList<QVariant> argumentList;
-    argumentList << qVariantFromValue(hostName);
+    argumentList << qVariantFromValue(hostAddress);
     return callWithArgumentList( QDBus::Block, QString::fromLatin1("serviceDataList"), argumentList );
 }
 
Index: runtime/kioslave/network/kded/networkdbusadaptor.cpp
===================================================================
--- runtime/kioslave/network/kded/networkdbusadaptor.cpp	(revision 1079783)
+++ runtime/kioslave/network/kded/networkdbusadaptor.cpp	(revision 1079784)
@@ -43,21 +43,21 @@
     qDBusRegisterMetaType<Mollet::NetServiceList>();
 }
 
-NetDevice NetworkDBusAdaptor::deviceData( const QString& hostName )
+NetDevice NetworkDBusAdaptor::deviceData( const QString& hostAddress )
 {
-    return parent()->deviceData( hostName );
+    return parent()->deviceData( hostAddress );
 }
-NetService NetworkDBusAdaptor::serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType )
+NetService NetworkDBusAdaptor::serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType )
 {
-    return parent()->serviceData( hostName, serviceName, serviceType );
+    return parent()->serviceData( hostAddress, serviceName, serviceType );
 }
 NetDeviceList NetworkDBusAdaptor::deviceDataList()
 {
     return parent()->deviceDataList();
 }
-NetServiceList NetworkDBusAdaptor::serviceDataList( const QString& hostName )
+NetServiceList NetworkDBusAdaptor::serviceDataList( const QString& hostAddress )
 {
-    return parent()->serviceDataList( hostName );
+    return parent()->serviceDataList( hostAddress );
 }
 
 NetworkDBusAdaptor::~NetworkDBusAdaptor()
Index: runtime/kioslave/network/kded/networkdbusadaptor.h
===================================================================
--- runtime/kioslave/network/kded/networkdbusadaptor.h	(revision 1079783)
+++ runtime/kioslave/network/kded/networkdbusadaptor.h	(revision 1079784)
@@ -49,10 +49,10 @@
     NetworkWatcher* parent() const;
 
   public Q_SLOTS:
-    Mollet::NetDevice deviceData( const QString& hostName );
-    Mollet::NetService serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType );
+    Mollet::NetDevice deviceData( const QString& hostAddress );
+    Mollet::NetService serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType );
     Mollet::NetDeviceList deviceDataList();
-    Mollet::NetServiceList serviceDataList( const QString& hostName );
+    Mollet::NetServiceList serviceDataList( const QString& hostAddress );
 };
 
 
Index: runtime/kioslave/network/kded/networkwatcher.cpp
===================================================================
--- runtime/kioslave/network/kded/networkwatcher.cpp	(revision 1079783)
+++ runtime/kioslave/network/kded/networkwatcher.cpp	(revision 1079784)
@@ -46,14 +46,14 @@
 }
 
 // TODO: instead use networkuri and return QVariant for all these
-NetDevice NetworkWatcher::deviceData( const QString& hostName )
+NetDevice NetworkWatcher::deviceData( const QString& hostAddress )
 {
     NetDevice result;
 
     const QList<NetDevice> deviceList = mNetwork->deviceList();
     foreach( const NetDevice& device, deviceList )
     {
-        if( device.hostName() == hostName )
+        if( device.hostAddress() == hostAddress )
         {
             result = device;
             break;
@@ -63,14 +63,14 @@
     return result;
 }
 
-NetService NetworkWatcher::serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType )
+NetService NetworkWatcher::serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType )
 {
     NetService result;
 
     const QList<NetDevice> deviceList = mNetwork->deviceList();
     foreach( const NetDevice& device, deviceList )
     {
-        if( device.hostName() == hostName )
+        if( device.hostAddress() == hostAddress )
         {
             const QList<NetService> serviceList = device.serviceList();
 
@@ -94,14 +94,14 @@
     return mNetwork->deviceList();
 }
 
-NetServiceList NetworkWatcher::serviceDataList( const QString& hostName )
+NetServiceList NetworkWatcher::serviceDataList( const QString& hostAddress )
 {
     NetServiceList result;
 
     const QList<NetDevice> deviceList = mNetwork->deviceList();
     foreach( const NetDevice& device, deviceList )
     {
-        if( device.hostName() == hostName )
+        if( device.hostAddress() == hostAddress )
         {
             result = device.serviceList();
             break;
Index: runtime/kioslave/network/kded/networkwatcher.h
===================================================================
--- runtime/kioslave/network/kded/networkwatcher.h	(revision 1079783)
+++ runtime/kioslave/network/kded/networkwatcher.h	(revision 1079784)
@@ -45,10 +45,10 @@
     virtual ~NetworkWatcher();
 
   public:
-    Mollet::NetDevice deviceData( const QString& hostName );
-    Mollet::NetService serviceData( const QString& hostName, const QString& serviceName, const QString& serviceType );
+    Mollet::NetDevice deviceData( const QString& hostAddress );
+    Mollet::NetService serviceData( const QString& hostAddress, const QString& serviceName, const QString& serviceType );
     Mollet::NetDeviceList deviceDataList();
-    Mollet::NetServiceList serviceDataList( const QString& hostName );
+    Mollet::NetServiceList serviceDataList( const QString& hostAddress );
 
   private:
     Network* mNetwork;
Index: runtime/kioslave/network/kded/kioslavenotifier.cpp
===================================================================
--- runtime/kioslave/network/kded/kioslavenotifier.cpp	(revision 1079783)
+++ runtime/kioslave/network/kded/kioslavenotifier.cpp	(revision 1079784)
@@ -43,9 +43,9 @@
 
 static inline QString idFrom( const NetworkUri& networkUri )
 {
-    return networkUri.hostName().isEmpty() ?    QString() :
-           networkUri.serviceName().isEmpty() ? networkUri.hostName() :
-           /*else*/                             networkUri.hostName()+'/'+networkUri.serviceName();
+    return networkUri.hostAddress().isEmpty() ?    QString() :
+           networkUri.serviceName().isEmpty() ? networkUri.hostAddress() :
+           /*else*/                             networkUri.hostAddress()+'/'+networkUri.serviceName();
 }
 
 static inline QString dirIdFor( const NetDevice& device )
@@ -55,17 +55,17 @@
 }
 static inline QString pathFor( const NetDevice& device )
 {
-    return device.hostName();
+    return device.hostAddress();
 }
 
 static inline QString dirIdFor( const NetService& service )
 {
-    return service.device().hostName();
+    return service.device().hostAddress();
 }
 
 static inline QString pathFor( const NetService& service )
 {
-    return service.device().hostName() + '/' + service.name()+'.'+service.type();
+    return service.device().hostAddress() + '/' + service.name()+'.'+service.type();
 }
 
 
Index: runtime/kioslave/network/network/builder/simpleitemfactory.cpp
===================================================================
--- runtime/kioslave/network/network/builder/simpleitemfactory.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/builder/simpleitemfactory.cpp	(revision 1079784)
@@ -24,6 +24,8 @@
 
 // lib
 #include "netservice_p.h"
+#include "upnp/service.h"
+#include "upnp/device.h"
 // KDE
 #include <KUrl>
 
@@ -191,6 +193,28 @@
     return result;
 }
 
+bool SimpleItemFactory::canCreateNetSystemFromUpnp( const UPnP::Device& upnpDevice ) const
+{
+Q_UNUSED( upnpDevice )
+    return true;
+}
+// TODO: add KIcon with specialiced KIconLoader (fetches Icons via D-Bus)
+NetServicePrivate* SimpleItemFactory::createNetService( const UPnP::Device& upnpDevice, const NetDevice& device ) const
+{
+    NetServicePrivate* result;
+
+    QString url = upnpDevice.presentationUrl();
+    if( url.isEmpty() )
+    {
+        url = QString::fromLatin1( "upnp://" );
+        url.append( upnpDevice.udn() );
+    }
+    result = new NetServicePrivate( upnpDevice.displayName(), QString::fromLatin1("unknown"),
+        "upnp."+upnpDevice.type(), device, url );
+
+    return result;
+}
+
 SimpleItemFactory::~SimpleItemFactory() {}
 
 }
Index: runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.cpp
===================================================================
--- runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.cpp	(revision 0)
+++ runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.cpp	(revision 1079784)
@@ -0,0 +1,220 @@
+/*
+    This file is part of the Mollet network library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "upnpnetworkbuilder.h"
+
+// lib
+#include "upnpnetsystemable.h"
+#include "abstractnetsystemfactory.h"
+#include "network_p.h"
+#include "netdevice_p.h"
+#include "netservice_p.h"
+// KUPnP
+#include <upnp/devicebrowser.h>
+#include <upnp/device.h>
+// Qt
+#include <QtCore/QStringList>
+
+#include <KDebug>
+
+namespace Mollet
+{
+
+UpnpNetworkBuilder::UpnpNetworkBuilder( NetworkPrivate* networkPrivate )
+  : AbstractNetworkBuilder()
+  , mNetworkPrivate( networkPrivate )
+  , mDeviceBrowser( 0 )
+{
+kDebug();
+}
+
+void UpnpNetworkBuilder::registerNetSystemFactory( AbstractNetSystemFactory* netSystemFactory )
+{
+    UpnpNetSystemAble* upnpNetSystemAble = qobject_cast<UpnpNetSystemAble*>( netSystemFactory );
+
+    if( upnpNetSystemAble )
+        mNetSystemFactoryList.append( upnpNetSystemAble );
+}
+
+void UpnpNetworkBuilder::start()
+{
+    mDeviceBrowser = new UPnP::DeviceBrowser();
+
+    connect( mDeviceBrowser, SIGNAL(deviceAdded( const UPnP::Device& )), SLOT(onUPnPDeviceAdded( const UPnP::Device& )) );
+    connect( mDeviceBrowser, SIGNAL(deviceRemoved( const UPnP::Device& )), SLOT(onUPnPDeviceRemoved( const UPnP::Device& )) );
+
+    const QList<UPnP::Device> devices = mDeviceBrowser->devices();
+
+    addUPnPDevices( devices );
+
+    // TODO: works already here, but is this a good design?
+    emit initDone();
+}
+
+void UpnpNetworkBuilder::addUPnPDevices( const QList<UPnP::Device>& upnpDevices )
+{
+    QList<NetDevice> addedDevices;
+    QList<NetService> addedServices;
+
+    QList<NetDevice>& deviceList = mNetworkPrivate->deviceList();
+    foreach( const UPnP::Device& upnpDevice, upnpDevices )
+    {
+        if( upnpDevice.hasParentDevice() )
+            continue;
+
+        const QString ipAddress = upnpDevice.ipAddress();
+
+        NetDevicePrivate* d = 0;
+        const NetDevice* deviceOfService;
+        foreach( const NetDevice& device, deviceList )
+        {
+        const bool isSameAddress = ( device.ipAddress() == ipAddress );
+kDebug()<<"existing device:"<<device.hostName()<<"at"<<device.ipAddress()<<"vs."<<ipAddress<<":"<<isSameAddress;
+            // TODO: lookup hostname and try to use that
+            if( isSameAddress )
+            {
+                d = device.dPtr();
+                deviceOfService = &device;
+                break;
+            }
+        }
+        if( ! d )
+        {
+            const QString displayName = upnpDevice.displayName();
+
+            const QString deviceName = displayName;
+            d = new NetDevicePrivate( deviceName );
+            d->setIpAddress( ipAddress );
+
+            NetDevice device( d );
+            addedDevices.append( device );
+            deviceList.append( device );
+            deviceOfService = &deviceList.last();
+kDebug()<<"new device:"<<deviceName<<"at"<<ipAddress;
+        }
+
+        NetServicePrivate* netServicePrivate = 0;
+        // do a priority based lookup who can build the object
+        // TODO: priorisation
+        foreach( const UpnpNetSystemAble* factory, mNetSystemFactoryList )
+        {
+            if( factory->canCreateNetSystemFromUpnp(upnpDevice) )
+            {
+                // TODO: here we should rather see if this service already exists
+                netServicePrivate = factory->createNetService( upnpDevice, *deviceOfService );
+                break;
+            }
+        }
+
+        NetService netService( netServicePrivate );
+        d->addService( netService );
+
+        addedServices.append( netService );
+kDebug()<<"new service:"<<netService.name()<<netService.url();
+
+        // try guessing the device type by the services on it
+        // TODO: move into  devicefactory
+        const QString serviceType = upnpDevice.type();
+        NetDevice::Type deviceTypeByService = NetDevice::Unknown;
+        QString deviceName;
+        if( serviceType == "InternetGatewayDevice1" )
+            deviceTypeByService = NetDevice::Router;
+
+        if( deviceTypeByService != NetDevice::Unknown )
+        {
+            if( deviceTypeByService > d->type() )
+            {
+                d->setType( deviceTypeByService );
+                if( ! deviceName.isEmpty() )
+                    d->setName( deviceName );
+            }
+        }
+    }
+
+    if( ! addedDevices.isEmpty() )
+        mNetworkPrivate->emitDevicesAdded( addedDevices );
+    if( ! addedServices.isEmpty() )
+        mNetworkPrivate->emitServicesAdded( addedServices );
+}
+
+
+void UpnpNetworkBuilder::removeUPnPDevices( const QList<UPnP::Device>& upnpDevices )
+{
+    QList<NetDevice> removedDevices;
+    QList<NetService> removedServices;
+
+    QList<NetDevice>& deviceList = mNetworkPrivate->deviceList();
+    foreach( const UPnP::Device& upnpDevice, upnpDevices )
+    {
+        const QString ipAddress = upnpDevice.ipAddress();
+
+        QMutableListIterator<NetDevice> it( deviceList );
+        while( it.hasNext())
+        {
+            const NetDevice& device = it.next();
+            if( device.ipAddress() == ipAddress )
+            {
+                NetDevicePrivate* d = device.dPtr();
+                NetService netService = d->removeService( upnpDevice.displayName() );
+                if( ! netService.isValid() )
+                    break;
+
+                removedServices.append( netService );
+
+                // remove device on last service
+                if( d->serviceList().count() == 0 )
+                {
+                    QList<NetDevice> removedDevices;
+                    removedDevices.append( device );
+                    // remove only after taking copy from reference into removed list
+                    it.remove();
+                }
+                break;
+            }
+        }
+    }
+   if( ! removedServices.isEmpty() )
+        mNetworkPrivate->emitServicesRemoved( removedServices );
+   if( ! removedDevices.isEmpty() )
+        mNetworkPrivate->emitDevicesRemoved( removedDevices );
+}
+
+
+void UpnpNetworkBuilder::onUPnPDeviceAdded( const UPnP::Device& device )
+{
+    QList<UPnP::Device> devices;
+    devices.append( device );
+    addUPnPDevices( devices );
+}
+
+void UpnpNetworkBuilder::onUPnPDeviceRemoved( const UPnP::Device& device )
+{
+    QList<UPnP::Device> devices;
+    devices.append( device );
+    removeUPnPDevices( devices );
+}
+
+UpnpNetworkBuilder::~UpnpNetworkBuilder()
+{
+}
+
+}
Index: runtime/kioslave/network/network/builder/upnp/upnpnetsystemable.h
===================================================================
--- runtime/kioslave/network/network/builder/upnp/upnpnetsystemable.h	(revision 0)
+++ runtime/kioslave/network/network/builder/upnp/upnpnetsystemable.h	(revision 1079784)
@@ -0,0 +1,58 @@
+/*
+    This file is part of the Mollet network library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNPNETSYSTEMABLE_H
+#define UPNPNETSYSTEMABLE_H
+
+// Qt
+#include <QtCore/QtPlugin>
+
+namespace UPnP {
+class Device;
+}
+class QString;
+
+
+namespace Mollet
+{
+class NetServicePrivate;
+class NetDevice;
+
+
+class UpnpNetSystemAble
+{
+  public:
+    virtual ~UpnpNetSystemAble();
+
+  public: // API to be implemented
+    virtual bool canCreateNetSystemFromUpnp( const UPnP::Device& upnpDevice ) const = 0;
+    virtual NetServicePrivate* createNetService( const UPnP::Device& upnpDevice, const NetDevice& device ) const = 0;
+};
+
+
+inline UpnpNetSystemAble::~UpnpNetSystemAble() {}
+
+}
+
+Q_DECLARE_INTERFACE( Mollet::UpnpNetSystemAble, "org.kde.mollet.upnpnetsystemable/1.0" )
+
+#endif
Index: runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.h
===================================================================
--- runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.h	(revision 0)
+++ runtime/kioslave/network/network/builder/upnp/upnpnetworkbuilder.h	(revision 1079784)
@@ -0,0 +1,73 @@
+/*
+    This file is part of the Mollet network library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNPNETWORKBUILDER_H
+#define UPNPNETWORKBUILDER_H
+
+// lib
+#include <abstractnetworkbuilder.h>
+#include <network.h>
+#include <netdevice.h>
+
+namespace UPnP {
+class DeviceBrowser;
+class Device;
+}
+
+
+namespace Mollet
+{
+class UpnpNetSystemAble;
+
+
+class UpnpNetworkBuilder : public AbstractNetworkBuilder
+{
+    Q_OBJECT
+
+  public:
+    explicit UpnpNetworkBuilder( NetworkPrivate* networkPrivate );
+    virtual ~UpnpNetworkBuilder();
+
+  public: // AbstractNetworkBuilder API
+    virtual void registerNetSystemFactory( AbstractNetSystemFactory* netSystemFactory );
+    virtual void start();
+    //TODO: void stop(); ? why needed, what to do?
+
+  protected:
+    void addUPnPDevices( const QList<UPnP::Device>& devices );
+    void removeUPnPDevices( const QList<UPnP::Device>& devices );
+
+  private Q_SLOTS:
+    void onUPnPDeviceAdded( const UPnP::Device& device );
+    void onUPnPDeviceRemoved( const UPnP::Device& device );
+
+  private: // data
+    NetworkPrivate* mNetworkPrivate;
+
+    QList<UpnpNetSystemAble*> mNetSystemFactoryList;
+
+    UPnP::DeviceBrowser* mDeviceBrowser;
+};
+
+}
+
+#endif
Index: runtime/kioslave/network/network/builder/simpleitemfactory.h
===================================================================
--- runtime/kioslave/network/network/builder/simpleitemfactory.h	(revision 1079783)
+++ runtime/kioslave/network/network/builder/simpleitemfactory.h	(revision 1079784)
@@ -25,16 +25,22 @@
 
 // lib
 #include <dnssd/dnssdnetsystemable.h>
+#include <upnp/upnpnetsystemable.h>
 #include <abstractnetsystemfactory.h>
 
 
 namespace Mollet
 {
 
-class SimpleItemFactory : public AbstractNetSystemFactory, public DNSSDNetSystemAble
+class SimpleItemFactory : public AbstractNetSystemFactory,
+                          public DNSSDNetSystemAble,
+                          public UpnpNetSystemAble
 {
-    Q_OBJECT
-    Q_INTERFACES( Mollet::DNSSDNetSystemAble )
+  Q_OBJECT
+  Q_INTERFACES(
+    Mollet::DNSSDNetSystemAble
+    Mollet::UpnpNetSystemAble
+  )
 
   public:
     SimpleItemFactory();
@@ -44,6 +50,10 @@
     virtual bool canCreateNetSystemFromDNSSD( const QString& serviceType ) const;
     virtual NetServicePrivate* createNetService( const DNSSD::RemoteService::Ptr& service, const NetDevice& device ) const;
 
+  public: // UpnpNetSystemAble API
+    virtual bool canCreateNetSystemFromUpnp( const UPnP::Device& upnpDevice ) const;
+    virtual NetServicePrivate* createNetService( const UPnP::Device& upnpDevice, const NetDevice& device ) const;
+
   private:
 };
 
Index: runtime/kioslave/network/network/builder/dnssd/dnssdnetworkbuilder.cpp
===================================================================
--- runtime/kioslave/network/network/builder/dnssd/dnssdnetworkbuilder.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/builder/dnssd/dnssdnetworkbuilder.cpp	(revision 1079784)
@@ -28,9 +28,10 @@
 #include "network_p.h"
 #include "netdevice_p.h"
 // KDE
-#include <dnssd/servicetypebrowser.h>
+#include <DNSSD/ServiceTypeBrowser>
 #include <DNSSD/ServiceBrowser>
 // Qt
+#include <QtNetwork/QHostAddress>
 #include <QtCore/QMutableListIterator>
 
 #include <KDebug>
@@ -117,14 +118,27 @@
 {
     QList<NetDevice>& deviceList = mNetworkPrivate->deviceList();
 
-    const QString hostName = service->hostName();
+    QString hostName = service->hostName();
+    // TODO: this blocks. and the ip address should be delivered from DNS-SD with resolve
+    const QHostAddress hostAddress = DNSSD::ServiceBrowser::resolveHostName( hostName );
+    const QString ipAddress = hostAddress.toString();
+    // forget domain name if just ip address
+    if( hostName == ipAddress )
+        hostName = QString();
 
     // device TODO: only search for if we can create the service?
     NetDevicePrivate* d = 0;
     const NetDevice* deviceOfService;
     foreach( const NetDevice& device, deviceList )
     {
-        if( device.hostName() == hostName )
+        const QString deviceHostName = device.hostName();
+        const bool useIpAddress = ( deviceHostName.isEmpty() || hostName.isEmpty() );
+        const bool isSameAddress = useIpAddress ?
+            ( device.ipAddress() == ipAddress ) :
+            ( deviceHostName == hostName );
+kDebug()<<"existing device:"<<deviceHostName<<"at"<<device.ipAddress()<<"vs."<<hostName<<"at"<<ipAddress<<":"<<isSameAddress;
+
+        if( isSameAddress )
         {
             d = device.dPtr();
             deviceOfService = &device;
@@ -134,7 +148,9 @@
     if( !d )
     {
         const QString deviceName = hostName.left( hostName.indexOf('.') );
-        d = new NetDevicePrivate( deviceName, hostName );
+        d = new NetDevicePrivate( deviceName );
+        d->setHostName( hostName );
+        d->setIpAddress( ipAddress );
         NetDevice device( d );
         deviceList.append( device );
         deviceOfService = &deviceList.last();
@@ -146,6 +162,11 @@
         mNetworkPrivate->emitDevicesAdded( newDevices );
 kDebug()<<"new device:"<<deviceName<<"at"<<hostName<<"by"<<service->type();
     }
+    else
+    {
+        if( d->hostName().isEmpty() && ! hostName.isEmpty() )
+            d->setHostName( hostName );
+    }
 
 
     const QString serviceType = service->type();
Index: runtime/kioslave/network/network/netdevice.cpp
===================================================================
--- runtime/kioslave/network/network/netdevice.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/netdevice.cpp	(revision 1079784)
@@ -29,7 +29,7 @@
 namespace Mollet
 {
 
-K_GLOBAL_STATIC_WITH_ARGS(KSharedPtr< NetDevicePrivate >, dummyNetDevicePrivate, ( new NetDevicePrivate(QString(),QString()) ))
+K_GLOBAL_STATIC_WITH_ARGS(KSharedPtr< NetDevicePrivate >, dummyNetDevicePrivate, ( new NetDevicePrivate(QString()) ))
 
 
 QString NetDevice::iconName( Type type )
@@ -59,6 +59,8 @@
 
 QString NetDevice::name() const     { return d->name(); }
 QString NetDevice::hostName() const { return d->hostName(); }
+QString NetDevice::ipAddress() const { return d->ipAddress(); }
+QString NetDevice::hostAddress() const { return d->hostAddress(); }
 NetDevice::Type NetDevice::type() const  { return d->type(); }
 QList<NetService> NetDevice::serviceList() const { return d->serviceList(); }
 
Index: runtime/kioslave/network/network/networkdbus.cpp
===================================================================
--- runtime/kioslave/network/network/networkdbus.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/networkdbus.cpp	(revision 1079784)
@@ -38,6 +38,7 @@
     argument.beginStructure();
     argument << devicePrivate->name();
     argument << devicePrivate->hostName();
+    argument << devicePrivate->ipAddress();
     argument << (int) devicePrivate->type();
     argument.endStructure();
 
@@ -47,15 +48,19 @@
 {
     QString name;
     QString hostName;
+    QString ipAddress;
     int type;
 
     argument.beginStructure();
     argument >> name;
     argument >> hostName;
+    argument >> ipAddress;
     argument >> type;
     argument.endStructure();
 
-    Mollet::NetDevicePrivate* d = new Mollet::NetDevicePrivate( name, hostName );
+    Mollet::NetDevicePrivate* d = new Mollet::NetDevicePrivate( name );
+    d->setHostName( hostName );
+    d->setIpAddress( ipAddress );
     d->setType( (Mollet::NetDevice::Type)type );
 
     device.setDPtr( d );
Index: runtime/kioslave/network/network/network_p.cpp
===================================================================
--- runtime/kioslave/network/network/network_p.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/network_p.cpp	(revision 1079784)
@@ -26,6 +26,7 @@
 #include <config-slp.h>
 // lib
 #include "builder/dnssd/dnssdnetworkbuilder.h"
+#include "builder/upnp/upnpnetworkbuilder.h"
 #include "builder/simpleitemfactory.h"
 #ifdef HAVE_SLP
 #include "builder/slp/slpnetworkbuilder.h"
@@ -47,10 +48,12 @@
     mNetSystemFactoryList.append( simpleItemFactory );
 
     DNSSDNetworkBuilder* dnssdBuilder = new DNSSDNetworkBuilder( this );
+    UpnpNetworkBuilder* upnpBuilder = new UpnpNetworkBuilder( this );
 #ifdef HAVE_SLP
 //     mSlpBuilder = new SlpNetworkBuilder( this );
 #endif
     mNetworkBuilderList.append( dnssdBuilder );
+    mNetworkBuilderList.append( upnpBuilder );
     mNoOfInitBuilders = mNetworkBuilderList.count();
 
     foreach( AbstractNetworkBuilder* builder, mNetworkBuilderList )
Index: runtime/kioslave/network/network/netdevice.h
===================================================================
--- runtime/kioslave/network/network/netdevice.h	(revision 1079783)
+++ runtime/kioslave/network/network/netdevice.h	(revision 1079784)
@@ -49,6 +49,7 @@
 class MOLLETNETWORK_EXPORT NetDevice
 {
     friend class DNSSDNetworkBuilder;
+    friend class UpnpNetworkBuilder;
     friend QDBusArgument& ::operator<<( QDBusArgument& argument, const NetDevice& device );
     friend const QDBusArgument& ::operator>>( const QDBusArgument& argument, NetDevice& device );
 
@@ -65,6 +66,10 @@
   public:
     QString name() const;
     QString hostName() const;
+    /// if hostName is not set, use ipAddress to identify device
+    QString ipAddress() const;
+    /// returns hostName if set, otherwise ipAddress TODO: find better name
+    QString hostAddress() const;
     Type type() const;
     QList<NetService> serviceList() const;
 
Index: runtime/kioslave/network/network/netservice.h
===================================================================
--- runtime/kioslave/network/network/netservice.h	(revision 1079783)
+++ runtime/kioslave/network/network/netservice.h	(revision 1079784)
@@ -49,6 +49,7 @@
 class MOLLETNETWORK_EXPORT NetService
 {
     friend class DNSSDNetworkBuilder;
+    friend class UpnpNetworkBuilder;
     friend QDBusArgument& ::operator<<( QDBusArgument& argument, const NetService& service );
     friend const QDBusArgument& ::operator>>( const QDBusArgument& argument, NetService& service );
 
Index: runtime/kioslave/network/network/netdevice_p.cpp
===================================================================
--- runtime/kioslave/network/network/netdevice_p.cpp	(revision 1079783)
+++ runtime/kioslave/network/network/netdevice_p.cpp	(revision 1079784)
@@ -29,9 +29,8 @@
 namespace Mollet
 {
 
-NetDevicePrivate::NetDevicePrivate( const QString& name, const QString& hostName )
+NetDevicePrivate::NetDevicePrivate( const QString& name )
   : mName( name )
-  , mHostName( hostName )
   , mType( NetDevice::Unknown )
 {
 }
Index: runtime/kioslave/network/network/netdevice_p.h
===================================================================
--- runtime/kioslave/network/network/netdevice_p.h	(revision 1079783)
+++ runtime/kioslave/network/network/netdevice_p.h	(revision 1079784)
@@ -38,17 +38,21 @@
 class NetDevicePrivate : public QSharedData
 {
   public:
-    explicit NetDevicePrivate( const QString& name, const QString& hostName );
+    explicit NetDevicePrivate( const QString& name );
     virtual ~NetDevicePrivate();
 
   public:
     const QString& name() const;
     const QString& hostName() const;
+    const QString& ipAddress() const;
+    const QString& hostAddress() const;
     NetDevice::Type type() const;
     const QList<NetService>& serviceList() const;
 
   public:
     void setName( const QString& name );
+    void setHostName( const QString& hostName );
+    void setIpAddress( const QString& ipAddress );
     void setType( NetDevice::Type type );
     void addService( const NetService& service );
     NetService removeService( const QString& serviceName );
@@ -56,17 +60,22 @@
   private:
     QString mName;
     QString mHostName;
+    QString mIpAddress;
     NetDevice::Type mType;
     QList<NetService> mServiceList;
 };
 
 
-inline const QString& NetDevicePrivate::name()     const { return mName; }
-inline const QString& NetDevicePrivate::hostName() const { return mHostName; }
-inline NetDevice::Type NetDevicePrivate::type()    const { return mType; }
+inline const QString& NetDevicePrivate::name()      const { return mName; }
+inline const QString& NetDevicePrivate::hostName()  const { return mHostName; }
+inline const QString& NetDevicePrivate::ipAddress() const { return mIpAddress; }
+inline NetDevice::Type NetDevicePrivate::type()     const { return mType; }
 inline const QList<NetService>& NetDevicePrivate::serviceList() const { return mServiceList; }
+inline const QString& NetDevicePrivate::hostAddress() const { return mHostName.isEmpty() ? mIpAddress : mHostName; }
 
 inline void NetDevicePrivate::setName( const QString& name ) { mName = name; }
+inline void NetDevicePrivate::setHostName( const QString& hostName ) { mHostName = hostName; }
+inline void NetDevicePrivate::setIpAddress( const QString& ipAddress ) { mIpAddress = ipAddress; }
 inline void NetDevicePrivate::setType( NetDevice::Type type ) { mType = type; }
 inline void NetDevicePrivate::addService( const NetService& service ) { mServiceList.append( service ); }
 
Index: runtime/kioslave/network/network/CMakeLists.txt
===================================================================
--- runtime/kioslave/network/network/CMakeLists.txt	(revision 1079783)
+++ runtime/kioslave/network/network/CMakeLists.txt	(revision 1079784)
@@ -1,11 +1,13 @@
 project( molletnetwork )
 
+set( LIBKUPNP_REL_DIR ../kupnp/lib )
 
 macro_bool_to_01( SLP_FOUND  HAVE_SLP )
 configure_file( config-slp.h.cmake  ${CMAKE_CURRENT_BINARY_DIR}/config-slp.h )
 
 include_directories(
   builder
+  ${LIBKUPNP_REL_DIR}
 )
 
 set( netsystemdriver_SRCS
@@ -24,6 +26,10 @@
   builder/dnssd/dnssdnetworkbuilder.cpp
 )
 
+set( upnpnetworkbuilder_SRCS
+  builder/upnp/upnpnetworkbuilder.cpp
+)
+
 set( networkbuilder_SRCS
   builder/abstractnetworkbuilder.cpp
   builder/abstractnetsystemfactory.cpp
@@ -36,6 +42,7 @@
 set( molletnetwork_LIB_SRCS
   ${netsystemdriver_SRCS}
 #   ${slpnetworkbuilder_SRCS}
+  ${upnpnetworkbuilder_SRCS}
   ${dnssdnetworkbuilder_SRCS}
   ${networkbuilder_SRCS}
   ${networkdbus_LIB_SRCS}
@@ -48,7 +55,7 @@
 )
 
 
-set( molletnetwork_LINK_LIBS  ${KDE4_KDECORE_LIBS}  ${KDE4_KDNSSD_LIBS} )
+set( molletnetwork_LINK_LIBS  kupnp ${KDE4_KDECORE_LIBS}  ${KDE4_KDNSSD_LIBS} ${QT_QTNETWORK_LIBRARY} )
 
 if(SLP_FOUND)
 set( molletnetwork_LINK_LIBS  ${molletnetwork_LINK_LIBS} ${SLP_LIBRARIES} )
Index: runtime/kioslave/network/mimetypes/network.xml
===================================================================
--- runtime/kioslave/network/mimetypes/network.xml	(revision 1079783)
+++ runtime/kioslave/network/mimetypes/network.xml	(revision 1079784)
@@ -274,7 +274,109 @@
     <comment>RealPlayer Shared Favorites</comment>
   </mime-type>
 
+  <!-- UPnP -->
+  <mime-type type="inode/vnd.kde.service.upnp.BasicDevice1">
+    <generic-icon name="network-server"/>
+    <comment>UPnP Basic Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.WLANAccessPointDevice1">
+    <generic-icon name="network-wireless"/>
+    <comment>UPnP WLAN Access Point Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.InternetGatewayDevice1">
+    <generic-icon name="network-server"/>
+    <comment>UPnP Internet Gateway Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.PrinterBasic1">
+    <generic-icon name="printer"/>
+    <comment>UPnP Printer (Basic)</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.PrinterEnhanced1">
+    <generic-icon name="printer"/>
+    <comment>UPnP Printer (Enhanced)</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.Scanner1">
+    <generic-icon name="scanner"/>
+    <comment>UPnP Scanner</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.MediaServer1">
+    <generic-icon name="folder-remote"/>
+    <comment>UPnP Media Server</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.MediaRenderer1">
+    <generic-icon name="terminal"/>
+    <comment>UPnP Media Renderer</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.MediaServer2">
+    <generic-icon name="folder-remote"/>
+    <comment>UPnP Media Server</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.MediaRenderer2">
+    <generic-icon name="terminal"/>
+    <comment>UPnP Media Renderer</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.MediaServer3">
+    <generic-icon name="folder-remote"/>
+    <comment>UPnP Media Server</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.SolarProtectionBlind1">
+    <generic-icon name="device"/>
+    <comment>UPnP Solar Protection Blind</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.DigitalSecurityCamera1">
+    <generic-icon name="camera"/>
+    <comment>UPnP Digital Security Camera</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.HVAC1">
+    <generic-icon name="device"/>
+    <comment>UPnP HVAC</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.LightingControls1">
+    <generic-icon name="light"/>
+    <comment>UPnP Lighting Controls</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.RemoteUIClient1">
+    <generic-icon name="printer"/>
+    <comment>UPnP Remote UI Client</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.RemoteUIServer1">
+    <generic-icon name="printer"/>
+    <comment>UPnP Remote UI Server</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.Unknown">
+    <generic-icon name="device"/>
+    <comment>Unknown UPnP Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
 
+  <mime-type type="inode/vnd.kde.service.upnp.WANDevice1">
+    <generic-icon name="network-wireless"/>
+    <comment>UPnP WAN Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+  <mime-type type="inode/vnd.kde.service.upnp.WANConnectionDevice1">
+    <generic-icon name="network-wireless"/>
+    <comment>UPnP WAN Connection Device</comment>
+    <expanded-acronym>UPnP Universal Plug and Play</expanded-acronym>
+  </mime-type>
+
   <!-- uri/ fake mime types -->
 <!--  <mime-type type="uri/mms">
     <comment>mms: URIs</comment>
Index: runtime/kioslave/network/CMakeLists.txt
===================================================================
--- runtime/kioslave/network/CMakeLists.txt	(revision 1079783)
+++ runtime/kioslave/network/CMakeLists.txt	(revision 1079784)
@@ -2,3 +2,4 @@
 add_subdirectory( ioslave )
 add_subdirectory( kded )
 add_subdirectory( mimetypes )
+add_subdirectory( kupnp )
Index: runtime/kioslave/network/kupnp/browser/main.cpp
===================================================================
--- runtime/kioslave/network/kupnp/browser/main.cpp	(revision 0)
+++ runtime/kioslave/network/kupnp/browser/main.cpp	(revision 1079784)
@@ -0,0 +1,58 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of
+    the License or (at your option) version 3 or any later version
+    accepted by the membership of KDE e.V. (or its successor approved
+    by the membership of KDE e.V.), which shall act as a proxy 
+    defined in Section 14 of version 3 of the license.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// lib
+#include <devicebrowser.h>
+#include <device.h>
+#include <service.h>
+// KDE
+#include <KApplication>
+#include <KCmdLineArgs>
+#include <KAboutData>
+// Qt
+#include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+
+
+int main( int argc, char* argv[] )
+{
+    KAboutData aboutData( "kupnpbrowser", "KUpnpBrowser", ki18n(""), "", ki18n("") );
+    KCmdLineArgs::init( argc, argv, &aboutData );
+    KApplication programCore;
+
+    UPnP::DeviceBrowser deviceBrowser;
+    const QList<UPnP::Device> devices = deviceBrowser.devices();
+
+    QTextStream out( stdout );
+    foreach( const UPnP::Device& device, devices )
+    {
+        const QList<UPnP::Service> services = device.services();
+
+        out << device.displayName() << " ("<<device.type()<<")"<<endl;
+        foreach( const UPnP::Service& service, services )
+            out << "* " << service.displayName() << " ("<<service.type()<<")"<<endl;
+    }
+
+    // run loop at least once
+    QTimer::singleShot( 0, &programCore, SLOT(quit()) );
+    return programCore.exec();
+}
Index: runtime/kioslave/network/kupnp/browser/CMakeLists.txt
===================================================================
--- runtime/kioslave/network/kupnp/browser/CMakeLists.txt	(revision 0)
+++ runtime/kioslave/network/kupnp/browser/CMakeLists.txt	(revision 1079784)
@@ -0,0 +1,18 @@
+include_directories(
+  ../lib
+)
+
+set( kupnpbrowser_SRCS
+  main.cpp
+)
+
+kde4_add_executable( kupnpbrowser  ${kupnpbrowser_SRCS} )
+
+target_link_libraries( kupnpbrowser
+  kupnp
+  ${KDE4_KDEUI_LIBS}
+  ${QT_QTGUI_LIBRARY}
+  ${QT_QTCORE_LIBRARY}
+)
+
+install( TARGETS kupnpbrowser  ${INSTALL_TARGETS_DEFAULT_ARGS} )
Index: runtime/kioslave/network/kupnp/lib/device.cpp
===================================================================
--- runtime/kioslave/network/kupnp/lib/device.cpp	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/device.cpp	(revision 1079784)
@@ -0,0 +1,72 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "device.h"
+#include "device_p.h"
+
+
+namespace UPnP
+{
+
+Device::Device()
+  : d( new DevicePrivate() )
+{}
+
+Device::Device( DevicePrivate* _d )
+  : d( _d )
+{
+}
+
+Device::Device( const Device& other )
+  : d( other.d )
+{
+}
+
+
+QString Device::udn() const { return d->udn(); }
+QString Device::displayName() const { return d->displayName(); }
+QString Device::type() const { return d->type(); }
+QList<Service> Device::services() const { return d->services(); }
+QString Device::ipAddress() const { return d->ipAddress(); }
+int Device::ipPortNumber() const { return d->ipPortNumber(); }
+QString Device::presentationUrl() const { return d->presentationUrl(); }
+Device Device::parentDevice() const { return d->parentDevice(); }
+QList<Device> Device::childDevices() const { return d->childDevices(); }
+bool Device::hasParentDevice() const { return d->hasParentDevice(); }
+bool Device::isValid() const { return d->isValid(); }
+
+Device& Device::operator =( const Device& other )
+{
+    d = other.d;
+    return *this;
+}
+
+bool Device::operator==( const Device& other ) const
+{
+    return ( d == other.d );
+}
+
+Device::~Device()
+{
+}
+
+}
Index: runtime/kioslave/network/kupnp/lib/org.Coherence.xml
===================================================================
--- runtime/kioslave/network/kupnp/lib/org.Coherence.xml	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/org.Coherence.xml	(revision 1079784)
@@ -0,0 +1,116 @@
+<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="introspect.xsl"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+  This file is part of ?
+  Found by introspection output via qdbusviewer
+
+  License
+-->
+
+<node>
+    <interface name="org.Coherence">
+        <method name="pin">
+            <arg direction="in" type="s" name="key" />
+            <arg direction="in" type="v" name="value" />
+        </method>
+        <method name="create_oob">
+            <arg direction="in" type="s" name="file" />
+            <arg direction="out" type="s" />
+        </method>
+        <signal name="DMR_added">
+            <arg type="v" name="device" />
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="import_resource">
+            <arg direction="in" type="s" name="device_id" />
+            <arg direction="in" type="s" name="source_uri" />
+            <arg direction="in" type="s" name="destination_uri" />
+            <arg direction="out" type="v" />
+        </method>
+        <signal name="DMS_added">
+            <arg type="v" name="device" />
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="get_device_with_id">
+            <arg direction="in" type="s" name="id" />
+            <arg direction="out" type="v" />
+        </method>
+        <method name="get_devices_async">
+            <arg direction="out" type="av" />
+        </method>
+        <method name="put_resource">
+            <arg direction="in" type="s" name="destination_uri" />
+            <arg direction="in" type="s" name="filepath" />
+            <arg direction="out" type="v" />
+        </method>
+        <method name="hostname">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="version">
+            <arg direction="out" type="s" />
+        </method>
+        <signal name="DMS_removed">
+            <arg type="s" name="udn" />
+        </signal>
+        <signal name="UPnP_ControlPoint_MediaServer_removed">
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="create_object">
+            <arg direction="in" type="s" name="device_id" /> 
+            <arg direction="in" type="s" name="container_id" /> 
+            <arg direction="in" type="a{ss}" name="arguments" /> 
+            <arg direction="out" type="v" />
+            <annotation name="com.trolltech.QtDBus.QtTypeName.In2" value="QVariantMap"/>
+        </method> 
+        <signal name="DMR_removed">
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="remove_plugin">
+            <arg direction="in" type="s" name="uuid" />
+            <arg direction="out" type="s" />
+        </method>
+        <signal name="UPnP_ControlPoint_MediaRenderer_detected">
+            <arg type="v" name="device" />
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="add_plugin">
+            <arg direction="in" type="s" name="backend" />
+            <arg direction="in" type="a{ss}" name="arguments" />
+            <arg direction="out" type="s" />
+            <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+        </method>
+        <signal name="UPnP_ControlPoint_MediaServer_detected">
+            <arg type="v" name="device" />
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="call_plugin">
+            <arg direction="in" type="s" name="uuid" />
+            <arg direction="in" type="s" name="method" />
+            <arg direction="in" type="a{ss}" name="arguments" />
+            <arg direction="out" type="s" />
+            <annotation name="com.trolltech.QtDBus.QtTypeName.In2" value="QVariantMap"/>
+        </method> 
+        <method name="get_devices">
+            <arg direction="out" type="av" />
+        </method>
+        <signal name="UPnP_ControlPoint_MediaRenderer_removed">
+            <arg type="s" name="udn" />
+        </signal>
+        <signal name="device_removed">
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="unpin">
+            <arg direction="in" type="s" name="key" />
+        </method>
+        <signal name="device_detected">
+            <arg type="v" name="device" />
+            <arg type="s" name="udn" />
+        </signal>
+        <method name="get_pin">
+            <arg direction="in" type="s" name="key" />
+            <arg direction="out" type="v" />
+        </method>
+    </interface>
+</node>
Index: runtime/kioslave/network/kupnp/lib/service.cpp
===================================================================
--- runtime/kioslave/network/kupnp/lib/service.cpp	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/service.cpp	(revision 1079784)
@@ -0,0 +1,61 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "service.h"
+#include "service_p.h"
+
+
+namespace UPnP
+{
+
+Service::Service()
+  : d( new ServicePrivate() ) // TODO: would a static default null object increase performance?
+{}
+
+Service::Service( ServicePrivate* _d )
+  : d( _d )
+{
+}
+
+Service::Service( const Service& other )
+  : d( other.d )
+{
+}
+
+// QString Service::udn() const { return d->udn(); }
+Device Service::device() const { return d->device(); }
+
+QString Service::displayName() const { return d->displayName(); }
+QString Service::type() const  { return d->type(); }
+
+
+Service& Service::operator =( const Service& other )
+{
+    d = other.d;
+    return *this;
+}
+
+Service::~Service()
+{
+}
+
+}
Index: runtime/kioslave/network/kupnp/lib/devicebrowser_p.cpp
===================================================================
--- runtime/kioslave/network/kupnp/lib/devicebrowser_p.cpp	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/devicebrowser_p.cpp	(revision 1079784)
@@ -0,0 +1,284 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+    Copyright 2009 Adriaan de Groot <groot@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as argument proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received argument copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "devicebrowser_p.h"
+
+// lib
+#include "device_p.h"
+#include "service_p.h"
+// Qt
+#include <QtDBus/QDBusArgument>
+
+#include <QtCore/QDebug>
+
+namespace UPnP
+{
+
+static const char requiredCoherenceVersionString[] = "0.6.5";
+static const int requiredCoherenceVersion[] = {0,6,5};
+static const int requiredCoherenceVersionLength =
+    sizeof(requiredCoherenceVersion) / sizeof(requiredCoherenceVersion[0]);
+
+
+static bool checkVersion( const QString& coherenceVersionString )
+{
+    const QStringList coherenceVersionParts = coherenceVersionString.split( '.' );
+
+    for( int i=0; i<requiredCoherenceVersionLength; ++i )
+    {
+        const int versionPart = coherenceVersionParts[i].toInt();
+        if( requiredCoherenceVersion[i] < versionPart )
+            break;
+
+        if( requiredCoherenceVersion[i] > versionPart )
+        {
+qDebug() << "Coherence version" << coherenceVersionString << "is not ok,"
+         << requiredCoherenceVersionString << "required.";
+            return false;
+        }
+    }
+qDebug() << "Coherence version" << coherenceVersionString << "is ok.";
+
+    return true;
+}
+
+QList<UPnP::Service> DeviceBrowserPrivate::demarshallServices( const Device& device, const QVariant& variant )
+{
+    QList<UPnP::Service> result;
+
+    const QStringList serviceDBusPathList = variant.value<QStringList>();
+    foreach( const QString& serviceDBusPath, serviceDBusPathList )
+    {
+        const QString typeName = serviceDBusPath.mid( serviceDBusPath.lastIndexOf('/')+1 );
+
+        ServicePrivate* servicePrivate = new ServicePrivate();
+        servicePrivate->setDevice( device );
+        servicePrivate->setDisplayName( typeName );
+        servicePrivate->setType( typeName );
+        servicePrivate->setDBusPath( serviceDBusPath );
+
+        result.append( Service(servicePrivate) );
+    }
+
+    return result;
+}
+
+Device DeviceBrowserPrivate::addDevice( const QDBusArgument& dBusArgument )
+{
+    DevicePrivate* devicePrivate = new DevicePrivate();
+    Device device( devicePrivate );
+
+    QString parentUdn;
+
+    dBusArgument.beginMap();
+    while( ! dBusArgument.atEnd() )
+    {
+        dBusArgument.beginMapEntry();
+        QString key;
+        QDBusVariant dBusVariant;
+        dBusArgument >> key >> dBusVariant;
+        const QVariant variant = dBusVariant.variant();
+
+        if( key == QLatin1String("udn") )
+        {
+            const QString uuid = variant.value<QString>().mid( 5 );
+            devicePrivate->setUdn( uuid );
+        }
+        else if( key == QLatin1String("friendly_name") )
+            devicePrivate->setDisplayName( variant.value<QString>() );
+        else if( key == QLatin1String("parent_udn") )
+            parentUdn = variant.value<QString>().mid( 5 );
+        else if( key == QLatin1String("device_type") )
+        {
+            const QStringList typeParts = variant.value<QString>().split( ':' );
+            devicePrivate->setType( typeParts[3]+typeParts[4] );
+        }
+        else if( key == QLatin1String("path") )
+            devicePrivate->setDBusPath( variant.value<QString>() );
+        else if( key == QLatin1String("presentation_url") )
+            devicePrivate->setPresentationUrl( variant.value<QString>() );
+        else if( key == QLatin1String("uri") )
+        {
+            const QString hostAddressAndPort = variant.value<QStringList>()[1];
+            const int indexOfSeparator = hostAddressAndPort.indexOf( ':' );
+            const QString hostAddress = hostAddressAndPort.left( indexOfSeparator );
+            const int portNumber = hostAddressAndPort.mid( indexOfSeparator+1 ).toInt();
+            devicePrivate->setIpAddress( hostAddress );
+            devicePrivate->setIpPortNumber( portNumber );
+        }
+        else if( key == QLatin1String("services") )
+        {
+            QList<Service> services = demarshallServices( device, variant );
+            devicePrivate->setServices( services );
+        }
+//         else
+        {
+            if( variant.canConvert<QString>())
+            {
+                const QString value = variant.value<QString>();
+qDebug() << "  " << key << value;
+            }
+            else
+            {
+qDebug() << "  " << key << "-not argument string-";
+            }
+        }
+        dBusArgument.endMapEntry();
+    }
+    dBusArgument.endMap();
+
+    const QString& udn = devicePrivate->udn();
+    if( udn.isEmpty() )
+    {
+qDebug()<<"No udn found!";
+        devicePrivate->setInvalid();
+    }
+    else if( mDevices.contains(udn) )
+    {
+qDebug()<<"Already inserted:"<<udn<<"!";
+        devicePrivate->setInvalid();
+    }
+    else if( ! mBrowsedDeviceTypes.isEmpty() && ! mBrowsedDeviceTypes.contains(devicePrivate->type()) )
+    {
+qDebug()<<"Not interested in:"<<devicePrivate->type();
+        devicePrivate->setInvalid();
+    }
+    else
+    {
+qDebug()<<"Adding: "<<device.displayName()<<udn;
+        mDevices[udn] = device;
+
+        if( ! parentUdn.isEmpty() )
+        {
+            if( mDevices.contains(parentUdn) )
+            {
+                devicePrivate->setParentDevice( mDevices[parentUdn].dPtr() );
+                // TODO: else set to pending devices waiting for their parent device streamed
+                // but how to find about orphaned devices? might increase by time if the backend is broken
+                // what to do if devices browsed are filtered? set a flag like wouldHaveParent?
+            }
+        }
+    }
+
+    return device;
+}
+
+
+
+void DeviceBrowserPrivate::init()
+{
+qDebug() << "Connecting to Coherence...";
+
+    // TODO: or use system bus?
+    mCoherence = new org::Coherence( "org.Coherence", "/org/Coherence", QDBusConnection::sessionBus()/*systemBus*/, q );
+
+    QDBusPendingReply<QString> versionReply = mCoherence->version();
+    versionReply.waitForFinished();
+    if( versionReply.isError() )
+    {
+qDebug()<< versionReply.error();
+        return;
+    }
+
+    const QString version = versionReply.value();
+
+    const bool versionOk = checkVersion( version );
+    if( ! versionOk )
+        return;
+
+    connect( mCoherence, SIGNAL(device_detected( const QDBusVariant&, const QString& )),
+             SLOT(onDeviceAdded( const QDBusVariant&, const QString& )) );
+
+    connect( mCoherence, SIGNAL(device_removed(const QString& )),
+             SLOT(onDeviceRemoved( const QString& )) );
+
+    QDBusPendingReply<QVariantList> devicesReply = mCoherence->get_devices();
+    devicesReply.waitForFinished();
+    if( devicesReply.isError() )
+    {
+qDebug()<< devicesReply.error();
+        return;
+    }
+
+qDebug()<< "Current devices...";
+    QVariantList devicesReplyValue = devicesReply.value();
+    foreach( const QVariant& devicesReplyValueItem, devicesReplyValue )
+    {
+        const QVariant variant = qvariant_cast<QDBusVariant>( devicesReplyValueItem ).variant();
+        const QDBusArgument dBusArgument = variant.value<QDBusArgument>();
+        addDevice( dBusArgument );
+    }
+qDebug()<<"That's all.";
+}
+
+QList<Device> DeviceBrowserPrivate::devices() const
+{
+    QList<Device> result;
+
+    QHashIterator<QString,Device> it( mDevices);
+    while( it.hasNext() )
+    {
+        it.next();
+        result.append( it.value() );
+    }
+
+    return result;
+}
+
+void DeviceBrowserPrivate::onDeviceAdded( const QDBusVariant& dBusVariant, const QString& udn )
+{
+    Q_UNUSED( udn );
+
+    const QVariant variant = dBusVariant.variant();
+    const QDBusVariant sv = variant.value<QDBusVariant>();
+    const QVariant v = sv.variant();
+    const QDBusArgument dBusArgument = v.value<QDBusArgument>();
+
+    Device device = addDevice( dBusArgument );
+    if( device.isValid() )
+        emit q->deviceAdded( device );
+}
+
+void DeviceBrowserPrivate::onDeviceRemoved( const QString& _udn )
+{
+    const QString udn = _udn.mid( 5 );
+    QHash<QString,Device>::Iterator it = mDevices.find( udn );
+    if( it != mDevices.end() )
+    {
+        Device device = it.value();
+        mDevices.erase( it );
+qDebug() << "Removing"<<device.displayName();
+        emit q->deviceRemoved( device );
+    }
+    else
+qDebug() << "Not found in device list:"<<udn;
+}
+
+
+DeviceBrowserPrivate::~DeviceBrowserPrivate()
+{
+    delete mCoherence;
+}
+
+
+}
Index: runtime/kioslave/network/kupnp/lib/device_p.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/device_p.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/device_p.h	(revision 1079784)
@@ -0,0 +1,147 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_DEVICE_P_H
+#define UPNP_DEVICE_P_H
+
+// lib
+#include "device.h"
+#include "service.h"
+// Qt
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QSharedData>
+
+
+namespace UPnP
+{
+
+class DevicePrivate : public QSharedData
+{
+  public:
+    DevicePrivate();
+
+    ~DevicePrivate();
+
+  public:
+    const QString& udn() const;
+    const QString& displayName() const;
+    const QString& type() const;
+    const QString& ipAddress() const;
+    int ipPortNumber() const;
+    const QString& presentationUrl() const;
+    const QString& dBusPath() const;
+    const QList<Service>& services() const;
+    Device parentDevice() const;
+    const QList<Device>& childDevices() const;
+
+    bool hasParentDevice() const;
+    bool isValid() const;
+
+  public:
+    void setUdn( const QString& udn );
+    void setType( const QString& deviceType );
+    void setDisplayName( const QString& displayName );
+    void setIpAddress( const QString& ipAddress );
+    void setIpPortNumber( int portNumber );
+    void setPresentationUrl( const QString& presentationUrl );
+    void setDBusPath( const QString& dBusPath );
+    void setServices( const QList<Service>& services );
+    void setParentDevice( DevicePrivate* parentDevicePrivate );
+
+    void setInvalid();
+
+    void addChildDevice( DevicePrivate* childDevice );
+    void removeChildDevice( DevicePrivate* childDevice );
+
+  protected:
+    // TODO: could just be a QByteArray
+    QString mUdn;
+    QString mDeviceType;
+    QString mDisplayName;
+    QString mIpAddress;
+    int mPortNumber;
+    QString mPresentationUrl;
+    QString mDBusPath;
+
+    QList<Service> mServices;
+
+    //just pointer to private to avoid circular refcounting
+    DevicePrivate* mParentDevicePrivate;
+    QList<Device> mChildDevices;
+};
+
+
+inline DevicePrivate::DevicePrivate()
+ : mParentDevicePrivate( 0 )
+{}
+
+inline const QString& DevicePrivate::udn() const { return mUdn; }
+inline const QString& DevicePrivate::type() const { return mDeviceType; }
+inline const QString& DevicePrivate::displayName() const { return mDisplayName; }
+inline const QString& DevicePrivate::ipAddress() const { return mIpAddress; }
+inline int DevicePrivate::ipPortNumber() const { return mPortNumber; }
+inline const QString& DevicePrivate::presentationUrl() const { return mPresentationUrl; }
+inline const QString& DevicePrivate::dBusPath() const { return mDBusPath; }
+inline const QList<Service>& DevicePrivate::services() const { return mServices; }
+inline Device DevicePrivate::parentDevice() const { return Device(mParentDevicePrivate); }
+inline const QList<Device>& DevicePrivate::childDevices() const { return mChildDevices; }
+inline bool DevicePrivate::hasParentDevice() const { return (mParentDevicePrivate != 0); }
+inline bool DevicePrivate::isValid() const { return ! mUdn.isEmpty(); }
+
+inline void DevicePrivate::setUdn( const QString& udn ) { mUdn = udn; }
+inline void DevicePrivate::setType( const QString& deviceType ) { mDeviceType = deviceType; }
+inline void DevicePrivate::setDisplayName( const QString& displayName ) { mDisplayName = displayName; }
+inline void DevicePrivate::setIpAddress( const QString& ipAddress ) { mIpAddress = ipAddress; }
+inline void DevicePrivate::setIpPortNumber( int portNumber ) { mPortNumber = portNumber; }
+inline void DevicePrivate::setPresentationUrl( const QString& presentationUrl ) { mPresentationUrl = presentationUrl; }
+inline void DevicePrivate::setDBusPath( const QString& dBusPath ) { mDBusPath = dBusPath; }
+inline void DevicePrivate::setServices( const QList<Service>& services ) { mServices = services; }
+inline void DevicePrivate::setParentDevice( DevicePrivate* parentDevicePrivate )
+{
+    mParentDevicePrivate = parentDevicePrivate;
+    if( mParentDevicePrivate )
+        mParentDevicePrivate->addChildDevice( this );
+}
+
+inline void DevicePrivate::setInvalid() { mUdn.clear(); }
+
+inline void DevicePrivate::addChildDevice( DevicePrivate* childDevice )
+{
+    mChildDevices.append( Device(childDevice) );
+}
+inline void DevicePrivate::removeChildDevice( DevicePrivate* childDevice )
+{
+    mChildDevices.removeOne( Device(childDevice) );
+}
+
+inline DevicePrivate::~DevicePrivate()
+{
+    if( mParentDevicePrivate )
+        mParentDevicePrivate->removeChildDevice( this );
+    foreach( const Device& device, mChildDevices )
+        device.dPtr()->setParentDevice( 0 );
+}
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/devicebrowser.cpp
===================================================================
--- runtime/kioslave/network/kupnp/lib/devicebrowser.cpp	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/devicebrowser.cpp	(revision 1079784)
@@ -0,0 +1,56 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "devicebrowser.h"
+#include "devicebrowser_p.h"
+
+
+namespace UPnP
+{
+
+DeviceBrowser::DeviceBrowser( const QStringList& deviceTypes )
+  : d( new DeviceBrowserPrivate(this,deviceTypes) )
+{
+    d->init();
+}
+DeviceBrowser::DeviceBrowser( const QString& deviceType )
+  : d( new DeviceBrowserPrivate(this,deviceType) )
+{
+    d->init();
+}
+
+QList<Device> DeviceBrowser::devices() const
+{
+    return d->devices();
+}
+
+QStringList DeviceBrowser::browsedDeviceTypes() const
+{
+    return d->browsedDeviceTypes();
+}
+
+DeviceBrowser::~DeviceBrowser()
+{
+    delete d;
+}
+
+}
Index: runtime/kioslave/network/kupnp/lib/device.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/device.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/device.h	(revision 1079784)
@@ -0,0 +1,86 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_DEVICE_H
+#define UPNP_DEVICE_H
+
+// lib
+#include "upnp_export.h"
+// Qt
+#include <QtCore/QExplicitlySharedDataPointer>
+
+template<class T> class QList;
+
+
+namespace UPnP
+{
+class DevicePrivate;
+class Service;
+
+
+class KUPNP_EXPORT Device
+{
+  friend class ServicePrivate;
+  friend class DevicePrivate;
+  friend class DeviceBrowserPrivate;
+
+  protected:
+    explicit Device( DevicePrivate* d );
+
+  public:
+    Device();
+    Device( const Device& other );
+
+    virtual ~Device();
+
+  public:
+    /// without the prefix "uuid:"
+    QString udn() const;
+    QString displayName() const;
+    QString type() const;
+    QString ipAddress() const;
+    int ipPortNumber() const;
+    QString presentationUrl() const;
+    QList<Service> services() const;
+    Device parentDevice() const;
+    QList<Device> childDevices() const;
+
+    bool hasParentDevice() const;
+    bool isValid() const;
+
+  public:
+    Device& operator =( const Device& other );
+    bool operator==( const Device& other ) const;
+
+  private:
+    DevicePrivate* dPtr() const;
+
+  protected:
+    QExplicitlySharedDataPointer<DevicePrivate> d;
+};
+
+
+inline  DevicePrivate* Device::dPtr() const { return const_cast<DevicePrivate*>( d.data() ); }
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/service_p.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/service_p.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/service_p.h	(revision 1079784)
@@ -0,0 +1,81 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_SERVICE_P_H
+#define UPNP_SERVICE_P_H
+
+// lib
+#include "service.h"
+#include "device.h"
+// Qt
+#include <QtCore/QString>
+#include <QtCore/QSharedData>
+
+
+namespace UPnP
+{
+
+class ServicePrivate : public QSharedData
+{
+  public:
+    ServicePrivate();
+
+    ~ServicePrivate();
+
+  public:
+    const Device& device() const;
+    const QString& displayName() const;
+    const QString& type() const;
+    const QString& dBusPath() const;
+
+  public:
+    void setDevice( const Device& device );
+    void setDisplayName( const QString& displayName );
+    void setType( const QString& type );
+    void setDBusPath( const QString& dBusPath );
+
+  protected:
+    Device mDevice;
+
+    QString mDisplayName;
+    QString mType;
+    QString mDBusPath;
+};
+
+
+inline ServicePrivate::ServicePrivate() {}
+
+inline const Device& ServicePrivate::device() const { return mDevice; }
+inline const QString& ServicePrivate::displayName() const { return mDisplayName; }
+inline const QString& ServicePrivate::type() const { return mType; }
+inline const QString& ServicePrivate::dBusPath() const { return mDBusPath; }
+
+inline void ServicePrivate::setDevice( const Device& device ) { mDevice = device; }
+inline void ServicePrivate::setDisplayName( const QString& displayName ) { mDisplayName = displayName; }
+inline void ServicePrivate::setType( const QString& type ) { mType = type; }
+inline void ServicePrivate::setDBusPath( const QString& dBusPath ) { mDBusPath = dBusPath; }
+
+inline ServicePrivate::~ServicePrivate() {}
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/service.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/service.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/service.h	(revision 1079784)
@@ -0,0 +1,74 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_SERVICE_H
+#define UPNP_SERVICE_H
+
+// lib
+#include "upnp_export.h"
+// #include "device.h"
+// Qt
+#include <QtCore/QExplicitlySharedDataPointer>
+
+
+namespace UPnP
+{
+class ServicePrivate;
+class Device;
+
+
+class KUPNP_EXPORT Service
+{
+  friend class ServicePrivate;
+  friend class DeviceBrowserPrivate;
+
+  protected:
+    explicit Service( ServicePrivate* d );
+
+  public:
+    Service();
+    Service( const Service& other );
+
+    virtual ~Service();
+
+  public:
+//     QString udn() const;
+    QString displayName() const;
+    QString type() const;
+    Device device() const;
+
+  public:
+    Service& operator =( const Service& other );
+
+  private:
+    ServicePrivate* dPtr() const;
+
+  protected:
+    QExplicitlySharedDataPointer<ServicePrivate> d;
+};
+
+
+inline  ServicePrivate* Service::dPtr() const { return const_cast<ServicePrivate*>( d.data() ); }
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/devicebrowser_p.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/devicebrowser_p.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/devicebrowser_p.h	(revision 1079784)
@@ -0,0 +1,88 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_DEVICEBROWSER_P_H
+#define UPNP_DEVICEBROWSER_P_H
+
+// lib
+#include "devicebrowser.h"
+#include "device.h"
+#include "coherence_interface.h"
+
+
+namespace UPnP
+{
+
+class DeviceBrowserPrivate : public QObject
+{
+  Q_OBJECT
+
+  protected:
+    static QList<Service> demarshallServices( const Device& device, const QVariant& variant );
+
+  public:
+    explicit DeviceBrowserPrivate( DeviceBrowser* q, const QStringList& deviceTypes );
+    explicit DeviceBrowserPrivate( DeviceBrowser* q, const QString& deviceType );
+
+    ~DeviceBrowserPrivate();
+
+  public:
+    QList<Device> devices() const;
+    const QStringList& browsedDeviceTypes() const;
+
+  public:
+    void init();
+
+  protected:
+    Device addDevice( const QDBusArgument& dbusArgument );
+
+  protected Q_SLOTS:
+    void onDeviceAdded( const QDBusVariant&, const QString& udn );
+    void onDeviceRemoved( const QString& udn );
+
+  protected:
+    DeviceBrowser* const q;
+
+    org::Coherence* mCoherence;
+
+    QStringList mBrowsedDeviceTypes;
+    QHash<QString,Device> mDevices;
+};
+
+
+inline DeviceBrowserPrivate::DeviceBrowserPrivate( DeviceBrowser* _q, const QStringList& deviceTypes )
+  : q( _q ),
+    mCoherence( 0 ),
+    mBrowsedDeviceTypes( deviceTypes )
+{}
+inline DeviceBrowserPrivate::DeviceBrowserPrivate( DeviceBrowser* _q, const QString& deviceType )
+  : q( _q ),
+    mCoherence( 0 )
+{
+    mBrowsedDeviceTypes.append( deviceType );
+}
+
+inline const QStringList& DeviceBrowserPrivate::browsedDeviceTypes() const { return mBrowsedDeviceTypes; }
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/devicebrowser.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/devicebrowser.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/devicebrowser.h	(revision 1079784)
@@ -0,0 +1,68 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_DEVICEBROWSER_H
+#define UPNP_DEVICEBROWSER_H
+
+// lib
+#include "upnp_export.h"
+// Qt
+#include <QtCore/QStringList>
+#include <QtCore/QObject>
+
+template<class T> class QList;
+
+
+namespace UPnP
+{
+class DeviceBrowserPrivate;
+class Device;
+
+
+class KUPNP_EXPORT DeviceBrowser : public QObject
+{
+  Q_OBJECT
+
+  friend class DeviceBrowserPrivate;
+
+  public:
+    explicit DeviceBrowser( const QStringList& deviceTypes = QStringList() );
+    explicit DeviceBrowser( const QString& deviceType );
+
+    virtual ~DeviceBrowser();
+
+  public:
+    QList<Device> devices() const;
+
+    QStringList browsedDeviceTypes() const;
+
+  Q_SIGNALS:
+    void deviceAdded( const UPnP::Device& device );
+    void deviceRemoved( const UPnP::Device& device );
+
+  protected:
+    DeviceBrowserPrivate* const d;
+};
+
+}
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/upnp_export.h
===================================================================
--- runtime/kioslave/network/kupnp/lib/upnp_export.h	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/upnp_export.h	(revision 1079784)
@@ -0,0 +1,44 @@
+/*
+    This file is part of the KUPnP library, part of the KDE project.
+
+    Copyright 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) version 3, or any
+    later version accepted by the membership of KDE e.V. (or its
+    successor approved by the membership of KDE e.V.), which shall
+    act as a proxy defined in Section 6 of version 3 of the license.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UPNP_EXPORT_H
+#define UPNP_EXPORT_H
+
+// KDE
+#include <kdemacros.h>
+
+
+#ifndef KUPNP_EXPORT
+  // building the library?
+# if defined(MAKE_KUPNP_LIB)
+#  define KUPNP_EXPORT KDE_EXPORT
+  // using the library
+# else
+#  define KUPNP_EXPORT KDE_IMPORT
+# endif
+#endif
+
+# ifndef KUPNP_EXPORT_DEPRECATED
+#  define KUPNP_EXPORT_DEPRECATED KDE_DEPRECATED KUPNP_EXPORT
+# endif
+
+#endif
Index: runtime/kioslave/network/kupnp/lib/CMakeLists.txt
===================================================================
--- runtime/kioslave/network/kupnp/lib/CMakeLists.txt	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/CMakeLists.txt	(revision 1079784)
@@ -0,0 +1,37 @@
+include_directories(
+)
+
+set( kupnp_LIB_SRCS
+  service.cpp
+  device.cpp
+  devicebrowser_p.cpp
+  devicebrowser.cpp
+)
+set( kupnp_LIB_HDRS
+  upnp_export.h
+  service.h
+  device.h
+  devicebrowser.h
+)
+
+# http://techbase.kde.org/Development/Tutorials/D-Bus/Accessing_Interfaces also adds:
+#PKGCONFIG_GETVAR(dbus-1 prefix DBUS_PREFIX)
+#set(network_xml ${DBUS_PREFIX}/interfaces/org.foo.bar.xml)
+qt4_add_dbus_interface( kupnp_LIB_SRCS  org.Coherence.xml coherence_interface )
+
+
+kde4_add_library( kupnp  STATIC ${kupnp_LIB_SRCS} )
+
+# If making the lib SHARED again, uncomment again:
+# target_link_libraries( kupnp
+#   ${QT_QTDBUS_LIBRARY}
+#   ${QT_QTCORE_LIBRARY}
+# )
+# set_target_properties( kupnp  PROPERTIES
+#   VERSION ${GENERIC_LIB_VERSION}
+#   SOVERSION ${GENERIC_LIB_SOVERSION}
+# )
+
+# install( TARGETS kupnp  ${INSTALL_TARGETS_DEFAULT_ARGS} )
+
+# install( FILES ${kupnp_LIB_HDRS}  DESTINATION ${INCLUDE_INSTALL_DIR}/upnp  COMPONENT Devel )
Index: runtime/kioslave/network/kupnp/lib/org.Coherence.device.xml
===================================================================
--- runtime/kioslave/network/kupnp/lib/org.Coherence.device.xml	(revision 0)
+++ runtime/kioslave/network/kupnp/lib/org.Coherence.device.xml	(revision 1079784)
@@ -0,0 +1,32 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+    <interface name="org.Coherence.device">
+        <method name="get_friendly_device_type">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="get_friendly_name">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="get_device_icons">
+            <arg direction="out" type="av" />
+        </method>
+        <method name="get_usn">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="get_device_type_version">
+            <arg direction="out" type="i" />
+        </method>
+        <method name="get_device_type">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="get_id">
+            <arg direction="out" type="s" />
+        </method>
+        <method name="get_info">
+            <arg direction="out" type="v" />
+        </method>
+        <method name="get_markup_name">
+            <arg direction="out" type="s" />
+        </method>
+    </interface>
+</node>
Index: runtime/kioslave/network/kupnp/CMakeLists.txt
===================================================================
--- runtime/kioslave/network/kupnp/CMakeLists.txt	(revision 0)
+++ runtime/kioslave/network/kupnp/CMakeLists.txt	(revision 1079784)
@@ -0,0 +1,4 @@
+project( kupnp )
+
+macro_optional_add_subdirectory(lib)
+#macro_optional_add_subdirectory(browser)