00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include <qglobal.h>
00025
#include <qpixmapcache.h>
00026
#include <dcopclient.h>
00027
#include <kdcopservicestarter.h>
00028
#include <kdebug.h>
00029
#include <kmessagebox.h>
00030
#include <ksimpleconfig.h>
00031
#include <kiconloader.h>
00032
#include <kservice.h>
00033
#include <kservicetype.h>
00034
00035
#include "kimiface_stub.h"
00036
00037
#include "kimproxy.h"
00038
00039
static KStaticDeleter<KIMProxy> _staticDeleter;
00040
00041
KIMProxy * KIMProxy::s_instance = 0L;
00042
00043
int bestPresence(
AppPresence* ap )
00044 {
00045 Q_ASSERT( ap );
00046 AppPresence::const_iterator it;
00047 it = ap->begin();
00048
int best = 0;
00049
if ( it != ap->end() )
00050 {
00051 best = it.data();
00052 ++it;
00053
for ( ; it != ap->end(); ++it )
00054 {
00055
if ( it.data() > best )
00056 best = it.data();
00057 }
00058 }
00059
return best;
00060 }
00061
00062
QCString bestAppId(
AppPresence* ap )
00063 {
00064 Q_ASSERT( ap );
00065 AppPresence::const_iterator it;
00066
QCString bestAppId;
00067 it = ap->begin();
00068
if ( it != ap->end() )
00069 {
00070
int best = it.data();
00071 bestAppId = it.key();
00072 ++it;
00073
for ( ; it != ap->end(); ++it )
00074 {
00075
if ( it.data() > best )
00076 {
00077 best = it.data();
00078 bestAppId = it.key();
00079 }
00080 }
00081 }
00082
return bestAppId;
00083 }
00084
00085 KIMProxy *
KIMProxy::instance(
DCOPClient * client )
00086 {
00087
if ( client )
00088 {
00089
if ( !s_instance )
00090 _staticDeleter.setObject( s_instance,
new KIMProxy( client ) );
00091
return s_instance;
00092 }
00093
else
00094
return 0L;
00095 }
00096
00097 KIMProxy::KIMProxy(
DCOPClient* dc ) :
DCOPObject(
"KIMProxyIface" ),
QObject()
00098 {
00099 m_im_client_stubs.setAutoDelete(
true );
00100 m_presence_map.setAutoDelete(
true );
00101
00102 m_apps_available =
false;
00103 m_dc = dc;
00104 m_initialized =
false;
00105 connect( m_dc, SIGNAL( applicationRemoved(
const QCString& ) ) ,
this, SLOT( unregisteredFromDCOP(
const QCString& ) ) );
00106 connect( m_dc, SIGNAL( applicationRegistered(
const QCString& ) ) ,
this, SLOT( registeredToDCOP(
const QCString& ) ) );
00107 m_dc->
setNotifications(
true );
00108
00109
00110
00111
QCString method =
"contactPresenceChanged( QString, QCString, int )";
00112
00113
00114
00115
if ( !
connectDCOPSignal( 0, 0, method, method,
false ) )
00116
KMessageBox::information( 0,
QString(
"Couldn't connect DCOP signal.\nWon't receive any status notifications!" ) );
00117 }
00118
00119 KIMProxy::~KIMProxy( )
00120 {
00121
00122 }
00123
00124 bool KIMProxy::initialize()
00125 {
00126
if ( !m_initialized )
00127 {
00128 m_initialized =
true;
00129
00130
if ( KServiceType::serviceType( IM_SERVICE_TYPE ) )
00131 {
00132
kdDebug( 5301 ) <<
k_funcinfo <<
endl;
00133
QCString dcopObjectId =
"KIMIface";
00134
00135
00136 KService::List offers = KServiceType::offers( IM_SERVICE_TYPE );
00137 KService::List::iterator offer;
00138
typedef QValueList<QCString> QCStringList;
00139 QCStringList registeredApps = m_dc->
registeredApplications();
00140 QCStringList::iterator app;
00141
const QCStringList::iterator end = registeredApps.end();
00142
00143
for ( app = registeredApps.begin(); app != end; ++app )
00144 {
00145
00146
00147
for ( offer = offers.begin(); offer != offers.end(); ++offer )
00148 {
00149
QCString dcopService = (*offer)->property(
"X-DCOP-ServiceName").toString().latin1();
00150
if ( !dcopService.isEmpty() )
00151 {
00152
00153
00154
QCString instanceName = (*app).left( dcopService.length() );
00155
00156
if ( instanceName == dcopService )
00157 {
00158 m_apps_available =
true;
00159
00160
if ( !m_im_client_stubs.find( dcopService ) )
00161 {
00162
kdDebug( 5301 ) <<
"inserting new stub for " << *app <<
" dcopObjectId " << dcopObjectId <<
endl;
00163 m_im_client_stubs.insert( *app,
new KIMIface_stub( m_dc, *app, dcopObjectId ) );
00164 }
00165 }
00166 }
00167 }
00168 }
00169 }
00170 }
00171
return !m_im_client_stubs.isEmpty();
00172 }
00173
00174 QStringList KIMProxy::allContacts()
00175 {
00176
QStringList value;
00177
00178
if (
initialize() )
00179 {
00180
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00181
for ( ; it.current(); ++it )
00182 {
00183 value += it.current()->allContacts();
00184 }
00185 }
00186
return value;
00187 }
00188
00189 QStringList KIMProxy::reachableContacts()
00190 {
00191
QStringList value;
00192
00193
if (
initialize() )
00194 {
00195
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00196
for ( ; it.current(); ++it )
00197 {
00198 value += it.current()->reachableContacts( );
00199 }
00200 }
00201
return value;
00202 }
00203
00204 QStringList KIMProxy::onlineContacts()
00205 {
00206
QStringList value;
00207
00208
if (
initialize() )
00209 {
00210
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00211
for ( ; it.current(); ++it )
00212 {
00213 value += it.current()->onlineContacts( );
00214 }
00215 }
00216
return value;
00217 }
00218
00219 QStringList KIMProxy::fileTransferContacts()
00220 {
00221
QStringList value;
00222
00223
if (
initialize() )
00224 {
00225
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00226
for ( ; it.current(); ++it )
00227 {
00228 value += it.current()->fileTransferContacts( );
00229 }
00230 }
00231
return value;
00232 }
00233
00234 bool KIMProxy::isPresent(
const QString& uid )
00235 {
00236
bool present =
false;
00237
if (
initialize() )
00238 {
00239
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00240
for ( ; it.current(); ++it )
00241 {
00242
if (it.current()->isPresent( uid ) )
00243 {
00244 present =
true;
00245
break;
00246 }
00247 }
00248 }
00249
return present;
00250 }
00251
00252 QString KIMProxy::displayName(
const QString& uid )
00253 {
00254
QString name;
00255
if (
initialize() )
00256 {
00257
if ( KIMIface_stub* s =
stubForUid( uid ) )
00258 name = s->displayName( uid );
00259 }
00260
00261
return name;
00262 }
00263
00264 int KIMProxy::presenceNumeric(
const QString& uid )
00265 {
00266
int presence = -1;
00267
if (
initialize() )
00268 {
00269
pollAll( uid );
00270
AppPresence *ap = m_presence_map.find( uid );
00271
if ( ap )
00272 presence = bestPresence( ap );
00273 }
00274
return presence;
00275 }
00276
00277 QString KIMProxy::presenceString(
const QString& uid )
00278 {
00279
00280
00281
QString presence;
00282 KIMIface_stub* s =
stubForUid( uid );
00283
if (
initialize() && s )
00284 {
00285
00286
PresenceStringMap * appPresenceStrings = m_client_presence_strings[ s ];
00287
if ( !appPresenceStrings )
00288 {
00289
00290 appPresenceStrings =
new PresenceStringMap();
00291 m_client_presence_strings.insert( s, appPresenceStrings );
00292 }
00293
int numeric =
presenceNumeric( uid );
00294 presence = (*appPresenceStrings)[ numeric ];
00295
if ( presence.isEmpty() )
00296 {
00297
00298 presence = s->presenceString( uid );
00299 appPresenceStrings->insert( numeric, presence );
00300 }
00301
00302 }
00303
return presence;
00304 }
00305
00306 QPixmap KIMProxy::presenceIcon(
const QString& uid )
00307 {
00308
QPixmap presence;
00309
if (
initialize() )
00310 {
00311
00312
pollAll( uid );
00313
AppPresence *existing = m_presence_map.find( uid );
00314
00315
QCString ba = bestAppId( existing );
00316
if ( !ba.isNull() )
00317 {
00318
QString appPresenceKey = QString::number(
presenceNumeric( uid ) ).append( ba );
00319
if ( !QPixmapCache::find( appPresenceKey, presence ) )
00320 {
00321
if ( KIMIface_stub* s =
stubForUid( uid ) )
00322 {
00323 presence = s->icon( uid );
00324 QPixmapCache::insert( appPresenceKey, presence );
00325 }
00326 }
00327 }
00328 }
00329
return presence;
00330 }
00331
00332 bool KIMProxy::canReceiveFiles(
const QString & uid )
00333 {
00334
if (
initialize() )
00335 {
00336
if ( KIMIface_stub* s =
stubForUid( uid ) )
00337
return s->canReceiveFiles( uid );
00338 }
00339
return false;
00340 }
00341
00342 bool KIMProxy::canRespond(
const QString & uid )
00343 {
00344
if (
initialize() )
00345 {
00346
if ( KIMIface_stub* s =
stubForUid( uid ) )
00347
return s->canRespond( uid );
00348 }
00349
return false;
00350 }
00351
00352 QString KIMProxy::context(
const QString & uid )
00353 {
00354
if (
initialize() )
00355 {
00356
if ( KIMIface_stub* s =
stubForUid( uid ) )
00357
return s->context( uid );
00358 }
00359
return QString::null;
00360 }
00361
00362 void KIMProxy::chatWithContact(
const QString& uid )
00363 {
00364
if (
initialize() )
00365 {
00366
if ( KIMIface_stub* s =
stubForUid( uid ) )
00367 s->chatWithContact( uid );
00368 }
00369
return;
00370 }
00371
00372 void KIMProxy::messageContact(
const QString& uid,
const QString& message )
00373 {
00374
if (
initialize() )
00375 {
00376
if ( KIMIface_stub* s =
stubForUid( uid ) )
00377 s->messageContact( uid, message );
00378 }
00379
return;
00380 }
00381
00382 void KIMProxy::sendFile(
const QString &uid,
const KURL &sourceURL,
const QString &altFileName, uint fileSize )
00383 {
00384
if (
initialize() )
00385 {
00386
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00387
for ( ; it.current(); ++it )
00388 {
00389
if ( it.current()->canReceiveFiles( uid ) )
00390 {
00391 it.current()->sendFile( uid, sourceURL, altFileName, fileSize );
00392
break;
00393 }
00394 }
00395 }
00396
return;
00397 }
00398
00399 bool KIMProxy::addContact(
const QString &contactId,
const QString &protocol )
00400 {
00401
if (
initialize() )
00402 {
00403
if ( KIMIface_stub* s =
stubForProtocol( protocol ) )
00404
return s->addContact( contactId, protocol );
00405 }
00406
return false;
00407 }
00408
00409 QString KIMProxy::locate(
const QString & contactId,
const QString & protocol )
00410 {
00411
if (
initialize() )
00412 {
00413
if ( KIMIface_stub* s =
stubForProtocol( protocol ) )
00414
return s->locate( contactId, protocol );
00415 }
00416
return QString::null;
00417 }
00418
00419 bool KIMProxy::imAppsAvailable()
00420 {
00421
kdDebug( 5301 ) <<
k_funcinfo <<
" returning " << m_apps_available<<
endl;
00422
return m_apps_available;
00423 }
00424
00425 bool KIMProxy::startPreferredApp()
00426 {
00427
QString preferences =
QString(
"[X-DCOP-ServiceName] = '%1'").arg(
preferredApp() );
00428
00429
QString error;
00430
QCString dcopService;
00431
00432
00433
00434 preferences = QString::null;
00435
int result = KDCOPServiceStarter::self()->findServiceFor( IM_SERVICE_TYPE, QString::null, preferences, &error, &dcopService );
00436
00437
kdDebug( 5301 ) <<
k_funcinfo <<
"error was: " << error <<
", dcopService: " << dcopService <<
endl;
00438
00439
return ( result == 0 );
00440 }
00441
00442
void KIMProxy::unregisteredFromDCOP(
const QCString& appId )
00443 {
00444
kdDebug( 5301 ) <<
k_funcinfo << appId <<
endl;
00445
if ( m_im_client_stubs.find( appId ) )
00446 {
00447
kdDebug( 5301 ) <<
"removing references to " << appId <<
endl;
00448
00449
QDictIterator<AppPresence> it( m_presence_map );
00450
for ( ; it.current(); ++it )
00451 {
00452 AppPresence::iterator apIt;
00453
for ( apIt = it.current()->begin(); apIt != it.current()->end(); ++apIt )
00454
if ( apIt.key() == appId )
00455 {
00456 it.current()->remove( apIt );
00457 }
00458 }
00459 m_im_client_stubs.remove( appId );
00460 emit
sigPresenceInfoExpired();
00461 }
00462 }
00463
00464
void KIMProxy::registeredToDCOP(
const QCString& appId )
00465 {
00466
00467
00468
00469
if ( appId.isEmpty() )
00470
return;
00471
00472
if ( !KServiceType::serviceType( IM_SERVICE_TYPE ) )
00473
return;
00474
00475
kdDebug( 5301 ) <<
k_funcinfo << appId <<
endl;
00476
bool newApp =
false;
00477
00478
const KService::List offers = KServiceType::offers( IM_SERVICE_TYPE );
00479 KService::List::const_iterator it;
00480
00481
00482
for ( it = offers.begin(); it != offers.end(); ++it )
00483 {
00484
QCString dcopObjectId =
"KIMIface";
00485
QCString dcopService = (*it)->property(
"X-DCOP-ServiceName").toString().latin1();
00486
kdDebug( 5301 ) <<
"dcopService: " << dcopService <<
", appId: " << appId <<
endl;
00487
if ( appId.left( dcopService.length() ) == dcopService )
00488 {
00489 m_apps_available =
true;
00490
00491
if ( !m_im_client_stubs.find( appId ) )
00492 {
00493 newApp =
true;
00494 m_im_client_stubs.insert( appId,
new KIMIface_stub( m_dc, appId, dcopObjectId ) );
00495 }
00496 }
00497
00498
00499 }
00500
if ( newApp )
00501 emit
sigPresenceInfoExpired();
00502 }
00503
00504 void KIMProxy::contactPresenceChanged(
QString uid,
QCString appId,
int presence )
00505 {
00506
00507
kdDebug( 5301 ) <<
k_funcinfo <<
"uid: " << uid <<
" appId: " << appId <<
" presence " << presence <<
endl;
00508
if (
updatePresence( uid, appId, presence ) )
00509 emit
sigContactPresenceChanged( uid );
00510 }
00511
00512 bool KIMProxy::updatePresence(
const QString &uid,
const QCString &appId,
int presence )
00513 {
00514
00515
AppPresence *userPresences = 0L;
00516
if ( ( userPresences = m_presence_map.find( uid ) ) )
00517 {
00518
00519
int oldBest = bestPresence( userPresences );
00520
QCString oldBestApp = bestAppId( userPresences );
00521
00522 userPresences->insert( appId, presence );
00523
int newBest = bestPresence( userPresences );
00524
00525
return ( newBest > oldBest || appId == oldBestApp );
00526 }
00527
else
00528 {
00529
00530 userPresences =
new AppPresence();
00531 userPresences->insert( appId, presence );
00532 m_presence_map.insert( uid, userPresences );
00533
return true;
00534 }
00535
return false;
00536 }
00537
00538 void KIMProxy::pollAll(
const QString &uid )
00539 {
00540
00541
00542
00543
if ( !m_presence_map.find( uid ) )
00544 {
00545
AppPresence *presence =
new AppPresence();
00546
00547
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00548
for ( ; it.current(); ++it )
00549 {
00550 presence->insert( it.currentKey().ascii(), it.current()->presenceStatus( uid ) );
00551 }
00552 m_presence_map.insert( uid, presence );
00553 }
00554 }
00555
00556 KIMIface_stub *
KIMProxy::stubForUid(
const QString &uid )
00557 {
00558
pollAll( uid );
00559
00560
00561
AppPresence *ap = m_presence_map.find( uid );
00562
00563
if ( ap )
00564
return m_im_client_stubs.find( bestAppId( ap ) );
00565
else
00566
return 0L;
00567 }
00568
00569 KIMIface_stub *
KIMProxy::stubForProtocol(
const QString &protocol)
00570 {
00571 KIMIface_stub * app;
00572
00573
QString preferred =
preferredApp();
00574
if ( ( app = m_im_client_stubs.find( preferred ) ) )
00575 {
00576
if ( app->protocols().grep( protocol ).count() > 0 )
00577
return app;
00578 }
00579
00580
QDictIterator<KIMIface_stub> it( m_im_client_stubs );
00581
for ( ; it.current(); ++it )
00582 {
00583
if ( it.current()->protocols().grep( protocol ).count() > 0 )
00584
return it.current();
00585 }
00586
return 0L;
00587 }
00588
00589 QString KIMProxy::preferredApp()
00590 {
00591
KConfig *store =
new KSimpleConfig( IM_CLIENT_PREFERENCES_FILE );
00592 store->
setGroup( IM_CLIENT_PREFERENCES_SECTION );
00593
QString preferredApp = store->
readEntry( IM_CLIENT_PREFERENCES_ENTRY );
00594
00595
return preferredApp;
00596 }
00597
00598
#include "kimproxy.moc"