• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kmail

configuredialog.cpp

Go to the documentation of this file.
00001 /*   -*- mode: C++; c-file-style: "gnu" -*-
00002  *   kmail: KDE mail client
00003  *   Copyright (C) 2000 Espen Sand, espen@kde.org
00004  *   Copyright (C) 2001-2003 Marc Mutz, mutz@kde.org
00005  *   Contains code segments and ideas from earlier kmail dialog code.
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License as published by
00009  *   the Free Software Foundation; either version 2 of the License, or
00010  *   (at your option) any later version.
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License along
00018  *   with this program; if not, write to the Free Software Foundation, Inc.,
00019  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // my headers:
00024 #include "configuredialog.h"
00025 #include "configuredialog_p.h"
00026 
00027 #include <config-kmail.h>
00028 
00029 #include "globalsettings.h"
00030 #include "templatesconfiguration_kfg.h"
00031 
00032 // other KMail headers:
00033 #include "kmkernel.h"
00034 #include "simplestringlisteditor.h"
00035 #include "accountdialog.h"
00036 #include <libkdepim/colorlistbox.h>
00037 #include "kmacctseldlg.h"
00038 using KMail::AccountDialog;
00039 #include "messagesender.h"
00040 #include "kmfoldermgr.h"
00041 #include <kpimidentities/identitymanager.h>
00042 #include "identitylistview.h"
00043 using KMail::IdentityListView;
00044 using KMail::IdentityListViewItem;
00045 #include "kcursorsaver.h"
00046 #include "accountmanager.h"
00047 #include "folderrequester.h"
00048 using KMail::FolderRequester;
00049 #include "accountcombobox.h"
00050 #include "imapaccountbase.h"
00051 using KMail::ImapAccountBase;
00052 #include "folderstorage.h"
00053 #include "kmfolder.h"
00054 #include "kmmainwidget.h"
00055 #include "kmmessagetag.h"
00056 #include "recentaddresses.h"
00057 using KPIM::RecentAddresses;
00058 #include "completionordereditor.h"
00059 #include "ldapclient.h"
00060 
00061 #include "templatesconfiguration.h"
00062 #include "customtemplates.h"
00063 
00064 using KMail::IdentityListView;
00065 using KMail::IdentityListViewItem;
00066 #include "identitydialog.h"
00067 using KMail::IdentityDialog;
00068 
00069 // other kdenetwork headers:
00070 #include <kpimidentities/identity.h>
00071 #include <kmime/kmime_dateformatter.h>
00072 using KMime::DateFormatter;
00073 #include "kleo/cryptoconfig.h"
00074 #include "kleo/cryptobackendfactory.h"
00075 #include "libkleo/ui/backendconfigwidget.h"
00076 #include "libkleo/ui/keyrequester.h"
00077 #include "libkleo/ui/keyselectiondialog.h"
00078 
00079 #include <mailtransport/transportmanagementwidget.h>
00080 using MailTransport::TransportManagementWidget;
00081 
00082 // other KDE headers:
00083 #include <klineedit.h>
00084 #include <klocale.h>
00085 #include <kcharsets.h>
00086 #include <kascii.h>
00087 #include <knuminput.h>
00088 #include <kfontchooser.h>
00089 #include <kmessagebox.h>
00090 #include <kurlrequester.h>
00091 #include <kseparator.h>
00092 #include <kiconloader.h>
00093 #include <kstandarddirs.h>
00094 #include <kwindowsystem.h>
00095 #include <kconfig.h>
00096 #include <kcmultidialog.h>
00097 #include <knotifyconfigwidget.h>
00098 #include <kconfiggroup.h>
00099 #include <kbuttongroup.h>
00100 #include <kcolorcombo.h>
00101 #include <kfontrequester.h>
00102 #include <kicondialog.h>
00103 #include <kkeysequencewidget.h>
00104 #include <KIconButton>
00105 #include <KRandom>
00106 #include <KColorScheme>
00107 
00108 // Qt headers:
00109 #include <QBoxLayout>
00110 #include <QCheckBox>
00111 #include <QGridLayout>
00112 #include <QHBoxLayout>
00113 #include <QHideEvent>
00114 #include <QLabel>
00115 #include <QLayout>
00116 #include <QList>
00117 #include <QRadioButton>
00118 #include <QGroupBox>
00119 #include <QToolTip>
00120 #include <QListWidget>
00121 #include <QValidator>
00122 #include <QVBoxLayout>
00123 #include <QWhatsThis>
00124 #include <QDBusConnection>
00125 #include <QHostInfo>
00126 #include <QTextCodec>
00127 #include <QMenu>
00128 
00129 // other headers:
00130 #include <assert.h>
00131 #include <stdlib.h>
00132 #include <kvbox.h>
00133 
00134 #ifndef _PATH_SENDMAIL
00135 #define _PATH_SENDMAIL  "/usr/sbin/sendmail"
00136 #endif
00137 
00138 #ifdef DIM
00139 #undef DIM
00140 #endif
00141 #define DIM(x) sizeof(x) / sizeof(*x)
00142 
00143 namespace {
00144 
00145   struct EnumConfigEntryItem {
00146     const char * key; // config key value, as appears in config file
00147     const char * desc; // description, to be i18n()ized
00148   };
00149   struct EnumConfigEntry {
00150     const char * group;
00151     const char * key;
00152     const char * desc;
00153     const EnumConfigEntryItem * items;
00154     int numItems;
00155     int defaultItem;
00156   };
00157   struct BoolConfigEntry {
00158     const char * group;
00159     const char * key;
00160     const char * desc;
00161     bool defaultValue;
00162   };
00163 
00164   static const char * lockedDownWarning =
00165     I18N_NOOP("<qt><p>This setting has been fixed by your administrator.</p>"
00166               "<p>If you think this is an error, please contact him.</p></qt>");
00167 
00168   void checkLockDown( QWidget * w, const KConfigGroup & c, const char * key ) {
00169     if ( c.isEntryImmutable( key ) ) {
00170       w->setEnabled( false );
00171       w->setToolTip( i18n( lockedDownWarning ) );
00172     } else {
00173       w->setToolTip("");
00174     }
00175   }
00176 
00177   void populateButtonGroup( QGroupBox * box, QButtonGroup * group, int orientation, const EnumConfigEntry & e ) {
00178     box->setTitle( i18n(e.desc) );
00179     if (orientation == Qt::Horizontal) {
00180       box->setLayout( new QHBoxLayout() );
00181     } else {
00182       box->setLayout( new QVBoxLayout() );
00183     }
00184     box->layout()->setSpacing( KDialog::spacingHint() );
00185     for (int i = 0; i < e.numItems; ++i) {
00186       QRadioButton *button = new QRadioButton( i18n(e.items[i].desc), box );
00187       group->addButton( button, i );
00188       box->layout()->addWidget( button );
00189     }
00190   }
00191 
00192   void populateCheckBox( QCheckBox * b, const BoolConfigEntry & e ) {
00193     b->setText( i18n( e.desc ) );
00194   }
00195 
00196   void loadWidget( QCheckBox * b, const KConfigGroup & c, const BoolConfigEntry & e ) {
00197     Q_ASSERT( c.name() == e.group );
00198     checkLockDown( b, c, e.key );
00199     b->setChecked( c.readEntry( e.key, e.defaultValue ) );
00200   }
00201 
00202   void loadWidget( QGroupBox * box, QButtonGroup * group, const KConfigGroup & c, const EnumConfigEntry & e ) {
00203     Q_ASSERT( c.name() == e.group );
00204     Q_ASSERT( group->buttons().size() == e.numItems );
00205     checkLockDown( box, c, e.key );
00206     const QString s = c.readEntry( e.key, e.items[e.defaultItem].key );
00207     for (int i = 0; i < e.numItems; i++) {
00208       if (s == e.items[i].key) {
00209         group->buttons()[i]->animateClick();
00210         return;
00211       }
00212     }
00213     group->buttons()[e.defaultItem]->animateClick();
00214   }
00215 
00216   void saveCheckBox( QCheckBox * b, KConfigGroup & c, const BoolConfigEntry & e ) {
00217     Q_ASSERT( c.name() == e.group );
00218     c.writeEntry( e.key, b->isChecked() );
00219   }
00220 
00221   void saveButtonGroup( QButtonGroup * group, KConfigGroup & c, const EnumConfigEntry & e ) {
00222     Q_ASSERT( c.name() == e.group );
00223     Q_ASSERT( group->buttons().size() == e.numItems );
00224     if (group->checkedId() != -1) {
00225       c.writeEntry( e.key, e.items[group->checkedId()].key );
00226     }
00227   }
00228 
00229   template <typename T_Widget, typename T_Entry>
00230   inline void loadProfile( T_Widget * g, const KConfigGroup & c, const T_Entry & e ) {
00231     if ( c.hasKey( e.key ) )
00232       loadWidget( g, c, e );
00233   }
00234 
00235   inline void loadProfile( QGroupBox * box, QButtonGroup * group, const KConfigGroup & c, const EnumConfigEntry & e ) {
00236     if (c.hasKey( e.key )) {
00237       loadWidget( box, group, c, e );
00238     }
00239   }
00240 }
00241 
00242 
00243 ConfigureDialog::ConfigureDialog( QWidget *parent, bool modal )
00244   : KCMultiDialog( parent )
00245   , mProfileDialog( 0 )
00246 {
00247   setFaceType( List );
00248   setButtons( Help | Default | Cancel | Apply | Ok | User1 | User2 );
00249   setButtonGuiItem( User1, KStandardGuiItem::reset() );
00250   setButtonGuiItem( User2, KGuiItem( i18n( "&Load Profile..." ) ) );
00251   setModal( modal );
00252   KWindowSystem::setIcons( winId(), qApp->windowIcon().pixmap( IconSize( KIconLoader::Desktop ), IconSize( KIconLoader::Desktop ) ), qApp->windowIcon().pixmap(IconSize( KIconLoader::Small ), IconSize( KIconLoader::Small ) ) );
00253   addModule ( "kmail_config_identity" );
00254   addModule ( "kmail_config_accounts" );
00255   addModule ( "kmail_config_appearance" );
00256   addModule ( "kmail_config_composer" );
00257   addModule ( "kmail_config_security" );
00258   addModule ( "kmail_config_misc" );
00259 
00260   connect( this, SIGNAL(okClicked()), SLOT(slotOk()) );
00261   connect( this, SIGNAL(applyClicked()), SLOT(slotApply()) );
00262   connect( this, SIGNAL(user2Clicked()), SLOT(slotUser2()) );
00263 
00264   // We store the size of the dialog on hide, because otherwise
00265   // the KCMultiDialog starts with the size of the first kcm, not
00266   // the largest one. This way at least after the first showing of
00267   // the largest kcm the size is kept.
00268   KConfigGroup geometry( KMKernel::config(), "Geometry" );
00269   int width = geometry.readEntry( "ConfigureDialogWidth", 0 );
00270   int height = geometry.readEntry( "ConfigureDialogHeight", 0 );
00271   if ( width != 0 && height != 0 ) {
00272      setMinimumSize( width, height );
00273   }
00274 
00275 }
00276 
00277 void ConfigureDialog::hideEvent( QHideEvent *ev ) {
00278   KConfigGroup geometry( KMKernel::config(), "Geometry" );
00279   geometry.writeEntry( "ConfigureDialogWidth", width() );
00280   geometry.writeEntry( "ConfigureDialogHeight",height() );
00281   KDialog::hideEvent( ev );
00282 }
00283 
00284 ConfigureDialog::~ConfigureDialog() {
00285 }
00286 
00287 void ConfigureDialog::slotApply() {
00288   GlobalSettings::self()->writeConfig();
00289 }
00290 
00291 void ConfigureDialog::slotOk() {
00292   GlobalSettings::self()->writeConfig();
00293 }
00294 
00295 void ConfigureDialog::slotUser2() {
00296   if ( mProfileDialog ) {
00297     mProfileDialog->raise();
00298     return;
00299   }
00300   mProfileDialog = new ProfileDialog( this );
00301   mProfileDialog->setObjectName( "mProfileDialog" );
00302   connect( mProfileDialog, SIGNAL(profileSelected(KConfig*)),
00303                 this, SIGNAL(installProfile(KConfig*)) );
00304   mProfileDialog->show();
00305 }
00306 
00307 // *************************************************************
00308 // *                                                           *
00309 // *                      IdentityPage                         *
00310 // *                                                           *
00311 // *************************************************************
00312 QString IdentityPage::helpAnchor() const
00313 {
00314   return QString::fromLatin1( "configure-identity" );
00315 }
00316 
00317 IdentityPage::IdentityPage( const KComponentData &instance, QWidget *parent )
00318   : ConfigModule( instance, parent ),
00319     mIdentityDialog( 0 )
00320 {
00321   QHBoxLayout *hlay = new QHBoxLayout( this );
00322   hlay->setSpacing( KDialog::spacingHint() );
00323   hlay->setMargin( 0 );
00324 
00325   mIdentityList = new IdentityListView( this );
00326   connect( mIdentityList, SIGNAL( itemSelectionChanged() ),
00327            SLOT( slotIdentitySelectionChanged() ) );
00328   connect( this, SIGNAL( changed(bool) ),
00329            SLOT( slotIdentitySelectionChanged() ) );
00330   connect( mIdentityList, SIGNAL( rename( KMail::IdentityListViewItem *, const QString & ) ),
00331            SLOT( slotRenameIdentity(KMail::IdentityListViewItem *, const QString & ) ) );
00332   connect( mIdentityList, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ),
00333            SLOT( slotModifyIdentity() ) );
00334   connect( mIdentityList, SIGNAL( contextMenu( KMail::IdentityListViewItem *, const QPoint & ) ),
00335            SLOT( slotContextMenu( KMail::IdentityListViewItem *, const QPoint & ) ) );
00336   // ### connect dragged(...), ...
00337 
00338   hlay->addWidget( mIdentityList, 1 );
00339 
00340   QVBoxLayout *vlay = new QVBoxLayout(); // inherits spacing
00341   hlay->addLayout( vlay );
00342 
00343   QPushButton *button = new QPushButton( i18n( "&Add..." ), this );
00344   mModifyButton = new QPushButton( i18n( "&Modify..." ), this );
00345   mRenameButton = new QPushButton( i18n( "&Rename" ), this );
00346   mRemoveButton = new QPushButton( i18n( "Remo&ve" ), this );
00347   mSetAsDefaultButton = new QPushButton( i18n( "Set as &Default" ), this );
00348   button->setAutoDefault( false );
00349   mModifyButton->setAutoDefault( false );
00350   mModifyButton->setEnabled( false );
00351   mRenameButton->setAutoDefault( false );
00352   mRenameButton->setEnabled( false );
00353   mRemoveButton->setAutoDefault( false );
00354   mRemoveButton->setEnabled( false );
00355   mSetAsDefaultButton->setAutoDefault( false );
00356   mSetAsDefaultButton->setEnabled( false );
00357   connect( button, SIGNAL( clicked() ),
00358            this, SLOT( slotNewIdentity() ) );
00359   connect( mModifyButton, SIGNAL( clicked() ),
00360            this, SLOT( slotModifyIdentity() ) );
00361   connect( mRenameButton, SIGNAL( clicked() ),
00362            this, SLOT( slotRenameIdentity() ) );
00363   connect( mRemoveButton, SIGNAL( clicked() ),
00364            this, SLOT( slotRemoveIdentity() ) );
00365   connect( mSetAsDefaultButton, SIGNAL( clicked() ),
00366            this, SLOT( slotSetAsDefault() ) );
00367   vlay->addWidget( button );
00368   vlay->addWidget( mModifyButton );
00369   vlay->addWidget( mRenameButton );
00370   vlay->addWidget( mRemoveButton );
00371   vlay->addWidget( mSetAsDefaultButton );
00372   vlay->addStretch( 1 );
00373 }
00374 
00375 void IdentityPage::load()
00376 {
00377   KPIMIdentities::IdentityManager *im = kmkernel->identityManager();
00378   mOldNumberOfIdentities = im->shadowIdentities().count();
00379   // Fill the list:
00380   mIdentityList->clear();
00381   QTreeWidgetItem *item = 0;
00382   for ( KPIMIdentities::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
00383     item = new IdentityListViewItem( mIdentityList, item, *it );
00384   }
00385   if ( mIdentityList->currentItem() ) {
00386     mIdentityList->currentItem()->setSelected( true );
00387   }
00388 }
00389 
00390 void IdentityPage::save()
00391 {
00392   Q_ASSERT( !mIdentityDialog );
00393 
00394   kmkernel->identityManager()->sort();
00395   kmkernel->identityManager()->commit();
00396 
00397   if( mOldNumberOfIdentities < 2 && mIdentityList->topLevelItemCount() > 1 ) {
00398     // have more than one identity, so better show the combo in the
00399     // composer now:
00400     KConfigGroup composer( KMKernel::config(), "Composer" );
00401     int showHeaders = composer.readEntry( "headers", HDR_STANDARD );
00402     showHeaders |= HDR_IDENTITY;
00403     composer.writeEntry( "headers", showHeaders );
00404   }
00405   // and now the reverse
00406   if( mOldNumberOfIdentities > 1 && mIdentityList->topLevelItemCount() < 2 ) {
00407     // have only one identity, so remove the combo in the composer:
00408     KConfigGroup composer( KMKernel::config(), "Composer" );
00409     int showHeaders = composer.readEntry( "headers", HDR_STANDARD );
00410     showHeaders &= ~HDR_IDENTITY;
00411     composer.writeEntry( "headers", showHeaders );
00412   }
00413 }
00414 
00415 void IdentityPage::slotNewIdentity()
00416 {
00417   Q_ASSERT( !mIdentityDialog );
00418 
00419   KPIMIdentities::IdentityManager *im = kmkernel->identityManager();
00420   NewIdentityDialog dialog( im->shadowIdentities(), this );
00421   dialog.setObjectName( "new" );
00422 
00423   if( dialog.exec() == QDialog::Accepted ) {
00424     QString identityName = dialog.identityName().trimmed();
00425     Q_ASSERT( !identityName.isEmpty() );
00426 
00427     //
00428     // Construct a new Identity:
00429     //
00430     switch ( dialog.duplicateMode() ) {
00431     case NewIdentityDialog::ExistingEntry:
00432       {
00433         KPIMIdentities::Identity &dupThis = im->modifyIdentityForName( dialog.duplicateIdentity() );
00434         im->newFromExisting( dupThis, identityName );
00435         break;
00436       }
00437     case NewIdentityDialog::ControlCenter:
00438       im->newFromControlCenter( identityName );
00439       break;
00440     case NewIdentityDialog::Empty:
00441       im->newFromScratch( identityName );
00442     default: ;
00443     }
00444 
00445     //
00446     // Insert into listview:
00447     //
00448     KPIMIdentities::Identity &newIdent = im->modifyIdentityForName( identityName );
00449     QTreeWidgetItem *item = 0;
00450     if ( mIdentityList->selectedItems().size() > 0 ) {
00451       item = mIdentityList->selectedItems()[0];
00452     }
00453 
00454     QTreeWidgetItem * newItem = 0;
00455     if ( item ) {
00456       newItem = new IdentityListViewItem( mIdentityList, mIdentityList->itemAbove( item ), newIdent );
00457     } else {
00458       newItem = new IdentityListViewItem( mIdentityList, newIdent );
00459     }
00460 
00461     mIdentityList->selectionModel()->clearSelection();
00462     if ( newItem ) {
00463       newItem->setSelected( true );
00464     }
00465 
00466     slotModifyIdentity();
00467   }
00468 }
00469 
00470 void IdentityPage::slotModifyIdentity()
00471 {
00472   Q_ASSERT( !mIdentityDialog );
00473 
00474   IdentityListViewItem *item = 0;
00475   if ( mIdentityList->selectedItems().size() > 0 ) {
00476     item = dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItems()[0] );
00477   }
00478   if ( !item ) {
00479     return;
00480   }
00481 
00482   mIdentityDialog = new IdentityDialog( this );
00483   mIdentityDialog->setIdentity( item->identity() );
00484 
00485   // Hmm, an unmodal dialog would be nicer, but a modal one is easier ;-)
00486   if ( mIdentityDialog->exec() == QDialog::Accepted ) {
00487     mIdentityDialog->updateIdentity( item->identity() );
00488     item->redisplay();
00489     emit changed( true );
00490   }
00491 
00492   delete mIdentityDialog;
00493   mIdentityDialog = 0;
00494 }
00495 
00496 void IdentityPage::slotRemoveIdentity()
00497 {
00498   Q_ASSERT( !mIdentityDialog );
00499 
00500   KPIMIdentities::IdentityManager *im = kmkernel->identityManager();
00501   kFatal( im->shadowIdentities().count() < 2, 5006 )
00502     << "Attempted to remove the last identity!";
00503 
00504   IdentityListViewItem *item = 0;
00505   if ( mIdentityList->selectedItems().size() > 0 ) {
00506     item = dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItems()[0] );
00507   }
00508   if ( !item ) {
00509     return;
00510   }
00511 
00512   QString msg = i18n( "<qt>Do you really want to remove the identity named "
00513                       "<b>%1</b>?</qt>", item->identity().identityName() );
00514   if( KMessageBox::warningContinueCancel( this, msg, i18n("Remove Identity"),
00515                                           KGuiItem(i18n("&Remove"),
00516                                           "edit-delete") )
00517       == KMessageBox::Continue ) {
00518     if ( im->removeIdentity( item->identity().identityName() ) ) {
00519       delete item;
00520       if ( mIdentityList->currentItem() ) {
00521         mIdentityList->currentItem()->setSelected( true );
00522       }
00523       refreshList();
00524     }
00525   }
00526 }
00527 
00528 void IdentityPage::slotRenameIdentity()
00529 {
00530   Q_ASSERT( !mIdentityDialog );
00531 
00532   QTreeWidgetItem *item = 0;
00533 
00534   if ( mIdentityList->selectedItems().size() > 0 ) {
00535     item = mIdentityList->selectedItems()[0];
00536   }
00537   if ( !item ) return;
00538 
00539   mIdentityList->editItem( item );
00540 }
00541 
00542 void IdentityPage::slotRenameIdentity( KMail::IdentityListViewItem *item , const QString &text )
00543 {
00544   if ( !item ) return;
00545 
00546   QString newName = text.trimmed();
00547   if ( !newName.isEmpty() &&
00548        !kmkernel->identityManager()->shadowIdentities().contains( newName ) ) {
00549     KPIMIdentities::Identity &ident = item->identity();
00550     ident.setIdentityName( newName );
00551     emit changed( true );
00552   }
00553   item->redisplay();
00554 }
00555 
00556 void IdentityPage::slotContextMenu( IdentityListViewItem *item, const QPoint &pos )
00557 {
00558   QMenu *menu = new QMenu( this );
00559   menu->addAction( i18n( "Add..." ), this, SLOT( slotNewIdentity() ) );
00560   if ( item ) {
00561     menu->addAction( i18n( "Modify..." ), this, SLOT( slotModifyIdentity() ) );
00562     if ( mIdentityList->topLevelItemCount() > 1 ) {
00563       menu->addAction( i18n( "Remove" ), this, SLOT( slotRemoveIdentity() ) );
00564     }
00565     if ( !item->identity().isDefault() ) {
00566       menu->addAction( i18n( "Set as Default" ), this, SLOT( slotSetAsDefault() ) );
00567     }
00568   }
00569   menu->exec( pos );
00570   delete menu;
00571 }
00572 
00573 
00574 void IdentityPage::slotSetAsDefault()
00575 {
00576   Q_ASSERT( !mIdentityDialog );
00577 
00578   IdentityListViewItem *item = 0;
00579   if ( mIdentityList->selectedItems().size() > 0 ) {
00580     item = dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItems()[0] );
00581   }
00582   if ( !item ) {
00583     return;
00584   }
00585 
00586   KPIMIdentities::IdentityManager *im = kmkernel->identityManager();
00587   im->setAsDefault( item->identity().uoid() );
00588   refreshList();
00589 }
00590 
00591 void IdentityPage::refreshList()
00592 {
00593   for ( int i = 0; i < mIdentityList->topLevelItemCount(); ++i ) {
00594     IdentityListViewItem *item = dynamic_cast<IdentityListViewItem*>( mIdentityList->topLevelItem( i ) );
00595     if ( item ) {
00596       item->redisplay();
00597     }
00598   }
00599   emit changed( true );
00600 }
00601 
00602 void IdentityPage::slotIdentitySelectionChanged()
00603 {
00604   IdentityListViewItem *item = 0;
00605   if ( mIdentityList->selectedItems().size() >  0 ) {
00606     item = dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItems()[0] );
00607   }
00608 
00609   mRemoveButton->setEnabled( item && mIdentityList->topLevelItemCount() > 1 );
00610   mModifyButton->setEnabled( item );
00611   mRenameButton->setEnabled( item );
00612   mSetAsDefaultButton->setEnabled( item && !item->identity().isDefault() );
00613 }
00614 
00615 // *************************************************************
00616 // *                                                           *
00617 // *                       AccountsPage                         *
00618 // *                                                           *
00619 // *************************************************************
00620 QString AccountsPage::helpAnchor() const {
00621   return QString::fromLatin1("configure-accounts");
00622 }
00623 
00624 AccountsPage::AccountsPage( const KComponentData &instance, QWidget *parent )
00625   : ConfigModuleWithTabs( instance, parent )
00626 {
00627   //
00628   // "Receiving" tab:
00629   //
00630   mReceivingTab = new ReceivingTab();
00631   addTab( mReceivingTab, i18n( "Receiving" ) );
00632   connect( mReceivingTab, SIGNAL(accountListChanged(const QStringList &)),
00633            this, SIGNAL(accountListChanged(const QStringList &)) );
00634 
00635   //
00636   // "Sending" tab:
00637   //
00638   mSendingTab = new SendingTab();
00639   addTab( mSendingTab, i18n( "Sending" ) );
00640 }
00641 
00642 AccountsPageSendingTab::~AccountsPageSendingTab()
00643 {
00644 }
00645 
00646 QString AccountsPage::SendingTab::helpAnchor() const {
00647   return QString::fromLatin1("configure-accounts-sending");
00648 }
00649 
00650 AccountsPageSendingTab::AccountsPageSendingTab( QWidget * parent )
00651   : ConfigModuleTab( parent )
00652 {
00653   // temp. vars:
00654   QVBoxLayout *vlay;
00655   QGridLayout *glay;
00656   QGroupBox   *group;
00657 
00658   vlay = new QVBoxLayout( this );
00659   vlay->setSpacing( KDialog::spacingHint() );
00660   vlay->setMargin( KDialog::marginHint() );
00661   // label: zero stretch ### FIXME more
00662   vlay->addWidget( new QLabel( i18n("Outgoing accounts (add at least one):"), this ) );
00663 
00664   TransportManagementWidget *tmw = new TransportManagementWidget( this );
00665   vlay->addWidget( tmw );
00666 
00667   // "Common options" groupbox:
00668   group = new QGroupBox( i18n("Common Options"), this );
00669   vlay->addWidget(group);
00670 
00671   // a grid layout for the contents of the "common options" group box
00672   glay = new QGridLayout();
00673   group->setLayout( glay );
00674   glay->setSpacing( KDialog::spacingHint() );
00675   glay->setColumnStretch( 2, 10 );
00676 
00677   // "confirm before send" check box:
00678   mConfirmSendCheck = new QCheckBox( i18n("Confirm &before send"), group );
00679   glay->addWidget( mConfirmSendCheck, 0, 0, 1, 2 );
00680   connect( mConfirmSendCheck, SIGNAL( stateChanged( int ) ),
00681            this, SLOT( slotEmitChanged( void ) ) );
00682 
00683   // "send on check" combo:
00684   mSendOnCheckCombo = new KComboBox( group );
00685   mSendOnCheckCombo->setEditable( false );
00686   mSendOnCheckCombo->addItems( QStringList()
00687                                       << i18n("Never Automatically")
00688                                       << i18n("On Manual Mail Checks")
00689                                       << i18n("On All Mail Checks") );
00690   glay->addWidget( mSendOnCheckCombo, 1, 1 );
00691   connect( mSendOnCheckCombo, SIGNAL( activated( int ) ),
00692            this, SLOT( slotEmitChanged( void ) ) );
00693 
00694   // "default send method" combo:
00695   mSendMethodCombo = new KComboBox( group );
00696   mSendMethodCombo->setEditable( false );
00697   mSendMethodCombo->addItems( QStringList()
00698                                       << i18n("Send Now")
00699                                       << i18n("Send Later") );
00700   glay->addWidget( mSendMethodCombo, 2, 1 );
00701   connect( mSendMethodCombo, SIGNAL( activated( int ) ),
00702            this, SLOT( slotEmitChanged( void ) ) );
00703 
00704 
00705   // "message property" combo:
00706   // ### FIXME: remove completely?
00707   mMessagePropertyCombo = new KComboBox( group );
00708   mMessagePropertyCombo->setEditable( false );
00709   mMessagePropertyCombo->addItems( QStringList()
00710                      << i18n("Allow 8-bit")
00711                      << i18n("MIME Compliant (Quoted Printable)") );
00712   glay->addWidget( mMessagePropertyCombo, 3, 1 );
00713   connect( mMessagePropertyCombo, SIGNAL( activated( int ) ),
00714            this, SLOT( slotEmitChanged( void ) ) );
00715 
00716   // "default domain" input field:
00717   mDefaultDomainEdit = new KLineEdit( group );
00718   glay->addWidget( mDefaultDomainEdit, 4, 1, 1, 2 );
00719   connect( mDefaultDomainEdit, SIGNAL( textChanged( const QString& ) ),
00720            this, SLOT( slotEmitChanged( void ) ) );
00721 
00722   // labels:
00723   QLabel *l =  new QLabel( i18n("Send &messages in outbox folder:"), group );
00724   l->setBuddy( mSendOnCheckCombo );
00725   glay->addWidget( l, 1, 0 );
00726 
00727   QString msg = i18n( GlobalSettings::self()->sendOnCheckItem()->whatsThis().toUtf8() );
00728   l->setWhatsThis( msg );
00729   mSendOnCheckCombo->setWhatsThis( msg );
00730 
00731   l = new QLabel( i18n("Defa&ult send method:"), group );
00732   l->setBuddy( mSendMethodCombo );
00733   glay->addWidget( l, 2, 0 );
00734   l = new QLabel( i18n("Message &property:"), group );
00735   l->setBuddy( mMessagePropertyCombo );
00736   glay->addWidget( l, 3, 0 );
00737   l = new QLabel( i18n("Defaul&t domain:"), group );
00738   l->setBuddy( mDefaultDomainEdit );
00739   glay->addWidget( l, 4, 0 );
00740 
00741   // and now: add QWhatsThis:
00742   msg = i18n( "<qt><p>The default domain is used to complete email "
00743               "addresses that only consist of the user's name."
00744               "</p></qt>" );
00745   l->setWhatsThis( msg );
00746   mDefaultDomainEdit->setWhatsThis( msg );
00747 }
00748 
00749 void AccountsPage::SendingTab::doLoadFromGlobalSettings() {
00750   mSendOnCheckCombo->setCurrentIndex( GlobalSettings::self()->sendOnCheck() );
00751 }
00752 
00753 void AccountsPage::SendingTab::doLoadOther() {
00754   KConfigGroup general( KMKernel::config(), "General");
00755   KConfigGroup composer( KMKernel::config(), "Composer");
00756 
00757   mSendMethodCombo->setCurrentIndex(
00758                 kmkernel->msgSender()->sendImmediate() ? 0 : 1 );
00759   mMessagePropertyCombo->setCurrentIndex(
00760                 kmkernel->msgSender()->sendQuotedPrintable() ? 1 : 0 );
00761 
00762   mConfirmSendCheck->setChecked(
00763       composer.readEntry( "confirm-before-send", false ) );
00764   QString str = general.readEntry( "Default domain" );
00765   if( str.isEmpty() ) {
00766     str = QHostInfo::localHostName();
00767   }
00768   mDefaultDomainEdit->setText( str );
00769 }
00770 
00771 void AccountsPage::SendingTab::save() {
00772   KConfigGroup general( KMKernel::config(), "General" );
00773   KConfigGroup composer( KMKernel::config(), "Composer" );
00774 
00775   // Save common options:
00776   GlobalSettings::self()->setSendOnCheck( mSendOnCheckCombo->currentIndex() );
00777   kmkernel->msgSender()->setSendImmediate(
00778                              mSendMethodCombo->currentIndex() == 0 );
00779   kmkernel->msgSender()->setSendQuotedPrintable(
00780                              mMessagePropertyCombo->currentIndex() == 1 );
00781   kmkernel->msgSender()->writeConfig( false ); // don't sync
00782   composer.writeEntry("confirm-before-send", mConfirmSendCheck->isChecked() );
00783   general.writeEntry( "Default domain", mDefaultDomainEdit->text() );
00784 }
00785 
00786 QString AccountsPage::ReceivingTab::helpAnchor() const {
00787   return QString::fromLatin1("configure-accounts-receiving");
00788 }
00789 
00790 AccountsPageReceivingTab::AccountsPageReceivingTab( QWidget * parent )
00791   : ConfigModuleTab( parent )
00792 {
00793   // temp. vars:
00794   QVBoxLayout *vlay;
00795   QVBoxLayout *btn_vlay;
00796   QHBoxLayout *hlay;
00797   QPushButton *button;
00798   QGroupBox   *group;
00799 
00800   vlay = new QVBoxLayout( this );
00801   vlay->setSpacing( KDialog::spacingHint() );
00802   vlay->setMargin( KDialog::marginHint() );
00803 
00804   // label: zero stretch
00805   vlay->addWidget( new QLabel( i18n("Incoming accounts (add at least one):"), this ) );
00806 
00807   // hbox layout: stretch 10, spacing inherited from vlay
00808   hlay = new QHBoxLayout();
00809   vlay->addLayout( hlay, 10 ); // high stretch to suppress groupbox's growing
00810 
00811   // account list: left widget in hlay; stretch 1
00812   mAccountList = new ListView( this );
00813   mAccountList->setObjectName( "accountList" );
00814   mAccountList->setHeaderLabels( QStringList() << "Name" << "Type" << "Folder" );
00815   mAccountList->setSortingEnabled( false );
00816 
00817   connect( mAccountList->selectionModel(),
00818            SIGNAL(
00819              selectionChanged( const QItemSelection &, const QItemSelection &)
00820            ),
00821            this,
00822            SLOT( slotAccountSelected() )
00823          );
00824   connect( mAccountList, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ),
00825            this, SLOT( slotModifySelectedAccount() ) );
00826   hlay->addWidget( mAccountList, 1 );
00827 
00828   // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
00829   btn_vlay = new QVBoxLayout();
00830   hlay->addLayout( btn_vlay );
00831 
00832   // "add..." button: stretch 0
00833   button = new QPushButton( i18n("A&dd..."), this );
00834   button->setAutoDefault( false );
00835   connect( button, SIGNAL(clicked()),
00836            this, SLOT(slotAddAccount()) );
00837   btn_vlay->addWidget( button );
00838 
00839   // "modify..." button: stretch 0
00840   mModifyAccountButton = new QPushButton( i18n("&Modify..."), this );
00841   mModifyAccountButton->setAutoDefault( false );
00842   mModifyAccountButton->setEnabled( false ); // b/c no item is selected yet
00843   connect( mModifyAccountButton, SIGNAL(clicked()),
00844            this, SLOT(slotModifySelectedAccount()) );
00845   btn_vlay->addWidget( mModifyAccountButton );
00846 
00847   // "remove..." button: stretch 0
00848   mRemoveAccountButton = new QPushButton( i18n("R&emove"), this );
00849   mRemoveAccountButton->setAutoDefault( false );
00850   mRemoveAccountButton->setEnabled( false ); // b/c no item is selected yet
00851   connect( mRemoveAccountButton, SIGNAL(clicked()),
00852            this, SLOT(slotRemoveSelectedAccount()) );
00853   btn_vlay->addWidget( mRemoveAccountButton );
00854   btn_vlay->addStretch( 1 ); // spacer
00855 
00856   mCheckmailStartupCheck = new QCheckBox( i18n("Chec&k mail on startup"), this );
00857   vlay->addWidget( mCheckmailStartupCheck );
00858   connect( mCheckmailStartupCheck, SIGNAL( stateChanged( int ) ),
00859            this, SLOT( slotEmitChanged( void ) ) );
00860 
00861   // "New Mail Notification" group box: stretch 0
00862   group = new QGroupBox( i18n( "New Mail Notification" ), this );
00863   vlay->addWidget( group );
00864 
00865   group->setLayout( new QVBoxLayout );
00866   group->layout()->setMargin( KDialog::marginHint() );
00867   group->layout()->setSpacing( KDialog::spacingHint() );
00868 
00869   // "beep on new mail" check box:
00870   mBeepNewMailCheck = new QCheckBox(i18n("&Beep"), group );
00871   mBeepNewMailCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
00872                                                  QSizePolicy::Fixed ) );
00873   connect( mBeepNewMailCheck, SIGNAL( stateChanged( int ) ),
00874            this, SLOT( slotEmitChanged( void ) ) );
00875 
00876   // "Detailed new mail notification" check box
00877   mVerboseNotificationCheck =
00878     new QCheckBox( i18n( "Deta&iled new mail notification" ), group );
00879   mVerboseNotificationCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
00880                                                          QSizePolicy::Fixed ) );
00881   mVerboseNotificationCheck->setToolTip(
00882                  i18n( "Show for each folder the number of newly arrived "
00883                        "messages" ) );
00884   mVerboseNotificationCheck->setWhatsThis(
00885     GlobalSettings::self()->verboseNewMailNotificationItem()->whatsThis() );
00886   connect( mVerboseNotificationCheck, SIGNAL( stateChanged( int ) ),
00887            this, SLOT( slotEmitChanged() ) );
00888 
00889   // "Other Actions" button:
00890   mOtherNewMailActionsButton = new QPushButton( i18n("Other Actio&ns"), group );
00891   mOtherNewMailActionsButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed,
00892                                                           QSizePolicy::Fixed ) );
00893   connect( mOtherNewMailActionsButton, SIGNAL(clicked()),
00894            this, SLOT(slotEditNotifications()) );
00895 
00896   group->layout()->addWidget( mBeepNewMailCheck );
00897   group->layout()->addWidget( mVerboseNotificationCheck );
00898   group->layout()->addWidget( mOtherNewMailActionsButton );
00899 }
00900 
00901 AccountsPageReceivingTab::~AccountsPageReceivingTab()
00902 {
00903   // When hitting Cancel or closing the dialog with the window-manager-button,
00904   // we have a number of things to clean up:
00905 
00906   // The newly created accounts
00907   QList< QPointer<KMAccount> >::Iterator it;
00908   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
00909     delete (*it);
00910   }
00911   mNewAccounts.clear();
00912 
00913   // The modified accounts
00914   QList<ModifiedAccountsType*>::Iterator j;
00915   for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
00916     delete (*j)->newAccount;
00917     delete (*j);
00918   }
00919   mModifiedAccounts.clear();
00920 
00921 
00922 }
00923 
00924 void AccountsPage::ReceivingTab::slotAccountSelected()
00925 {
00926   QTreeWidgetItem *item = mAccountList->currentItem();
00927   mModifyAccountButton->setEnabled( item );
00928   mRemoveAccountButton->setEnabled( item );
00929 }
00930 
00931 QStringList AccountsPage::ReceivingTab::occupiedNames()
00932 {
00933   QStringList accountNames = kmkernel->acctMgr()->getAccounts();
00934 
00935   QList<ModifiedAccountsType*>::Iterator k;
00936   for (k = mModifiedAccounts.begin(); k != mModifiedAccounts.end(); ++k )
00937     if ((*k)->oldAccount)
00938       accountNames.removeAll( (*k)->oldAccount->name() );
00939 
00940   QList< QPointer<KMAccount> >::Iterator l;
00941   for (l = mAccountsToDelete.begin(); l != mAccountsToDelete.end(); ++l )
00942     if (*l)
00943       accountNames.removeAll( (*l)->name() );
00944 
00945   QList< QPointer<KMAccount> >::Iterator it;
00946   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it )
00947     if (*it)
00948       accountNames += (*it)->name();
00949 
00950   QList<ModifiedAccountsType*>::Iterator j;
00951   for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
00952     accountNames += (*j)->newAccount->name();
00953 
00954   return accountNames;
00955 }
00956 
00957 void AccountsPage::ReceivingTab::slotAddAccount() {
00958   KMAcctSelDlg accountSelectorDialog( this );
00959   if( accountSelectorDialog.exec() != QDialog::Accepted ) return;
00960 
00961   KAccount::Type accountType = accountSelectorDialog.selected();
00962   KMAccount *account = kmkernel->acctMgr()->create( accountType );
00963   if ( !account ) {
00964     // ### FIXME: Give the user more information. Is this error
00965     // recoverable?
00966     KMessageBox::sorry( this, i18n("Unable to create account") );
00967     return;
00968   }
00969 
00970   account->init(); // fill the account fields with good default values
00971 
00972   AccountDialog dialog( i18n("Add Account"), account, this );
00973 
00974   if( dialog.exec() != QDialog::Accepted ) {
00975     delete account;
00976     return;
00977   }
00978 
00979   account->deinstallTimer();
00980   account->setName( kmkernel->acctMgr()->makeUnique( account->name() ) );
00981 
00982   QTreeWidgetItem *after = mAccountList->topLevelItemCount() > 0 ?
00983       mAccountList->topLevelItem( mAccountList->topLevelItemCount() - 1 ) :
00984       0;
00985 
00986   QTreeWidgetItem *listItem = new QTreeWidgetItem( mAccountList, after );
00987   listItem->setText( 0, account->name() );
00988   listItem->setText( 1, KAccount::displayNameForType( account->type() ) );
00989   if( account->folder() )
00990     listItem->setText( 2, account->folder()->label() );
00991 
00992   mNewAccounts.append( account );
00993   emit changed( true );
00994 }
00995 
00996 
00997 
00998 void AccountsPage::ReceivingTab::slotModifySelectedAccount()
00999 {
01000   QTreeWidgetItem *listItem = mAccountList->currentItem();
01001   if( !listItem ) return;
01002 
01003   KMAccount *account = 0;
01004   QList<ModifiedAccountsType*>::Iterator j;
01005   for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
01006     if ( (*j)->newAccount->name() == listItem->text( 0 ) ) {
01007       account = (*j)->newAccount;
01008       break;
01009     }
01010 
01011   if ( !account ) {
01012     QList< QPointer<KMAccount> >::Iterator it;
01013     for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
01014       if ( (*it)->name() == listItem->text( 0 ) ) {
01015         account = *it;
01016         break;
01017       }
01018 
01019     if ( !account ) {
01020       account = kmkernel->acctMgr()->findByName( listItem->text( 0 ) );
01021       if( !account ) {
01022         // ### FIXME: How should this happen? See above.
01023         KMessageBox::sorry( this, i18n("Unable to locate account") );
01024         return;
01025       }
01026       if ( account->type() == KAccount::Imap ||
01027            account->type() == KAccount::DImap )
01028       {
01029         ImapAccountBase* ai = static_cast<ImapAccountBase*>( account );
01030         if ( ai->namespaces().isEmpty() || ai->namespaceToDelimiter().isEmpty() )
01031         {
01032           // connect to server - the namespaces are fetched automatically
01033           kDebug(5006) <<"slotModifySelectedAccount - connect";
01034           ai->makeConnection();
01035         }
01036       }
01037 
01038       ModifiedAccountsType *mod = new ModifiedAccountsType;
01039       mod->oldAccount = account;
01040       mod->newAccount = kmkernel->acctMgr()->create( account->type(),
01041                                                    account->name() );
01042       mod->newAccount->pseudoAssign( account );
01043       mModifiedAccounts.append( mod );
01044       account = mod->newAccount;
01045     }
01046   }
01047 
01048   QStringList accountNames = occupiedNames();
01049   accountNames.removeAll( account->name() );
01050 
01051   AccountDialog dialog( i18n("Modify Account"), account, this );
01052 
01053   if( dialog.exec() != QDialog::Accepted ) return;
01054 
01055   if ( accountNames.contains( account->name() ) )
01056     account->setName(