00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <qstring.h>
00019 #include <qtimer.h>
00020
00021 #include <kabc/addressbook.h>
00022 #include <kabc/addressee.h>
00023 #include <kabc/resource.h>
00024 #include <kabc/stdaddressbook.h>
00025
00026
00027 #include <kdialog.h>
00028 #include <klocale.h>
00029 #include <kmessagebox.h>
00030 #include "accountselector.h"
00031 #include "kopeteuiglobal.h"
00032
00033 #include "kopeteaccount.h"
00034 #include "kopeteaccountmanager.h"
00035 #include "kopetecontact.h"
00036 #include "kopetemetacontact.h"
00037 #include "kopetepluginmanager.h"
00038 #include "kopeteprotocol.h"
00039
00040 #include "kabcpersistence.h"
00041
00042 namespace Kopete
00043 {
00044
00048 static QString unionContents( QString arg1, QString arg2 )
00049 {
00050 QChar separator( 0xE000 );
00051 QStringList outList = arg1.split( separator, QString::SkipEmptyParts );
00052 QStringList arg2List = arg2.split( separator, QString::SkipEmptyParts );
00053 for ( QStringList::iterator it = arg2List.begin(); it != arg2List.end(); ++it )
00054 if ( !outList.contains( *it ) )
00055 outList.append( *it );
00056 QString out = outList.join( QString( separator ) );
00057 return out;
00058 }
00059
00060 class KABCPersistence::Private
00061 {
00062 public:
00063 Private()
00064 : addrBookWritePending(false)
00065 {}
00066 QList<KABC::Resource *> pendingResources;
00067 bool addrBookWritePending;
00068
00069
00070 static KABC::AddressBook* s_addressBook;
00071 };
00072
00073 KABC::AddressBook* KABCPersistence::Private::s_addressBook = 0L;
00074
00075 KABCPersistence::KABCPersistence( QObject * parent, const char * name ) : QObject( parent)
00076 {
00077 setObjectName( name );
00078 d = new Private;
00079 }
00080
00081 KABCPersistence::~KABCPersistence()
00082 {
00083 delete d;
00084 }
00085
00086 KABCPersistence *KABCPersistence::self()
00087 {
00088 static KABCPersistence s;
00089 return &s;
00090 }
00091
00092 KABC::AddressBook* KABCPersistence::addressBook()
00093 {
00094 if ( Private::s_addressBook == 0L )
00095 {
00096 Private::s_addressBook = KABC::StdAddressBook::self();
00097 KABC::StdAddressBook::setAutomaticSave( false );
00098 }
00099 return Private::s_addressBook;
00100 }
00101
00102 void KABCPersistence::write( MetaContact * mc )
00103 {
00104
00105 KABC::AddressBook* ab = addressBook();
00106
00107 kDebug( 14010 ) << "looking up Addressee for " << mc->displayName() << "...";
00108
00109 KABC::Addressee theAddressee = ab->findByUid( mc->metaContactId() );
00110
00111
00112 if ( theAddressee.isEmpty() )
00113 {
00114
00115 return;
00116 }
00117 else
00118 {
00119
00120 QMap<QString, QStringList> addressMap;
00121 QList<Contact *> contacts = mc->contacts();
00122 QListIterator<Contact *> cIt( contacts );
00123 while ( cIt.hasNext() )
00124 {
00125 Contact * c = cIt.next();
00126 QStringList addresses = addressMap[ c->protocol()->addressBookIndexField() ];
00127 addresses.append( c->contactId() );
00128 addressMap.insert( c->protocol()->addressBookIndexField(), addresses );
00129 }
00130
00131
00132 QMap<QString, QStringList>::ConstIterator it = addressMap.begin();
00133 for ( ; it != addressMap.end(); ++it )
00134 {
00135
00136 QString currentCustomForProtocol = theAddressee.custom( it.key(), QLatin1String( "All" ) );
00137
00138 QString toWrite = unionContents( currentCustomForProtocol, it.value().join( QString( QChar( 0xE000 ) ) ) );
00139
00140 kDebug( 14010 ) << "Writing: " << it.key() << ", " << "All" << ", " << toWrite;
00141 theAddressee.insertCustom( it.key(), QLatin1String( "All" ), toWrite );
00142 QString check = theAddressee.custom( it.key(), QLatin1String( "All" ) );
00143 }
00144 ab->insertAddressee( theAddressee );
00145 writeAddressBook( theAddressee.resource() );
00146
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 }
00176
00177 void KABCPersistence::writeAddressBook( KABC::Resource * res)
00178 {
00179 if ( !d->pendingResources.count( res ) )
00180 d->pendingResources.append( res );
00181 if ( !d->addrBookWritePending )
00182 {
00183 d->addrBookWritePending = true;
00184 QTimer::singleShot( 2000, this, SLOT( slotWriteAddressBook() ) );
00185 }
00186 }
00187
00188 void KABCPersistence::slotWriteAddressBook()
00189 {
00190
00191 KABC::AddressBook* ab = addressBook();
00192 QListIterator<KABC::Resource *> it( d->pendingResources );
00193 while ( it.hasNext() )
00194 {
00195
00196 KABC::Ticket *ticket = ab->requestSaveTicket( it.next() );
00197 if ( !ticket )
00198 kWarning( 14010 ) << "WARNING: Resource is locked by other application!";
00199 else
00200 {
00201 if ( !ab->save( ticket ) )
00202 {
00203 kWarning( 14010 ) << "ERROR: Saving failed!";
00204 ab->releaseSaveTicket( ticket );
00205 }
00206 }
00207
00208 }
00209 d->pendingResources.clear();
00210 d->addrBookWritePending = false;
00211 }
00212
00213 void KABCPersistence::removeKABC( MetaContact *)
00214 {
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 }
00259
00260 bool KABCPersistence::syncWithKABC( MetaContact * mc )
00261 {
00262 kDebug(14010) ;
00263 bool contactAdded = false;
00264
00265 KABC::AddressBook* ab = addressBook();
00266 KABC::Addressee addr = ab->findByUid( mc->metaContactId() );
00267
00268 if ( !addr.isEmpty() )
00269 {
00270
00271 QStringList customs = addr.customs();
00272
00273 QStringList::ConstIterator it;
00274 for ( it = customs.begin(); it != customs.end(); ++it )
00275 {
00276 QString app, name, value;
00277 splitField( *it, app, name, value );
00278 kDebug( 14010 ) << "app=" << app << " name=" << name << " value=" << value;
00279
00280 if ( app.startsWith( QLatin1String( "messaging/" ) ) )
00281 {
00282 if ( name == QLatin1String( "All" ) )
00283 {
00284 kDebug( 14010 ) << " syncing \"" << app << ":" << name << " with contact list ";
00285
00286
00287 QString protocolName = app.right( app.length() - 10 );
00288
00289 if ( protocolName == QLatin1String( "xmpp" ) )
00290 protocolName = QLatin1String( "jabber" );
00291
00292
00293 Protocol * proto = dynamic_cast<Protocol*>( PluginManager::self()->loadPlugin( QLatin1String( "kopete_" ) + protocolName ) );
00294 if ( !proto )
00295 {
00296 KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
00297 i18n( "<qt>\"%1\" is not supported by Kopete.</qt>", protocolName ),
00298 i18n( "Could Not Sync with KDE Address Book" ) );
00299 continue;
00300 }
00301
00302
00303 QStringList addresses = value.split( QChar( 0xE000 ), QString::SkipEmptyParts );
00304 QStringList::iterator end = addresses.end();
00305 for ( QStringList::iterator it = addresses.begin(); it != end; ++it )
00306 {
00307
00308
00309
00310
00311 int separatorPos = (*it).indexOf( QChar( 0xE120 ) );
00312 if ( separatorPos != -1 )
00313 *it = (*it).left( separatorPos );
00314
00315 Kopete::MetaContact *otherMc = 0;
00316 foreach( Kopete::Account *act, Kopete::AccountManager::self()->accounts() )
00317 {
00318 if( act->protocol() != proto )
00319 continue;
00320 Kopete::Contact *c= act->contacts()[*it];
00321 if(c)
00322 {
00323 otherMc=c->metaContact();
00324 break;
00325 }
00326 }
00327
00328 if ( otherMc )
00329 {
00330
00331 if ( otherMc == mc )
00332 {
00333 kDebug( 14010 ) << *it << " already a child of this metacontact.";
00334 continue;
00335 }
00336 kDebug( 14010 ) << *it << " already exists in OTHER metacontact, move here?";
00337
00338 otherMc->findContact( proto->pluginId(), QString(), *it )->setMetaContact( mc );
00339 }
00340 else
00341 {
00342
00343 kDebug( 14010 ) << proto->pluginId() << "://" << *it << " was not found in the contact list. Prompting to add...";
00344 if ( KMessageBox::Yes == KMessageBox::questionYesNo( Kopete::UI::Global::mainWidget(),
00345 i18n( "<qt>An address was added to this contact by another application.<br />Would you like to use it in Kopete?<br /><b>Protocol:</b> %1<br /><b>Address:</b> %2</qt>", proto->displayName(), *it ), i18n( "Import Address From Address Book" ), KGuiItem( i18n("Use") ), KGuiItem( i18n("Do Not Use") ), QLatin1String( "ImportFromKABC" ) ) )
00346 {
00347
00348
00349
00350 int accountcount=0;
00351 bool allAccountsConnected = true;
00352 Kopete::Account *chosen = 0;
00353 foreach( Kopete::Account *act, Kopete::AccountManager::self()->accounts() )
00354 {
00355 if( act->protocol() == proto)
00356 {
00357 accountcount++;
00358 if(!act->isConnected())
00359 {
00360 allAccountsConnected=false;
00361 break;
00362 }
00363 chosen=act;
00364 }
00365 }
00366
00367 if ( !allAccountsConnected )
00368 {
00369 KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
00370 i18n( "<qt>One or more of your accounts using %1 are offline. Most systems have to be connected to add contacts. Please connect these accounts and try again.</qt>", protocolName ),
00371 i18n( "Not Connected" ) );
00372 continue;
00373 }
00374
00375
00376
00377 if ( accountcount > 1 )
00378 {
00379 KDialog *chooser = new KDialog(0);
00380 chooser->setCaption( i18n("Choose Account") );
00381 chooser->setButtons( KDialog::Ok | KDialog::Cancel );
00382
00383 AccountSelector *accSelector = new AccountSelector(proto, chooser);
00384 accSelector->setObjectName( QLatin1String("accSelector") );
00385 chooser->setMainWidget(accSelector);
00386 if ( chooser->exec() == QDialog::Rejected )
00387 continue;
00388 chosen = accSelector->selectedItem();
00389
00390 delete chooser;
00391 }
00392 else if ( accountcount == 0 )
00393 {
00394 KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
00395 i18n( "<qt>You do not have an account configured for <b>%1</b> yet. Please create an account, connect it, and try again.</qt>", protocolName ),
00396 i18n( "No Account Found" ) );
00397 continue;
00398 }
00399
00400
00401 if ( chosen )
00402 {
00403 kDebug( 14010 ) << "Adding " << *it << " to " << chosen->accountId();
00404 if ( chosen->addContact( *it, mc ) )
00405 contactAdded = true;
00406 else
00407 KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
00408 i18n( "<qt>It was not possible to add the contact.</qt>" ),
00409 i18n( "Could Not Add Contact") ) ;
00410 }
00411 }
00412 else
00413 kDebug( 14010 ) << " user declined to add " << *it << " to contact list ";
00414 }
00415 }
00416 kDebug( 14010 ) << " all " << addresses.count() << " contacts in " << proto->pluginId() << " checked ";
00417 }
00418 else
00419 kDebug( 14010 ) << "not interested in name=" << name;
00420
00421 }
00422 else
00423 kDebug( 14010 ) << "not interested in app=" << app;
00424 }
00425 }
00426 return contactAdded;
00427 return false;
00428 }
00429
00430
00431 void KABCPersistence::splitField( const QString &str, QString &app, QString &name, QString &value )
00432 {
00433 int colon = str.indexOf( ':' );
00434 if ( colon != -1 ) {
00435 QString tmp = str.left( colon );
00436 value = str.mid( colon + 1 );
00437
00438 int dash = tmp.indexOf( '-' );
00439 if ( dash != -1 ) {
00440 app = tmp.left( dash );
00441 name = tmp.mid( dash + 1 );
00442 }
00443 }
00444 }
00445
00446 }
00447
00448
00449
00450 #include "kabcpersistence.moc"