mailtransport
transportmanager.cpp
00001 /* 00002 Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 00018 */ 00019 00020 #include "transportmanager.h" 00021 #include "resourcesendjob_p.h" 00022 #include "mailtransport_defs.h" 00023 #include "sendmailjob.h" 00024 #include "smtpjob.h" 00025 #include "transport.h" 00026 #include "transportjob.h" 00027 #include "transporttype.h" 00028 #include "transporttype_p.h" 00029 #include "addtransportdialog.h" 00030 #include "transportconfigdialog.h" 00031 #include "transportconfigwidget.h" 00032 #include "sendmailconfigwidget.h" 00033 #include "smtpconfigwidget.h" 00034 00035 #include <QApplication> 00036 #include <QtDBus/QDBusConnection> 00037 #include <QtDBus/QDBusConnectionInterface> 00038 #include <QtDBus/QDBusServiceWatcher> 00039 #include <QPointer> 00040 #include <QRegExp> 00041 #include <QStringList> 00042 00043 #include <KConfig> 00044 #include <KConfigGroup> 00045 #include <KDebug> 00046 #include <KEMailSettings> 00047 #include <KLocale> 00048 #include <KMessageBox> 00049 #include <KRandom> 00050 #include <KUrl> 00051 #include <KWallet/Wallet> 00052 00053 #include <akonadi/agentinstance.h> 00054 #include <akonadi/agentmanager.h> 00055 00056 using namespace MailTransport; 00057 using namespace KWallet; 00058 00059 namespace MailTransport { 00064 class TransportManagerPrivate 00065 { 00066 public: 00067 TransportManagerPrivate( TransportManager *parent ) 00068 : q( parent ) 00069 { 00070 } 00071 00072 ~TransportManagerPrivate() { 00073 delete config; 00074 qDeleteAll( transports ); 00075 } 00076 00077 KConfig *config; 00078 QList<Transport *> transports; 00079 TransportType::List types; 00080 bool myOwnChange; 00081 bool appliedChange; 00082 KWallet::Wallet *wallet; 00083 bool walletOpenFailed; 00084 bool walletAsyncOpen; 00085 int defaultTransportId; 00086 bool isMainInstance; 00087 QList<TransportJob *> walletQueue; 00088 TransportManager *q; 00089 00090 void readConfig(); 00091 void writeConfig(); 00092 void fillTypes(); 00093 int createId() const; 00094 void prepareWallet(); 00095 void validateDefault(); 00096 void migrateToWallet(); 00097 00098 // Slots 00099 void slotTransportsChanged(); 00100 void slotWalletOpened( bool success ); 00101 void dbusServiceUnregistered(); 00102 void agentTypeAdded( const Akonadi::AgentType &atype ); 00103 void agentTypeRemoved( const Akonadi::AgentType &atype ); 00104 void jobResult( KJob *job ); 00105 }; 00106 00107 } 00108 00109 class StaticTransportManager : public TransportManager 00110 { 00111 public: 00112 StaticTransportManager() : TransportManager() {} 00113 }; 00114 00115 StaticTransportManager *sSelf = 0; 00116 00117 static void destroyStaticTransportManager() { 00118 delete sSelf; 00119 } 00120 00121 TransportManager::TransportManager() 00122 : QObject(), d( new TransportManagerPrivate( this ) ) 00123 { 00124 KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); 00125 KGlobal::locale()->insertCatalog( QLatin1String( "libakonadi-kmime" ) ); 00126 qAddPostRoutine( destroyStaticTransportManager ); 00127 d->myOwnChange = false; 00128 d->appliedChange = false; 00129 d->wallet = 0; 00130 d->walletOpenFailed = false; 00131 d->walletAsyncOpen = false; 00132 d->defaultTransportId = -1; 00133 d->config = new KConfig( QLatin1String( "mailtransports" ) ); 00134 00135 QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, 00136 QDBusConnection::ExportScriptableSlots | 00137 QDBusConnection::ExportScriptableSignals ); 00138 00139 QDBusServiceWatcher *watcher = new QDBusServiceWatcher( DBUS_SERVICE_NAME, QDBusConnection::sessionBus(), 00140 QDBusServiceWatcher::WatchForUnregistration, this ); 00141 connect( watcher, SIGNAL( serviceUnregistered( const QString& ) ), SLOT( dbusServiceUnregistered() ) ); 00142 00143 QDBusConnection::sessionBus().connect( QString(), QString(), 00144 DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, 00145 this, SLOT(slotTransportsChanged()) ); 00146 00147 d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); 00148 00149 d->fillTypes(); 00150 } 00151 00152 TransportManager::~TransportManager() 00153 { 00154 qRemovePostRoutine( destroyStaticTransportManager ); 00155 delete d; 00156 } 00157 00158 TransportManager *TransportManager::self() 00159 { 00160 if ( !sSelf ) { 00161 sSelf = new StaticTransportManager; 00162 sSelf->d->readConfig(); 00163 } 00164 return sSelf; 00165 } 00166 00167 Transport *TransportManager::transportById( int id, bool def ) const 00168 { 00169 foreach ( Transport *t, d->transports ) { 00170 if ( t->id() == id ) { 00171 return t; 00172 } 00173 } 00174 00175 if ( def || ( id == 0 && d->defaultTransportId != id ) ) { 00176 return transportById( d->defaultTransportId, false ); 00177 } 00178 return 0; 00179 } 00180 00181 Transport *TransportManager::transportByName( const QString &name, bool def ) const 00182 { 00183 foreach ( Transport *t, d->transports ) { 00184 if ( t->name() == name ) { 00185 return t; 00186 } 00187 } 00188 if ( def ) { 00189 return transportById( 0, false ); 00190 } 00191 return 0; 00192 } 00193 00194 QList< Transport * > TransportManager::transports() const 00195 { 00196 return d->transports; 00197 } 00198 00199 TransportType::List TransportManager::types() const 00200 { 00201 return d->types; 00202 } 00203 00204 Transport *TransportManager::createTransport() const 00205 { 00206 int id = d->createId(); 00207 Transport *t = new Transport( QString::number( id ) ); 00208 t->setId( id ); 00209 return t; 00210 } 00211 00212 void TransportManager::addTransport( Transport *transport ) 00213 { 00214 if ( d->transports.contains( transport ) ) { 00215 kDebug() << "Already have this transport."; 00216 return; 00217 } 00218 00219 kDebug() << "Added transport" << transport; 00220 d->transports.append( transport ); 00221 d->validateDefault(); 00222 emitChangesCommitted(); 00223 } 00224 00225 void TransportManager::schedule( TransportJob *job ) 00226 { 00227 connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); 00228 00229 // check if the job is waiting for the wallet 00230 if ( !job->transport()->isComplete() ) { 00231 kDebug() << "job waits for wallet:" << job; 00232 d->walletQueue << job; 00233 loadPasswordsAsync(); 00234 return; 00235 } 00236 00237 job->start(); 00238 } 00239 00240 void TransportManager::createDefaultTransport() 00241 { 00242 KEMailSettings kes; 00243 Transport *t = createTransport(); 00244 t->setName( i18n( "Default Transport" ) ); 00245 t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); 00246 if ( t->isValid() ) { 00247 t->writeConfig(); 00248 addTransport( t ); 00249 } else { 00250 kWarning() << "KEMailSettings does not contain a valid transport."; 00251 } 00252 } 00253 00254 bool TransportManager::showTransportCreationDialog( QWidget *parent, 00255 ShowCondition showCondition ) 00256 { 00257 if ( showCondition == IfNoTransportExists ) { 00258 if ( !isEmpty() ) { 00259 return true; 00260 } 00261 00262 const int response = KMessageBox::messageBox( parent, 00263 KMessageBox::WarningContinueCancel, 00264 i18n( "You must create an outgoing account before sending." ), 00265 i18n( "Create Account Now?" ), 00266 KGuiItem( i18n( "Create Account Now" ) ) ); 00267 if ( response != KMessageBox::Continue ) { 00268 return false; 00269 } 00270 } 00271 00272 QPointer<AddTransportDialog> dialog = new AddTransportDialog( parent ); 00273 const bool accepted = ( dialog->exec() == QDialog::Accepted ); 00274 delete dialog; 00275 return accepted; 00276 } 00277 00278 bool TransportManager::configureTransport( Transport *transport, QWidget *parent ) 00279 { 00280 if( transport->type() == Transport::EnumType::Akonadi ) { 00281 using namespace Akonadi; 00282 AgentInstance instance = AgentManager::self()->instance( transport->host() ); 00283 if( !instance.isValid() ) { 00284 kWarning() << "Invalid resource instance" << transport->host(); 00285 } 00286 instance.configure( parent ); // Async... 00287 transport->writeConfig(); 00288 return true; // No way to know here if the user cancelled or not. 00289 } 00290 00291 QPointer<KDialog> dialog = new KDialog( parent ); 00292 TransportConfigWidget *configWidget = 0; 00293 switch( transport->type() ) { 00294 case Transport::EnumType::SMTP: 00295 { 00296 configWidget = new SMTPConfigWidget( transport, dialog ); 00297 break; 00298 } 00299 case Transport::EnumType::Sendmail: 00300 { 00301 configWidget = new SendmailConfigWidget( transport, dialog ); 00302 break; 00303 } 00304 default: 00305 { 00306 Q_ASSERT( false ); 00307 delete dialog; 00308 return false; 00309 } 00310 } 00311 dialog->setMainWidget( configWidget ); 00312 dialog->setCaption( i18n( "Configure account" ) ); 00313 dialog->setButtons( KDialog::Ok | KDialog::Cancel ); 00314 bool okClicked = ( dialog->exec() == QDialog::Accepted ); 00315 if( okClicked ) { 00316 configWidget->apply(); // calls transport->writeConfig() 00317 } 00318 delete dialog; 00319 return okClicked; 00320 } 00321 00322 TransportJob *TransportManager::createTransportJob( int transportId ) 00323 { 00324 Transport *t = transportById( transportId, false ); 00325 if ( !t ) { 00326 return 0; 00327 } 00328 t = t->clone(); // Jobs delete their transports. 00329 t->updatePasswordState(); 00330 switch ( t->type() ) { 00331 case Transport::EnumType::SMTP: 00332 return new SmtpJob( t, this ); 00333 case Transport::EnumType::Sendmail: 00334 return new SendmailJob( t, this ); 00335 case Transport::EnumType::Akonadi: 00336 return new ResourceSendJob( t, this ); 00337 } 00338 Q_ASSERT( false ); 00339 return 0; 00340 } 00341 00342 TransportJob *TransportManager::createTransportJob( const QString &transport ) 00343 { 00344 bool ok = false; 00345 Transport *t = 0; 00346 00347 int transportId = transport.toInt( &ok ); 00348 if ( ok ) { 00349 t = transportById( transportId ); 00350 } 00351 00352 if ( !t ) { 00353 t = transportByName( transport, false ); 00354 } 00355 00356 if ( t ) { 00357 return createTransportJob( t->id() ); 00358 } 00359 00360 return 0; 00361 } 00362 00363 bool TransportManager::isEmpty() const 00364 { 00365 return d->transports.isEmpty(); 00366 } 00367 00368 QList<int> TransportManager::transportIds() const 00369 { 00370 QList<int> rv; 00371 foreach ( Transport *t, d->transports ) { 00372 rv << t->id(); 00373 } 00374 return rv; 00375 } 00376 00377 QStringList TransportManager::transportNames() const 00378 { 00379 QStringList rv; 00380 foreach ( Transport *t, d->transports ) { 00381 rv << t->name(); 00382 } 00383 return rv; 00384 } 00385 00386 QString TransportManager::defaultTransportName() const 00387 { 00388 Transport *t = transportById( d->defaultTransportId, false ); 00389 if ( t ) { 00390 return t->name(); 00391 } 00392 return QString(); 00393 } 00394 00395 int TransportManager::defaultTransportId() const 00396 { 00397 return d->defaultTransportId; 00398 } 00399 00400 void TransportManager::setDefaultTransport( int id ) 00401 { 00402 if ( id == d->defaultTransportId || !transportById( id, false ) ) { 00403 return; 00404 } 00405 d->defaultTransportId = id; 00406 d->writeConfig(); 00407 } 00408 00409 void TransportManager::removeTransport( int id ) 00410 { 00411 Transport *t = transportById( id, false ); 00412 if ( !t ) { 00413 return; 00414 } 00415 emit transportRemoved( t->id(), t->name() ); 00416 00417 // Kill the resource, if Akonadi-type transport. 00418 if( t->type() == Transport::EnumType::Akonadi ) { 00419 using namespace Akonadi; 00420 const AgentInstance instance = AgentManager::self()->instance( t->host() ); 00421 if( !instance.isValid() ) { 00422 kWarning() << "Could not find resource instance."; 00423 } 00424 AgentManager::self()->removeInstance( instance ); 00425 } 00426 00427 d->transports.removeAll( t ); 00428 d->validateDefault(); 00429 QString group = t->currentGroup(); 00430 delete t; 00431 d->config->deleteGroup( group ); 00432 d->writeConfig(); 00433 00434 } 00435 00436 void TransportManagerPrivate::readConfig() 00437 { 00438 QList<Transport *> oldTransports = transports; 00439 transports.clear(); 00440 00441 QRegExp re( QLatin1String( "^Transport (.+)$" ) ); 00442 QStringList groups = config->groupList().filter( re ); 00443 foreach ( const QString &s, groups ) { 00444 re.indexIn( s ); 00445 Transport *t = 0; 00446 00447 // see if we happen to have that one already 00448 foreach ( Transport *old, oldTransports ) { 00449 if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { 00450 kDebug() << "reloading existing transport:" << s; 00451 t = old; 00452 t->readConfig(); 00453 oldTransports.removeAll( old ); 00454 break; 00455 } 00456 } 00457 00458 if ( !t ) { 00459 t = new Transport( re.cap( 1 ) ); 00460 } 00461 if ( t->id() <= 0 ) { 00462 t->setId( createId() ); 00463 t->writeConfig(); 00464 } 00465 transports.append( t ); 00466 } 00467 00468 qDeleteAll( oldTransports ); 00469 oldTransports.clear(); 00470 00471 // read default transport 00472 KConfigGroup group( config, "General" ); 00473 defaultTransportId = group.readEntry( "default-transport", 0 ); 00474 if ( defaultTransportId == 0 ) { 00475 // migrated default transport contains the name instead 00476 QString name = group.readEntry( "default-transport", QString() ); 00477 if ( !name.isEmpty() ) { 00478 Transport *t = q->transportByName( name, false ); 00479 if ( t ) { 00480 defaultTransportId = t->id(); 00481 writeConfig(); 00482 } 00483 } 00484 } 00485 validateDefault(); 00486 migrateToWallet(); 00487 } 00488 00489 void TransportManagerPrivate::writeConfig() 00490 { 00491 KConfigGroup group( config, "General" ); 00492 group.writeEntry( "default-transport", defaultTransportId ); 00493 config->sync(); 00494 q->emitChangesCommitted(); 00495 } 00496 00497 void TransportManagerPrivate::fillTypes() 00498 { 00499 Q_ASSERT( types.isEmpty() ); 00500 00501 // SMTP. 00502 { 00503 TransportType type; 00504 type.d->mType = Transport::EnumType::SMTP; 00505 type.d->mName = i18nc( "@option SMTP transport", "SMTP" ); 00506 type.d->mDescription = i18n( "An SMTP server on the Internet" ); 00507 types << type; 00508 } 00509 00510 // Sendmail. 00511 { 00512 TransportType type; 00513 type.d->mType = Transport::EnumType::Sendmail; 00514 type.d->mName = i18nc( "@option sendmail transport", "Sendmail" ); 00515 type.d->mDescription = i18n( "A local sendmail installation" ); 00516 types << type; 00517 } 00518 00519 // All Akonadi resources with MailTransport capability. 00520 { 00521 using namespace Akonadi; 00522 foreach ( const AgentType &atype, AgentManager::self()->types() ) { 00523 // TODO probably the string "MailTransport" should be #defined somewhere 00524 // and used like that in the resources (?) 00525 if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { 00526 TransportType type; 00527 type.d->mType = Transport::EnumType::Akonadi; 00528 type.d->mAgentType = atype; 00529 type.d->mName = atype.name(); 00530 type.d->mDescription = atype.description(); 00531 types << type; 00532 kDebug() << "Found Akonadi type" << atype.name(); 00533 } 00534 } 00535 00536 // Watch for appearing and disappearing types. 00537 QObject::connect( AgentManager::self(), SIGNAL(typeAdded(Akonadi::AgentType)), 00538 q, SLOT(agentTypeAdded(Akonadi::AgentType)) ); 00539 QObject::connect( AgentManager::self(), SIGNAL(typeRemoved(Akonadi::AgentType)), 00540 q, SLOT(agentTypeRemoved(Akonadi::AgentType)) ); 00541 } 00542 00543 kDebug() << "Have SMTP, Sendmail, and" << types.count() - 2 << "Akonadi types."; 00544 } 00545 00546 void TransportManager::emitChangesCommitted() 00547 { 00548 d->myOwnChange = true; // prevent us from reading our changes again 00549 d->appliedChange = false; // but we have to read them at least once 00550 emit transportsChanged(); 00551 emit changesCommitted(); 00552 } 00553 00554 void TransportManagerPrivate::slotTransportsChanged() 00555 { 00556 if ( myOwnChange && appliedChange ) { 00557 myOwnChange = false; 00558 appliedChange = false; 00559 return; 00560 } 00561 00562 kDebug(); 00563 config->reparseConfiguration(); 00564 // FIXME: this deletes existing transport objects! 00565 readConfig(); 00566 appliedChange = true; // to prevent recursion 00567 emit q->transportsChanged(); 00568 } 00569 00570 int TransportManagerPrivate::createId() const 00571 { 00572 QList<int> usedIds; 00573 foreach ( Transport *t, transports ) { 00574 usedIds << t->id(); 00575 } 00576 usedIds << 0; // 0 is default for unknown 00577 int newId; 00578 do { 00579 newId = KRandom::random(); 00580 } while ( usedIds.contains( newId ) ); 00581 return newId; 00582 } 00583 00584 KWallet::Wallet * TransportManager::wallet() 00585 { 00586 if ( d->wallet && d->wallet->isOpen() ) { 00587 return d->wallet; 00588 } 00589 00590 if ( !Wallet::isEnabled() || d->walletOpenFailed ) { 00591 return 0; 00592 } 00593 00594 WId window = 0; 00595 if ( qApp->activeWindow() ) { 00596 window = qApp->activeWindow()->winId(); 00597 } else if ( !QApplication::topLevelWidgets().isEmpty() ) { 00598 window = qApp->topLevelWidgets().first()->winId(); 00599 } 00600 00601 delete d->wallet; 00602 d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); 00603 00604 if ( !d->wallet ) { 00605 d->walletOpenFailed = true; 00606 return 0; 00607 } 00608 00609 d->prepareWallet(); 00610 return d->wallet; 00611 } 00612 00613 void TransportManagerPrivate::prepareWallet() 00614 { 00615 if ( !wallet ) { 00616 return; 00617 } 00618 if ( !wallet->hasFolder( WALLET_FOLDER ) ) { 00619 wallet->createFolder( WALLET_FOLDER ); 00620 } 00621 wallet->setFolder( WALLET_FOLDER ); 00622 } 00623 00624 void TransportManager::loadPasswords() 00625 { 00626 foreach ( Transport *t, d->transports ) { 00627 t->readPassword(); 00628 } 00629 00630 // flush the wallet queue 00631 const QList<TransportJob*> copy = d->walletQueue; 00632 d->walletQueue.clear(); 00633 foreach ( TransportJob *job, copy ) { 00634 job->start(); 00635 } 00636 00637 emit passwordsChanged(); 00638 } 00639 00640 void TransportManager::loadPasswordsAsync() 00641 { 00642 kDebug(); 00643 00644 // check if there is anything to do at all 00645 bool found = false; 00646 foreach ( Transport *t, d->transports ) { 00647 if ( !t->isComplete() ) { 00648 found = true; 00649 break; 00650 } 00651 } 00652 if ( !found ) { 00653 return; 00654 } 00655 00656 // async wallet opening 00657 if ( !d->wallet && !d->walletOpenFailed ) { 00658 WId window = 0; 00659 if ( qApp->activeWindow() ) { 00660 window = qApp->activeWindow()->winId(); 00661 } else if ( !QApplication::topLevelWidgets().isEmpty() ) { 00662 window = qApp->topLevelWidgets().first()->winId(); 00663 } 00664 00665 d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, 00666 Wallet::Asynchronous ); 00667 if ( d->wallet ) { 00668 connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); 00669 d->walletAsyncOpen = true; 00670 } else { 00671 d->walletOpenFailed = true; 00672 loadPasswords(); 00673 } 00674 return; 00675 } 00676 if ( d->wallet && !d->walletAsyncOpen ) { 00677 loadPasswords(); 00678 } 00679 } 00680 00681 void TransportManagerPrivate::slotWalletOpened( bool success ) 00682 { 00683 kDebug(); 00684 walletAsyncOpen = false; 00685 if ( !success ) { 00686 walletOpenFailed = true; 00687 delete wallet; 00688 wallet = 0; 00689 } else { 00690 prepareWallet(); 00691 } 00692 q->loadPasswords(); 00693 } 00694 00695 void TransportManagerPrivate::validateDefault() 00696 { 00697 if ( !q->transportById( defaultTransportId, false ) ) { 00698 if ( q->isEmpty() ) { 00699 defaultTransportId = -1; 00700 } else { 00701 defaultTransportId = transports.first()->id(); 00702 writeConfig(); 00703 } 00704 } 00705 } 00706 00707 void TransportManagerPrivate::migrateToWallet() 00708 { 00709 // check if we tried this already 00710 static bool firstRun = true; 00711 if ( !firstRun ) { 00712 return; 00713 } 00714 firstRun = false; 00715 00716 // check if we are the main instance 00717 if ( !isMainInstance ) { 00718 return; 00719 } 00720 00721 // check if migration is needed 00722 QStringList names; 00723 foreach ( Transport *t, transports ) { 00724 if ( t->needsWalletMigration() ) { 00725 names << t->name(); 00726 } 00727 } 00728 if ( names.isEmpty() ) { 00729 return; 00730 } 00731 00732 // ask user if he wants to migrate 00733 int result = KMessageBox::questionYesNoList( 00734 0, 00735 i18n( "The following mail transports store their passwords in an " 00736 "unencrypted configuration file.\nFor security reasons, " 00737 "please consider migrating these passwords to KWallet, the " 00738 "KDE Wallet management tool,\nwhich stores sensitive data " 00739 "for you in a strongly encrypted file.\n" 00740 "Do you want to migrate your passwords to KWallet?" ), 00741 names, i18n( "Question" ), 00742 KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), 00743 QString::fromAscii( "WalletMigrate" ) ); 00744 if ( result != KMessageBox::Yes ) { 00745 return; 00746 } 00747 00748 // perform migration 00749 foreach ( Transport *t, transports ) { 00750 if ( t->needsWalletMigration() ) { 00751 t->migrateToWallet(); 00752 } 00753 } 00754 } 00755 00756 void TransportManagerPrivate::dbusServiceUnregistered() 00757 { 00758 QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); 00759 } 00760 00761 void TransportManagerPrivate::agentTypeAdded( const Akonadi::AgentType &atype ) 00762 { 00763 using namespace Akonadi; 00764 if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { 00765 TransportType type; 00766 type.d->mType = Transport::EnumType::Akonadi; 00767 type.d->mAgentType = atype; 00768 type.d->mName = atype.name(); 00769 type.d->mDescription = atype.description(); 00770 types << type; 00771 kDebug() << "Added new Akonadi type" << atype.name(); 00772 } 00773 } 00774 00775 void TransportManagerPrivate::agentTypeRemoved( const Akonadi::AgentType &atype ) 00776 { 00777 using namespace Akonadi; 00778 foreach ( const TransportType &type, types ) { 00779 if( type.type() == Transport::EnumType::Akonadi && 00780 type.agentType() == atype ) { 00781 types.removeAll( type ); 00782 kDebug() << "Removed Akonadi type" << atype.name(); 00783 } 00784 } 00785 } 00786 00787 void TransportManagerPrivate::jobResult( KJob *job ) 00788 { 00789 walletQueue.removeAll( static_cast<TransportJob*>( job ) ); 00790 } 00791 00792 #include "transportmanager.moc"