File indexing completed on 2024-03-24 15:27:57
0001 /* This file is part of kdebase/workspace/solid 0002 Copyright (C) 2005,2007 Will Stephenson <wstephenson@kde.org> 0003 0004 Copyright (c) 2010 Klarälvdalens Datakonsult AB, 0005 a KDAB Group company <info@kdab.com> 0006 Author: Kevin Ottens <kevin.ottens@kdab.com> 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Lesser General Public 0010 License as published by the Free Software Foundation; either 0011 version 2.1 of the License, or (at your option) version 3, or any 0012 later version accepted by the membership of KDE e.V. (or its 0013 successor approved by the membership of KDE e.V.), which shall 0014 act as a proxy defined in Section 6 of version 3 of the license. 0015 0016 This library is distributed in the hope that it will be useful, 0017 but WITHOUT ANY WARRANTY; without even the implied warranty of 0018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0019 Lesser General Public License for more details. 0020 0021 You should have received a copy of the GNU Lesser General Public 0022 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0023 */ 0024 0025 #include "networkstatus.h" 0026 0027 #include <QDBusServiceWatcher> 0028 #include <QMap> 0029 0030 #include <kdebug.h> 0031 0032 #include "clientadaptor.h" 0033 #include "serviceadaptor.h" 0034 0035 #include "systemstatusinterface.h" 0036 0037 #ifdef NM_BACKEND_ENABLED 0038 #include "networkmanagerstatus.h" 0039 #endif 0040 0041 #include "wicdstatus.h" 0042 0043 #include <kpluginfactory.h> 0044 #include "ntracknetworkstate.h" 0045 0046 K_PLUGIN_FACTORY_WITH_JSON(NetworkStatusFactory, 0047 "networkstatus.json", 0048 registerPlugin<NetworkStatusModule>();) 0049 0050 // INTERNALLY USED STRUCTS AND TYPEDEFS 0051 0052 typedef QMap< QString, Network * > NetworkMap; 0053 0054 class NetworkStatusModule::Private 0055 { 0056 public: 0057 Private() : status( Solid::Networking::Unknown ), backend( nullptr ), serviceWatcher( nullptr ), 0058 backendAppearedWatcher( nullptr ), backendDisappearedWatcher ( nullptr ) 0059 { 0060 0061 } 0062 ~Private() 0063 { 0064 0065 } 0066 NetworkMap networks; 0067 Solid::Networking::Status status; 0068 SystemStatusInterface *backend; 0069 QDBusServiceWatcher *serviceWatcher; 0070 QDBusServiceWatcher *backendAppearedWatcher; 0071 QDBusServiceWatcher *backendDisappearedWatcher; 0072 }; 0073 0074 // CTORS/DTORS 0075 0076 NetworkStatusModule::NetworkStatusModule(QObject* parent, const QList<QVariant>&) 0077 : KDEDModule(parent), d( new Private ) 0078 { 0079 new ClientAdaptor( this ); 0080 new ServiceAdaptor( this ); 0081 0082 #ifdef HAVE_QNTRACK 0083 new NtrackNetworkState( this ); 0084 #endif 0085 0086 init(); 0087 } 0088 0089 NetworkStatusModule::~NetworkStatusModule() 0090 { 0091 Q_FOREACH ( Network * net, d->networks ) { 0092 delete net; 0093 } 0094 0095 delete d; 0096 } 0097 0098 // CLIENT INTERFACE 0099 0100 int NetworkStatusModule::status() 0101 { 0102 kDebug( 1222 ) << " status: " << (int)d->status; 0103 return (int)d->status; 0104 } 0105 0106 //protected: 0107 0108 void NetworkStatusModule::updateStatus() 0109 { 0110 Solid::Networking::Status bestStatus = Solid::Networking::Unknown; 0111 const Solid::Networking::Status oldStatus = d->status; 0112 0113 Q_FOREACH ( Network * net, d->networks ) { 0114 if ( net->status() > bestStatus ) 0115 bestStatus = net->status(); 0116 } 0117 d->status = bestStatus; 0118 0119 if ( oldStatus != d->status ) { 0120 if (d->status == Solid::Networking::Connected) { 0121 QTimer::singleShot(2000, this, SLOT(delayedStatusChanged())); 0122 } else { 0123 emit statusChanged( (uint)d->status ); 0124 } 0125 } 0126 } 0127 0128 void NetworkStatusModule::delayedStatusChanged() 0129 { 0130 emit statusChanged( (uint)d->status ); 0131 } 0132 0133 void NetworkStatusModule::serviceUnregistered( const QString & name ) 0134 { 0135 // unregister and delete any networks owned by a service that has just unregistered 0136 d->serviceWatcher->removeWatchedService( name ); 0137 QMutableMapIterator<QString,Network*> it( d->networks ); 0138 while ( it.hasNext() ) { 0139 it.next(); 0140 if ( it.value()->service() == name ) { 0141 kDebug( 1222 ) << "Departing service " << name << " owned network " << it.value()->name() << ", removing it"; 0142 Network * removedNet = it.value(); 0143 it.remove(); 0144 updateStatus(); 0145 delete removedNet; 0146 } 0147 } 0148 } 0149 0150 // SERVICE INTERFACE // 0151 0152 QStringList NetworkStatusModule::networks() 0153 { 0154 if ( d->networks.count() ) { 0155 kDebug() << "Network status module is aware of " << d->networks.count() << " networks"; 0156 } else { 0157 kDebug( 1222 ) << "Network status module is not aware of any networks"; 0158 } 0159 return d->networks.keys(); 0160 } 0161 0162 void NetworkStatusModule::setNetworkStatus( const QString & networkName, int st ) 0163 { 0164 kDebug( 1222 ) << networkName << ", " << st; 0165 Solid::Networking::Status changedStatus = (Solid::Networking::Status)st; 0166 if ( d->networks.contains( networkName ) ) { 0167 Network * net = d->networks[ networkName ]; 0168 net->setStatus( changedStatus ); 0169 updateStatus(); 0170 } else { 0171 kDebug( 1222 ) << " No network named '" << networkName << "' known."; 0172 } 0173 } 0174 0175 void NetworkStatusModule::registerNetwork( const QString & networkName, int status, const QString & serviceName ) 0176 { 0177 QDBusConnection dbus = QDBusConnection::sessionBus(); 0178 QDBusConnectionInterface * sessionBus = dbus.interface(); 0179 QString uniqueOwner = sessionBus->serviceOwner( serviceName ).value(); 0180 0181 kDebug( 1222 ) << networkName << ", with status " << status << " is owned by " << uniqueOwner; 0182 0183 d->networks.insert( networkName, new Network( networkName, status, uniqueOwner ) ); 0184 0185 if ( d->serviceWatcher ) { 0186 d->serviceWatcher->addWatchedService( uniqueOwner ); 0187 } 0188 0189 updateStatus(); 0190 } 0191 0192 void NetworkStatusModule::unregisterNetwork( const QString & networkName ) 0193 { 0194 if ( networkName != QLatin1String("SolidNetwork") ) { 0195 kDebug( 1222 ) << networkName << " unregistered."; 0196 0197 if ( d->serviceWatcher ) { 0198 Network * net = d->networks.value( networkName ); 0199 if ( net ) { 0200 d->serviceWatcher->removeWatchedService( net->service() ); 0201 } 0202 } 0203 0204 d->networks.remove( networkName ); 0205 updateStatus(); 0206 } 0207 } 0208 0209 void NetworkStatusModule::backendRegistered() 0210 { 0211 // we need to reset backend objects to make them connect to the appearing service. 0212 qDeleteAll(backends); 0213 backends.clear(); 0214 0215 delete d->backendAppearedWatcher; 0216 d->backendAppearedWatcher = nullptr; 0217 0218 delete d->backendDisappearedWatcher; 0219 d->backendDisappearedWatcher = nullptr; 0220 init(); 0221 } 0222 0223 void NetworkStatusModule::backendUnregistered() 0224 { 0225 solidNetworkingStatusChanged(Solid::Networking::Unknown); 0226 } 0227 0228 void NetworkStatusModule::init() 0229 { 0230 if (backends.isEmpty()) { 0231 #ifdef NM_BACKEND_ENABLED 0232 backends << new NetworkManagerStatus( this ); 0233 #endif 0234 backends << new WicdStatus( this ); 0235 } 0236 0237 for ( int i = 0; i < backends.count(); i++ ) { 0238 if ( backends.value(i)->isSupported() ) { 0239 // select our backend... 0240 d->backend = backends.takeAt(i); 0241 // and delete the rest. 0242 qDeleteAll(backends); 0243 backends.clear(); 0244 break; 0245 } 0246 } 0247 0248 if (d->backendAppearedWatcher == nullptr) { 0249 d->backendAppearedWatcher = new QDBusServiceWatcher(this); 0250 d->backendAppearedWatcher->setConnection(QDBusConnection::systemBus()); 0251 d->backendAppearedWatcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration); 0252 } 0253 0254 if ( d->backend == nullptr ) { 0255 // if none found watch for all backends registration. 0256 for ( int i = 0; i < backends.count(); i++ ) { 0257 d->backendAppearedWatcher->addWatchedService(backends.value(i)->serviceName()); 0258 } 0259 connect(d->backendAppearedWatcher, SIGNAL(serviceRegistered(QString)), SLOT(backendRegistered())); 0260 return; 0261 } else { 0262 // watch for the selected backend re-registration only. 0263 d->backendAppearedWatcher->addWatchedService(d->backend->serviceName()); 0264 connect(d->backendAppearedWatcher, SIGNAL(serviceRegistered(QString)), SLOT(backendRegistered())); 0265 0266 // watch for the selected bakend unregistration. 0267 if (d->backendDisappearedWatcher == nullptr) { 0268 d->backendDisappearedWatcher = new QDBusServiceWatcher(this); 0269 d->backendDisappearedWatcher->setConnection(QDBusConnection::systemBus()); 0270 d->backendDisappearedWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); 0271 d->backendDisappearedWatcher->addWatchedService(d->backend->serviceName()); 0272 connect(d->backendDisappearedWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(backendUnregistered())); 0273 } 0274 0275 connect( d->backend, SIGNAL(statusChanged(Solid::Networking::Status)), 0276 this, SLOT(solidNetworkingStatusChanged(Solid::Networking::Status))); 0277 Solid::Networking::Status status = d->backend->status(); 0278 registerNetwork( QLatin1String("SolidNetwork"), status, QLatin1String("org.kde.kded5") ); 0279 } 0280 0281 d->serviceWatcher = new QDBusServiceWatcher(this); 0282 d->serviceWatcher->setConnection(QDBusConnection::sessionBus()); 0283 d->serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); 0284 connect(d->serviceWatcher, SIGNAL(serviceUnregistered(QString)), SLOT(serviceUnregistered(QString))); 0285 } 0286 0287 void NetworkStatusModule::solidNetworkingStatusChanged( Solid::Networking::Status status ) 0288 { 0289 kDebug( 1222 ) << "SolidNetwork changed status: " << status; 0290 setNetworkStatus( QLatin1String("SolidNetwork"), status ); 0291 } 0292 0293 #include "moc_networkstatus.cpp" 0294 #include "networkstatus.moc"