diff --git a/mailtransport/CMakeLists.txt b/mailtransport/CMakeLists.txt index b07e162e7..0c18fdda5 100644 --- a/mailtransport/CMakeLists.txt +++ b/mailtransport/CMakeLists.txt @@ -1,78 +1,79 @@ add_subdirectory( kconf_update ) add_subdirectory( tests ) add_definitions("-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII") add_definitions( -DKDE_DEFAULT_DEBUG_AREA=5324 ) set(mailtransport_lib_srcs transport.cpp transportmanager.cpp + transporttypeinfo.cpp transportcombobox.cpp transportlistview.cpp transportmanagementwidget.cpp addtransportassistant.cpp transportconfigdialog.cpp transportconfigwidget.cpp akonadiconfigwidget.cpp sendmailconfigwidget.cpp smtpconfigwidget.cpp transportjob.cpp akonadijob.cpp sendmailjob.cpp smtpjob.cpp precommandjob.cpp legacydecrypt.cpp socket.cpp servertest.cpp ) kde4_add_ui_files(mailtransport_lib_srcs addtransportassistanttypepage.ui addtransportassistantnamepage.ui akonadisettings.ui sendmailsettings.ui smtpsettings.ui transportmanagementwidget.ui ) kde4_add_kcfg_files(mailtransport_lib_srcs transportbase.kcfgc) kde4_add_library(mailtransport SHARED ${mailtransport_lib_srcs}) target_link_libraries(mailtransport ${KDE4_KIO_LIBS} akonadi-kde) set_target_properties(mailtransport PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) install(TARGETS mailtransport EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES mailtransport.kcfg DESTINATION ${KCFG_INSTALL_DIR}) set(mailtransport_kcm_srcs configmodule.cpp) kde4_add_plugin(kcm_mailtransport ${mailtransport_kcm_srcs}) target_link_libraries(kcm_mailtransport ${KDE4_KDEUI_LIBS} mailtransport) install(TARGETS kcm_mailtransport DESTINATION ${PLUGIN_INSTALL_DIR}) install(FILES kcm_mailtransport.desktop DESTINATION ${SERVICES_INSTALL_DIR}) install( FILES mailtransport_export.h transportjob.h akonadijob.h sendmailjob.h smtpjob.h ${CMAKE_CURRENT_BINARY_DIR}/transportbase.h transport.h transportmanager.h servertest.h transportcombobox.h transportconfigdialog.h transportmanagementwidget.h DESTINATION ${INCLUDE_INSTALL_DIR}/mailtransport COMPONENT Devel) diff --git a/mailtransport/TODO.cberzan b/mailtransport/TODO.cberzan index e03579abf..d5c4cc074 100644 --- a/mailtransport/TODO.cberzan +++ b/mailtransport/TODO.cberzan @@ -1,14 +1,12 @@ * TransportConfigDialog needs validate() * all CamelCase... * smtpsettings.ui has hidden widgets... test those... and why can't I set/see the 'visible' property in designer? * why is identitylistview in kmail instead of kpimidentities? -* figure out what needs to be exported and what not +* figure out what needs to be exported and what not (add .hs to CMakeLists afterwards) * include KLocale or KLocalizedString?? Design: * is there a way to make KConfig XT give me separate settings for SMTP, Sendmail, Akonadi? Currently all of the settings are for SMTP, and Sendmail and Akonadi just use the 'host' setting for storing the sendmail path or Akonadi resource id, respectively. -* transport type manager to handle all the switches - -> also configWidgetForType Bugs: * modify -> change password -> ok. password is saved in wallet and seen ok on restart, but clicking modify again shows old password diff --git a/mailtransport/addtransportassistant.cpp b/mailtransport/addtransportassistant.cpp index f5d0139ce..e3c4ca14b 100644 --- a/mailtransport/addtransportassistant.cpp +++ b/mailtransport/addtransportassistant.cpp @@ -1,199 +1,194 @@ /* Copyright (c) 2009 Constantin Berzan Based on code from Kopete (addaccountwizard) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "addtransportassistant.h" +#include "transport.h" +#include "transportconfigwidget.h" +#include "transportmanager.h" +#include "transporttypeinfo.h" + #include #include #include #include -#include "transportconfigwidget.h" -#include "transport.h" -#include "transportbase.h" -#include "transportmanager.h" - #include "ui_addtransportassistanttypepage.h" #include "ui_addtransportassistantnamepage.h" using namespace MailTransport; /** @internal */ class AddTransportAssistant::Private { public: Private() : typePage( 0 ) , configPage( 0 ) , namePage( 0 ) , configPageContents( 0 ) , transport( 0 ) , lastType( -1 ) { } QTreeWidgetItem* selectedType(); KPageWidgetItem *typeItem; KPageWidgetItem *configItem; KPageWidgetItem *nameItem; QWidget *typePage; KVBox *configPage; QWidget *namePage; TransportConfigWidget *configPageContents; Transport *transport; int lastType; Ui::AddTransportAssistantTypePage uiTypePage; Ui::AddTransportAssistantNamePage uiNamePage; }; AddTransportAssistant::AddTransportAssistant( QWidget *parent ) : KAssistantDialog( parent ) , d( new Private ) { + d->transport = TransportManager::self()->createTransport(); + Q_ASSERT( d->transport ); + // type page d->typePage = new QWidget( this ); d->uiTypePage.setupUi( d->typePage ); d->uiTypePage.typeListView->setColumnCount( 2 ); QStringList header; header << i18n( "Type" ) << i18n( "Description" ); d->uiTypePage.typeListView->setHeaderLabels( header ); d->typeItem = addPage( d->typePage, d->typePage->windowTitle() ); setValid( d->typeItem, false ); // populate type list - // TODO: HACKish way to get transport descriptions... - // TODO TransportManagementWidget has i18ns for transport types -> share? - Q_ASSERT( d->transport == 0 ); - d->transport = TransportManager::self()->createTransport(); - Q_ASSERT( d->transport ); - int enumid = 0; - const KConfigSkeleton::ItemEnum *const item = d->transport->typeItem(); - foreach( const KConfigSkeleton::ItemEnum::Choice2 &choice, item->choices2() ) { + for( int i = 0; i < TransportTypeInfo::typeCount(); i++ ) { QTreeWidgetItem *treeItem = new QTreeWidgetItem( d->uiTypePage.typeListView ); - treeItem->setData( 0, Qt::UserRole, enumid ); // the transport type - enumid++; - treeItem->setText( 0, choice.label ); - treeItem->setText( 1, choice.whatsThis ); + treeItem->setData( 0, Qt::UserRole, i ); // the transport type + treeItem->setText( 0, TransportTypeInfo::nameForType( i ) ); + treeItem->setText( 1, TransportTypeInfo::descriptionForType( i ) ); } d->uiTypePage.typeListView->resizeColumnToContents( 0 ); d->uiTypePage.typeListView->setFocus(); // connect user input connect( d->uiTypePage.typeListView, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), this, SLOT( typeListClicked() ) ); connect( d->uiTypePage.typeListView, SIGNAL( itemSelectionChanged() ), this, SLOT( typeListClicked() ) ); connect( d->uiTypePage.typeListView, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ), this, SLOT( typeListDoubleClicked() ) ); // settings page d->configPage = new KVBox( this ); d->configItem = addPage( d->configPage, i18n( "Step Two: Transport Settings" ) ); // name page d->namePage = new QWidget( this ); d->uiNamePage.setupUi( d->namePage ); // TODO set up sensible default name d->nameItem = addPage( d->namePage, d->namePage->windowTitle() ); } QTreeWidgetItem* AddTransportAssistant::Private::selectedType() { QList sel = uiTypePage.typeListView->selectedItems(); if( !sel.empty() ) return sel.first(); return 0; } void AddTransportAssistant::typeListClicked() { // Make sure a type is selected before allowing the user to continue. setValid( d->typeItem, d->selectedType() != 0 ); } void AddTransportAssistant::typeListDoubleClicked() { // Proceed to the next page if a type is double clicked. next(); } void AddTransportAssistant::accept() { // register transport d->configPageContents->apply(); TransportManager::self()->addTransport( d->transport ); d->transport = 0; // don't delete it if( d->uiNamePage.setDefault->isChecked() ) { TransportManager::self()->setDefaultTransport( d->transport->id() ); } KAssistantDialog::accept(); } void AddTransportAssistant::next() { if( currentPage() == d->typeItem ) { QTreeWidgetItem *item = d->selectedType(); int type = item->data( 0, Qt::UserRole ).toInt(); // the transport type Q_ASSERT( type >= 0 && type < TransportBase::EnumType::COUNT ); // create appropriate config widget if( d->configPageContents && d->lastType == type ) { // same type as before; keep settings } else { d->transport->setType( type ); d->lastType = type; delete d->configPageContents; - d->configPageContents = TransportManager::self()->configWidgetForTransport( d->transport, d->configPage ); + d->configPageContents = TransportTypeInfo::configWidgetForTransport( d->transport, d->configPage ); // let the configWidget's KConfigDialogManager handle kcfg_name: KConfigDialogManager *mgr = d->configPageContents->configManager(); Q_ASSERT( mgr ); Q_ASSERT( d->namePage ); mgr->addWidget( d->namePage ); } } KAssistantDialog::next(); } void AddTransportAssistant::reject() { delete d->transport; d->transport = 0; KAssistantDialog::reject(); } AddTransportAssistant::~AddTransportAssistant() { delete d->transport; delete d; } #include "addtransportassistant.moc" diff --git a/mailtransport/mailtransport.kcfg b/mailtransport/mailtransport.kcfg index 60ab46fae..c1a71f331 100644 --- a/mailtransport/mailtransport.kcfg +++ b/mailtransport/mailtransport.kcfg @@ -1,118 +1,115 @@ 0 The name that will be used when referring to this server. i18n("Unnamed") - TODO smtp description - TODO sendmail description - TODO Akonadi description SMTP The domain name or numerical address of the SMTP server. The port number that the SMTP server is listening on. The default port is 25. 25 The user name to send to the server for authorization. A command to run locally, prior to sending email. This can be used to set up SSH tunnels, for example. Leave it empty if no command should be run. Check this option if your SMTP server requires authentication before accepting mail. This is known as 'Authenticated SMTP' or simply ASMTP. false Check this option to have your password stored. If KWallet is available the password will be stored there which is considered safe. However, if KWallet is not available, the password will be stored in the configuration file. The password is stored in an obfuscated format, but should not be considered secure from decryption efforts if access to the configuration file is obtained. false PLAIN Check this option to use a custom hostname when identifying to the mail server. This is useful when your system's hostname may not be set correctly or to mask your system's true hostname. false Enter the hostname that should be used when identifying to the server. diff --git a/mailtransport/transportconfigdialog.cpp b/mailtransport/transportconfigdialog.cpp index e755e89b9..7d9c1dded 100644 --- a/mailtransport/transportconfigdialog.cpp +++ b/mailtransport/transportconfigdialog.cpp @@ -1,64 +1,65 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Copyright (c) 2009 Constantin Berzan Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportconfigdialog.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportmanager.h" +#include "transporttypeinfo.h" #include #include using namespace MailTransport; class MailTransport::TransportConfigDialog::Private { public: TransportConfigWidget *configWidget; // TODO not really necessary right now; used only in constructor }; TransportConfigDialog::TransportConfigDialog( Transport *transport, QWidget *parent ) : KDialog( parent ), d( new Private ) { Q_ASSERT( transport ); - d->configWidget = TransportManager::self()->configWidgetForTransport( transport ); + d->configWidget = TransportTypeInfo::configWidgetForTransport( transport ); kDebug() << "transport" << transport->id() << "config widget" << d->configWidget; Q_ASSERT( d->configWidget ); setMainWidget( d->configWidget ); setButtons( Ok|Cancel ); connect( this, SIGNAL( okClicked() ), d->configWidget, SLOT( apply() ) ); } TransportConfigDialog::~ TransportConfigDialog() { delete d; } #include "transportconfigdialog.moc" diff --git a/mailtransport/transportlistview.cpp b/mailtransport/transportlistview.cpp index 1471bcc01..2a296c803 100644 --- a/mailtransport/transportlistview.cpp +++ b/mailtransport/transportlistview.cpp @@ -1,129 +1,116 @@ /* Copyright (c) 2009 Constantin Berzan Based on KMail code by: Copyright (c) 2002 Marc Mutz 2007 Mathias Soeken This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportlistview.h" #include "transport.h" #include "transportmanager.h" +#include "transporttypeinfo.h" #include #include #include #include using namespace MailTransport; TransportListView::TransportListView( QWidget *parent ) : QTreeWidget( parent ) { setHeaderLabels( QStringList() << i18nc( "@title:column email transport name", "Name" ) << i18nc( "@title:column email transport type", "Type" ) ); setRootIsDecorated( false ); header()->setMovable( false ); setAllColumnsShowFocus( true ); setAlternatingRowColors( true ); setSortingEnabled( true ); sortByColumn( 0, Qt::AscendingOrder ); setSelectionMode( SingleSelection ); fillTransportList(); connect( TransportManager::self(), SIGNAL(transportsChanged()), this, SLOT(fillTransportList()) ); } void TransportListView::editItem( QTreeWidgetItem *item, int column ) { // TODO: is there a nicer way to make only the 'name' column editable? if ( column == 0 && item ) { Qt::ItemFlags oldFlags = item->flags(); item->setFlags( oldFlags | Qt::ItemIsEditable ); QTreeWidget::editItem( item, 0 ); item->setFlags( oldFlags ); } } void TransportListView::commitData( QWidget *editor ) { if( selectedItems().size() < 1 ) { // transport was deleted by someone else??? kDebug() << "No selected item."; return; } QTreeWidgetItem *item = selectedItems()[0]; QLineEdit *edit = dynamic_cast( editor ); // krazy:exclude=qclasses Q_ASSERT( edit ); // original code had if int id = item->data( 0, Qt::UserRole ).toInt(); Transport *t = TransportManager::self()->transportById( id ); if( !t ) { kWarning() << "Transport" << id << "not known by manager."; return; } kDebug() << "Renaming transport" << id << "to" << edit->text(); t->setName( edit->text() ); t->forceUniqueName(); t->writeConfig(); } void TransportListView::fillTransportList() { // try to preserve the selection int selected = -1; if ( currentItem() ) { selected = currentItem()->data( 0, Qt::UserRole ).toInt(); } clear(); foreach ( Transport *t, TransportManager::self()->transports() ) { QTreeWidgetItem *item = new QTreeWidgetItem( this ); item->setData( 0, Qt::UserRole, t->id() ); item->setText( 0, t->name() ); - QString type; - // TODO: perhaps Transport or TransportManager should have nameForType()? - switch ( t->type() ) { - case Transport::EnumType::SMTP: - type = i18nc( "@option SMTP transport", "SMTP" ); - break; - case Transport::EnumType::Sendmail: - type = i18nc( "@option sendmail transport", "Sendmail" ); - break; - case Transport::EnumType::Akonadi: - type = i18nc( "@option Akonadi Resource transport", "Akonadi Resource" ); - break; - } + QString type = TransportTypeInfo::nameForType( t->type() ); if ( TransportManager::self()->defaultTransportId() == t->id() ) { type += i18nc( "@label the default mail transport", " (Default)" ); } item->setText( 1, type ); if ( t->id() == selected ) { setCurrentItem( item ); } } - - // updateButtonState(); //TODO see comment in TransportManagementWidget } #include "transportlistview.moc" diff --git a/mailtransport/transportmanager.cpp b/mailtransport/transportmanager.cpp index 632b8bf61..57160af24 100644 --- a/mailtransport/transportmanager.cpp +++ b/mailtransport/transportmanager.cpp @@ -1,612 +1,582 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportmanager.h" #include "mailtransport_defs.h" #include "transport.h" -#include "akonadijob.h" -#include "sendmailjob.h" -#include "smtpjob.h" #include "transportconfigwidget.h" -#include "sendmailconfigwidget.h" -#include "akonadiconfigwidget.h" -#include "smtpconfigwidget.h" +#include "transportjob.h" +#include "transporttypeinfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportManager::Private { public: Private() {} ~Private() { delete config; qDeleteAll( transports ); } KConfig *config; QList transports; bool myOwnChange; bool appliedChange; KWallet::Wallet *wallet; bool walletOpenFailed; bool walletAsyncOpen; int defaultTransportId; bool isMainInstance; QList walletQueue; }; class StaticTransportManager : public TransportManager { public: StaticTransportManager() : TransportManager() {} }; StaticTransportManager *sSelf = 0; static void destroyStaticTransportManager() { delete sSelf; } TransportManager::TransportManager() : QObject(), d( new Private ) { KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); qAddPostRoutine( destroyStaticTransportManager ); d->myOwnChange = false; d->appliedChange = false; d->wallet = 0; d->walletOpenFailed = false; d->walletAsyncOpen = false; d->defaultTransportId = -1; d->config = new KConfig( QLatin1String( "mailtransports" ) ); QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals ); QDBusConnection::sessionBus().connect( QString(), QString(), DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, this, SLOT(slotTransportsChanged()) ); d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(dbusServiceOwnerChanged(QString,QString,QString)) ); } TransportManager::~TransportManager() { qRemovePostRoutine( destroyStaticTransportManager ); delete d; } TransportManager *TransportManager::self() { if ( !sSelf ) { sSelf = new StaticTransportManager; sSelf->readConfig(); } return sSelf; } Transport *TransportManager::transportById( int id, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->id() == id ) { return t; } } if ( def || ( id == 0 && d->defaultTransportId != id ) ) { return transportById( d->defaultTransportId, false ); } return 0; } Transport *TransportManager::transportByName( const QString &name, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->name() == name ) { return t; } } if ( def ) { return transportById( 0, false ); } return 0; } QList< Transport * > TransportManager::transports() const { return d->transports; } Transport *TransportManager::createTransport() const { int id = createId(); Transport *t = new Transport( QString::number( id ) ); t->setId( id ); return t; } void TransportManager::addTransport( Transport *transport ) { if ( d->transports.contains( transport ) ) { return; } d->transports.append( transport ); validateDefault(); emitChangesCommitted(); } void TransportManager::schedule( TransportJob *job ) { connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); // check if the job is waiting for the wallet if ( !job->transport()->isComplete() ) { kDebug() << "job waits for wallet:" << job; d->walletQueue << job; loadPasswordsAsync(); return; } job->start(); } void TransportManager::createDefaultTransport() { KEMailSettings kes; Transport *t = createTransport(); t->setName( i18n( "Default Transport" ) ); t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); if ( t->isValid() ) { t->writeConfig(); addTransport( t ); } else { kWarning() << "KEMailSettings does not contain a valid transport."; } } TransportJob *TransportManager::createTransportJob( int transportId ) { Transport *t = transportById( transportId, false ); if ( !t ) { return 0; } - switch ( t->type() ) { - case Transport::EnumType::SMTP: - return new SmtpJob( t->clone(), this ); - case Transport::EnumType::Sendmail: - return new SendmailJob( t->clone(), this ); - case Transport::EnumType::Akonadi: - return new AkonadiJob( t->clone(), this ); - } - Q_ASSERT( false ); - return 0; + return TransportTypeInfo::jobForTransport( t->clone(), this ); } TransportJob *TransportManager::createTransportJob( const QString &transport ) { bool ok = false; Transport *t = 0; int transportId = transport.toInt( &ok ); if ( ok ) { t = transportById( transportId ); } if ( !t ) { t = transportByName( transport, false ); } if ( t ) { return createTransportJob( t->id() ); } return 0; } -TransportConfigWidget *TransportManager::configWidgetForTransport( Transport *transport, QWidget *parent ) -{ - Q_ASSERT( transport ); - - switch( transport->type() ) { - case Transport::EnumType::SMTP: - return new SMTPConfigWidget( transport, parent ); - case Transport::EnumType::Sendmail: - return new SendmailConfigWidget( transport, parent ); - case Transport::EnumType::Akonadi: - return new AkonadiConfigWidget( transport, parent ); - } - Q_ASSERT( false ); - return 0; -} - - bool TransportManager::isEmpty() const { return d->transports.isEmpty(); } QList TransportManager::transportIds() const { QList rv; foreach ( Transport *t, d->transports ) { rv << t->id(); } return rv; } QStringList TransportManager::transportNames() const { QStringList rv; foreach ( Transport *t, d->transports ) { rv << t->name(); } return rv; } QString TransportManager::defaultTransportName() const { Transport *t = transportById( d->defaultTransportId, false ); if ( t ) { return t->name(); } return QString(); } int TransportManager::defaultTransportId() const { return d->defaultTransportId; } void TransportManager::setDefaultTransport( int id ) { if ( id == d->defaultTransportId || !transportById( id, false ) ) { return; } d->defaultTransportId = id; writeConfig(); } void TransportManager::removeTransport( int id ) { Transport *t = transportById( id, false ); if ( !t ) { return; } emit transportRemoved( t->id(), t->name() ); d->transports.removeAll( t ); validateDefault(); QString group = t->currentGroup(); delete t; d->config->deleteGroup( group ); writeConfig(); } void TransportManager::readConfig() { QList oldTransports = d->transports; d->transports.clear(); QRegExp re( QLatin1String( "^Transport (.+)$" ) ); QStringList groups = d->config->groupList().filter( re ); foreach ( const QString &s, groups ) { re.indexIn( s ); Transport *t = 0; // see if we happen to have that one already foreach ( Transport *old, oldTransports ) { if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { kDebug() << "reloading existing transport:" << s; t = old; t->readConfig(); oldTransports.removeAll( old ); break; } } if ( !t ) { t = new Transport( re.cap( 1 ) ); } if ( t->id() <= 0 ) { t->setId( createId() ); t->writeConfig(); } d->transports.append( t ); } qDeleteAll( oldTransports ); oldTransports.clear(); // read default transport KConfigGroup group( d->config, "General" ); d->defaultTransportId = group.readEntry( "default-transport", 0 ); if ( d->defaultTransportId == 0 ) { // migrated default transport contains the name instead QString name = group.readEntry( "default-transport", QString() ); if ( !name.isEmpty() ) { Transport *t = transportByName( name, false ); if ( t ) { d->defaultTransportId = t->id(); writeConfig(); } } } validateDefault(); migrateToWallet(); } void TransportManager::writeConfig() { KConfigGroup group( d->config, "General" ); group.writeEntry( "default-transport", d->defaultTransportId ); d->config->sync(); emitChangesCommitted(); } void TransportManager::emitChangesCommitted() { d->myOwnChange = true; // prevent us from reading our changes again d->appliedChange = false; // but we have to read them at least once emit transportsChanged(); emit changesCommitted(); } void TransportManager::slotTransportsChanged() { if ( d->myOwnChange && d->appliedChange ) { d->myOwnChange = false; d->appliedChange = false; return; } kDebug(); d->config->reparseConfiguration(); // FIXME: this deletes existing transport objects! readConfig(); d->appliedChange = true; // to prevent recursion emit transportsChanged(); } int TransportManager::createId() const { QList usedIds; foreach ( Transport *t, d->transports ) { usedIds << t->id(); } usedIds << 0; // 0 is default for unknown int newId; do { newId = KRandom::random(); } while ( usedIds.contains( newId ) ); return newId; } KWallet::Wallet * TransportManager::wallet() { if ( d->wallet && d->wallet->isOpen() ) { return d->wallet; } if ( !Wallet::isEnabled() || d->walletOpenFailed ) { return 0; } WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } delete d->wallet; d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); if ( !d->wallet ) { d->walletOpenFailed = true; return 0; } prepareWallet(); return d->wallet; } void TransportManager::prepareWallet() { if ( !d->wallet ) { return; } if ( !d->wallet->hasFolder( WALLET_FOLDER ) ) { d->wallet->createFolder( WALLET_FOLDER ); } d->wallet->setFolder( WALLET_FOLDER ); } void TransportManager::loadPasswords() { foreach ( Transport *t, d->transports ) { t->readPassword(); } // flush the wallet queue foreach ( TransportJob *job, d->walletQueue ) { job->start(); } d->walletQueue.clear(); emit passwordsChanged(); } void TransportManager::loadPasswordsAsync() { kDebug(); // check if there is anything to do at all bool found = false; foreach ( Transport *t, d->transports ) { if ( !t->isComplete() ) { found = true; break; } } if ( !found ) { return; } // async wallet opening if ( !d->wallet && !d->walletOpenFailed ) { WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, Wallet::Asynchronous ); if ( d->wallet ) { connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); d->walletAsyncOpen = true; } else { d->walletOpenFailed = true; loadPasswords(); } return; } if ( d->wallet && !d->walletAsyncOpen ) { loadPasswords(); } } void TransportManager::slotWalletOpened( bool success ) { kDebug(); d->walletAsyncOpen = false; if ( !success ) { d->walletOpenFailed = true; delete d->wallet; d->wallet = 0; } else { prepareWallet(); } loadPasswords(); } void TransportManager::validateDefault() { if ( !transportById( d->defaultTransportId, false ) ) { if ( isEmpty() ) { d->defaultTransportId = -1; } else { d->defaultTransportId = d->transports.first()->id(); writeConfig(); } } } void TransportManager::migrateToWallet() { // check if we tried this already static bool firstRun = true; if ( !firstRun ) { return; } firstRun = false; // check if we are the main instance if ( !d->isMainInstance ) { return; } // check if migration is needed QStringList names; foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { names << t->name(); } } if ( names.isEmpty() ) { return; } // ask user if he wants to migrate int result = KMessageBox::questionYesNoList( 0, i18n( "The following mail transports store their passwords in an " "unencrypted configuration file.\nFor security reasons, " "please consider migrating these passwords to KWallet, the " "KDE Wallet management tool,\nwhich stores sensitive data " "for you in a strongly encrypted file.\n" "Do you want to migrate your passwords to KWallet?" ), names, i18n( "Question" ), KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), QString::fromAscii( "WalletMigrate" ) ); if ( result != KMessageBox::Yes ) { return; } // perform migration foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { t->migrateToWallet(); } } } void TransportManager::dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ) { Q_UNUSED( oldOwner ); if ( service == DBUS_SERVICE_NAME && newOwner.isEmpty() ) { QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); } } void TransportManager::jobResult( KJob *job ) { d->walletQueue.removeAll( static_cast( job ) ); } #include "transportmanager.moc" diff --git a/mailtransport/transportmanager.h b/mailtransport/transportmanager.h index e31255eda..376efc4f2 100644 --- a/mailtransport/transportmanager.h +++ b/mailtransport/transportmanager.h @@ -1,266 +1,255 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTMANAGER_H #define MAILTRANSPORT_TRANSPORTMANAGER_H #include #include #include class KJob; namespace KWallet { class Wallet; } namespace MailTransport { class Transport; class TransportConfigWidget; class TransportJob; /** Takes care of loading and storing mail transport settings and creating of transport jobs. */ class MAILTRANSPORT_EXPORT TransportManager : public QObject { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kde.pim.TransportManager" ) friend class Transport; friend class Private; public: class Private; /** Destructor. */ virtual ~TransportManager(); /** Returns the TransportManager instance. */ static TransportManager *self(); /** Tries to load passwords asynchronously from KWallet if needed. The passwordsChanged() signal is emitted once the passwords have been loaded. Nothing happens if the passwords were already available. */ void loadPasswordsAsync(); /** Returns the Transport object with the given id. @param id The identifier of the Transport. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use. It might become invalid as soon as the event loop is entered again due to remote changes. If you need to store a Transport object, store the transport identifier instead. */ Transport *transportById( int id, bool def = true ) const; /** Returns the transport object with the given name. @param name The transport name. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use, see transportById() for limitations. */ Transport *transportByName( const QString &name, bool def = true ) const; /** Returns a list of all available transports. Note: The Transport objects become invalid as soon as a change occur, so they are only suitable for immediate use. */ QListtransports() const; /** Creates a new, empty Transport object. The object is owned by the caller. If you want to add the Transport permanently (eg. after configuring it) call addTransport(). */ Transport *createTransport() const; /** Adds the given transport. The object ownership is transferred to TransportMananger, ie. you must not delete @p transport. @param transport The Transport object to add. */ void addTransport( Transport *transport ); /** Creates a mail transport job for the given transport identifier. Returns 0 if the specified transport is invalid. @param transportId The transport identifier. */ TransportJob *createTransportJob( int transportId ); /** Creates a mail transport job for the given transport identifer, or transport name. Returns 0 if the specified transport is invalid. @param transport A string defining a mail transport. */ TransportJob *createTransportJob( const QString &transport ); /** Executes the given transport job. This is the preferred way to start transport jobs. It takes care of asynchronously loading passwords from KWallet if necessary. @param job The completely configured transport job to execute. */ void schedule( TransportJob *job ); /** Tries to create a transport based on KEMailSettings. If the data in KEMailSettings is incomplete, no transport is created. */ void createDefaultTransport(); - /** - Creates an appropriate configuration widget for the transport, depending - on its type. - - @param transport The transport - @param parent The parent passed to the widget's constructor - - TODO should this be public? - */ - TransportConfigWidget *configWidgetForTransport( Transport *transport, QWidget *parent = 0 ); - public Q_SLOTS: /** Returns true if there are no mail transports at all. */ Q_SCRIPTABLE bool isEmpty() const; /** Returns a list of transport identifiers. */ Q_SCRIPTABLE QList transportIds() const; /** Returns a list of transport names. */ Q_SCRIPTABLE QStringList transportNames() const; /** Returns the default transport name. */ Q_SCRIPTABLE QString defaultTransportName() const; /** Returns the default transport identifier. Invalid if there are no transports at all. */ Q_SCRIPTABLE int defaultTransportId() const; /** Sets the default transport. The change will be in effect immediately. @param id The identifier of the new default transport. */ Q_SCRIPTABLE void setDefaultTransport( int id ); /** Deletes the specified transport. @param id The identifier of the mail transport to remove. */ Q_SCRIPTABLE void removeTransport( int id ); Q_SIGNALS: /** Emitted when transport settings have changed (by this or any other TransportManager instance). */ Q_SCRIPTABLE void transportsChanged(); /** Internal signal to synchronize all TransportManager instances. This signal is emitted by the instance writing the changes. You probably want to use transportsChanged() instead. */ Q_SCRIPTABLE void changesCommitted(); /** Emitted when passwords have been loaded from the wallet. If you made a deep copy of a transport, you should call updatePasswordState() for the cloned transport to ensure its password is updated as well. */ void passwordsChanged(); /** Emitted when a transport is deleted. @param id The identifier of the deleted transport. @param name The name of the deleted transport. */ void transportRemoved( int id, const QString &name ); /** Emitted when a transport has been renamed. @param id The identifier of the renamed transport. @param oldName The old name. @param newName The new name. */ void transportRenamed( int id, const QString &oldName, const QString &newName ); protected: /** Returns a pointer to an open wallet if available, 0 otherwise. The wallet is opened synchronously if necessary. */ KWallet::Wallet *wallet(); /** Loads all passwords synchronously. */ void loadPasswords(); TransportManager(); private: void readConfig(); void writeConfig(); void emitChangesCommitted(); int createId() const; void prepareWallet(); void validateDefault(); void migrateToWallet(); private Q_SLOTS: void slotTransportsChanged(); void slotWalletOpened( bool success ); void dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ); void jobResult( KJob *job ); private: Private *const d; }; } #endif diff --git a/mailtransport/transporttypeinfo.cpp b/mailtransport/transporttypeinfo.cpp new file mode 100644 index 000000000..4d95b6442 --- /dev/null +++ b/mailtransport/transporttypeinfo.cpp @@ -0,0 +1,98 @@ +/* + Copyright (c) 2009 Constantin Berzan + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "transporttypeinfo.h" + +#include "akonadiconfigwidget.h" +#include "sendmailconfigwidget.h" +#include "smtpconfigwidget.h" +#include "akonadijob.h" +#include "sendmailjob.h" +#include "smtpjob.h" +#include "transport.h" + +#include +#include + +#include + +using namespace MailTransport; + +int TransportTypeInfo::typeCount() +{ + return 3; +} + +QString TransportTypeInfo::nameForType( int type ) +{ + switch( type ) { + case Transport::EnumType::SMTP: + return i18nc( "@option SMTP transport", "SMTP" ); + case Transport::Transport::EnumType::Sendmail: + return i18nc( "@option sendmail transport", "Sendmail" ); + case Transport::EnumType::Akonadi: + return i18nc( "@option Akonadi Resource transport", "Akonadi Resource" ); + } + Q_ASSERT( false ); + return QString(); +} + +QString TransportTypeInfo::descriptionForType( int type ) +{ + // TODO polish these + switch( type ) { + case Transport::EnumType::SMTP: + return i18n( "An SMTP server on the internet" ); + case Transport::EnumType::Sendmail: + return i18n( "A local sendmail installation" ); + case Transport::EnumType::Akonadi: + return i18n( "A local Akonadi resource with the ability to send mail" ); + } + Q_ASSERT( false ); + return QString(); +} + +TransportJob *TransportTypeInfo::jobForTransport( Transport *transport, QObject *parent ) +{ + switch( transport->type() ) { + case Transport::EnumType::SMTP: + return new SmtpJob( transport, parent ); + case Transport::EnumType::Sendmail: + return new SendmailJob( transport, parent ); + case Transport::EnumType::Akonadi: + return new AkonadiJob( transport, parent ); + } + Q_ASSERT( false ); + return 0; +} + +TransportConfigWidget *TransportTypeInfo::configWidgetForTransport( Transport *transport, QWidget *parent ) +{ + switch( transport->type() ) { + case Transport::EnumType::SMTP: + return new SMTPConfigWidget( transport, parent ); + case Transport::EnumType::Sendmail: + return new SendmailConfigWidget( transport, parent ); + case Transport::EnumType::Akonadi: + return new AkonadiConfigWidget( transport, parent ); + } + Q_ASSERT( false ); + return 0; +} + diff --git a/mailtransport/transporttypeinfo.h b/mailtransport/transporttypeinfo.h new file mode 100644 index 000000000..5941fb857 --- /dev/null +++ b/mailtransport/transporttypeinfo.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2009 Constantin Berzan + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef MAILTRANSPORT_TRANSPORTTYPEINFO_H +#define MAILTRANSPORT_TRANSPORTTYPEINFO_H + +#include + +class QObject; +class QWidget; + +namespace MailTransport { + +class Transport; +class TransportConfigWidget; +class TransportJob; + +/** + A class providing central information about the types supported by + Mailtransport. It avoids having to switch(type) all over the place. + + TODO export? + + TODO docu +*/ +class TransportTypeInfo +{ + public: + static int typeCount(); + + static QString nameForType( int type ); + static QString descriptionForType( int type ); + static TransportJob *jobForTransport( Transport *transport, QObject *parent = 0 ); + static TransportConfigWidget *configWidgetForTransport( Transport *transport, QWidget *parent = 0 ); + + private: + TransportTypeInfo(); + ~TransportTypeInfo(); + +}; + +} + +#endif