kmail

configuredialog.cpp

00001 /*   -*- mode: C++; c-file-style: "gnu" -*-
00002  *   kmail: KDE mail client
00003  *   This file: 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
00018  *   along with this program; if not, write to the Free Software
00019  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // This must be first
00024 #include <config.h>
00025 
00026 // my headers:
00027 #include "configuredialog.h"
00028 #include "configuredialog_p.h"
00029 
00030 #include "globalsettings.h"
00031 #include "replyphrases.h"
00032 #include "templatesconfiguration_kfg.h"
00033 
00034 // other KMail headers:
00035 #include "kmkernel.h"
00036 #include "simplestringlisteditor.h"
00037 #include "accountdialog.h"
00038 using KMail::AccountDialog;
00039 #include "colorlistbox.h"
00040 #include "kmacctseldlg.h"
00041 #include "messagesender.h"
00042 #include "kmtransport.h"
00043 #include "kmfoldermgr.h"
00044 #include <libkpimidentities/identitymanager.h>
00045 #include "identitylistview.h"
00046 using KMail::IdentityListView;
00047 using KMail::IdentityListViewItem;
00048 #include "kcursorsaver.h"
00049 #include "accountmanager.h"
00050 #include <composercryptoconfiguration.h>
00051 #include <warningconfiguration.h>
00052 #include <smimeconfiguration.h>
00053 #include "templatesconfiguration.h"
00054 #include "customtemplates.h"
00055 #include "folderrequester.h"
00056 using KMail::FolderRequester;
00057 #include "accountcombobox.h"
00058 #include "imapaccountbase.h"
00059 using KMail::ImapAccountBase;
00060 #include "folderstorage.h"
00061 #include "kmfolder.h"
00062 #include "kmmainwidget.h"
00063 #include "recentaddresses.h"
00064 using KRecentAddress::RecentAddresses;
00065 #include "completionordereditor.h"
00066 #include "ldapclient.h"
00067 #include "index.h"
00068 
00069 using KMail::IdentityListView;
00070 using KMail::IdentityListViewItem;
00071 #include "identitydialog.h"
00072 using KMail::IdentityDialog;
00073 
00074 // other kdenetwork headers:
00075 #include <libkpimidentities/identity.h>
00076 #include <kmime_util.h>
00077 using KMime::DateFormatter;
00078 #include <kleo/cryptoconfig.h>
00079 #include <kleo/cryptobackendfactory.h>
00080 #include <ui/backendconfigwidget.h>
00081 #include <ui/keyrequester.h>
00082 #include <ui/keyselectiondialog.h>
00083 
00084 // other KDE headers:
00085 #include <klocale.h>
00086 #include <kapplication.h>
00087 #include <kcharsets.h>
00088 #include <kasciistringtools.h>
00089 #include <kdebug.h>
00090 #include <knuminput.h>
00091 #include <kfontdialog.h>
00092 #include <kmessagebox.h>
00093 #include <kurlrequester.h>
00094 #include <kseparator.h>
00095 #include <kiconloader.h>
00096 #include <kstandarddirs.h>
00097 #include <kwin.h>
00098 #include <knotifydialog.h>
00099 #include <kconfig.h>
00100 #include <kactivelabel.h>
00101 #include <kcmultidialog.h>
00102 #include <kcombobox.h>
00103 
00104 // Qt headers:
00105 #include <tqvalidator.h>
00106 #include <tqwhatsthis.h>
00107 #include <tqvgroupbox.h>
00108 #include <tqvbox.h>
00109 #include <tqvbuttongroup.h>
00110 #include <tqhbuttongroup.h>
00111 #include <tqtooltip.h>
00112 #include <tqlabel.h>
00113 #include <tqtextcodec.h>
00114 #include <tqheader.h>
00115 #include <tqpopupmenu.h>
00116 #include <tqradiobutton.h>
00117 #include <tqlayout.h>
00118 #include <tqcheckbox.h>
00119 #include <tqwidgetstack.h>
00120 
00121 // other headers:
00122 #include <assert.h>
00123 #include <stdlib.h>
00124 
00125 #ifndef _PATH_SENDMAIL
00126 #define _PATH_SENDMAIL  "/usr/sbin/sendmail"
00127 #endif
00128 
00129 #ifdef DIM
00130 #undef DIM
00131 #endif
00132 #define DIM(x) sizeof(x) / sizeof(*x)
00133 
00134 namespace {
00135 
00136   struct EnumConfigEntryItem {
00137     const char * key; // config key value, as appears in config file
00138     const char * desc; // description, to be i18n()ized
00139   };
00140   struct EnumConfigEntry {
00141     const char * group;
00142     const char * key;
00143     const char * desc;
00144     const EnumConfigEntryItem * items;
00145     int numItems;
00146     int defaultItem;
00147   };
00148   struct BoolConfigEntry {
00149     const char * group;
00150     const char * key;
00151     const char * desc;
00152     bool defaultValue;
00153   };
00154 
00155   static const char * lockedDownWarning =
00156     I18N_NOOP("<qt><p>This setting has been fixed by your administrator.</p>"
00157               "<p>If you think this is an error, please contact him.</p></qt>");
00158 
00159   void checkLockDown( TQWidget * w, const KConfigBase & c, const char * key ) {
00160     if ( c.entryIsImmutable( key ) ) {
00161       w->setEnabled( false );
00162       TQToolTip::add( w, i18n( lockedDownWarning ) );
00163     } else {
00164       TQToolTip::remove( w );
00165     }
00166   }
00167 
00168   void populateButtonGroup( TQButtonGroup * g, const EnumConfigEntry & e ) {
00169     g->setTitle( i18n( e.desc ) );
00170     g->layout()->setSpacing( KDialog::spacingHint() );
00171     for ( int i = 0 ; i < e.numItems ; ++i )
00172       g->insert( new TQRadioButton( i18n( e.items[i].desc ), g ), i );
00173   }
00174 
00175   void populateCheckBox( TQCheckBox * b, const BoolConfigEntry & e ) {
00176     b->setText( i18n( e.desc ) );
00177   }
00178 
00179   void loadWidget( TQCheckBox * b, const KConfigBase & c, const BoolConfigEntry & e ) {
00180     Q_ASSERT( c.group() == e.group );
00181     checkLockDown( b, c, e.key );
00182     b->setChecked( c.readBoolEntry( e.key, e.defaultValue ) );
00183   }
00184 
00185   void loadWidget( TQButtonGroup * g, const KConfigBase & c, const EnumConfigEntry & e ) {
00186     Q_ASSERT( c.group() == e.group );
00187     Q_ASSERT( g->count() == e.numItems );
00188     checkLockDown( g, c, e.key );
00189     const TQString s = c.readEntry( e.key, e.items[e.defaultItem].key );
00190     for ( int i = 0 ; i < e.numItems ; ++i )
00191       if ( s == e.items[i].key ) {
00192         g->setButton( i );
00193         return;
00194       }
00195     g->setButton( e.defaultItem );
00196   }
00197 
00198   void saveCheckBox( TQCheckBox * b, KConfigBase & c, const BoolConfigEntry & e ) {
00199     Q_ASSERT( c.group() == e.group );
00200     c.writeEntry( e.key, b->isChecked() );
00201   }
00202 
00203   void saveButtonGroup( TQButtonGroup * g, KConfigBase & c, const EnumConfigEntry & e ) {
00204     Q_ASSERT( c.group() == e.group );
00205     Q_ASSERT( g->count() == e.numItems );
00206     c.writeEntry( e.key, e.items[ g->id( g->selected() ) ].key );
00207   }
00208 
00209   template <typename T_Widget, typename T_Entry>
00210   inline void loadProfile( T_Widget * g, const KConfigBase & c, const T_Entry & e ) {
00211     if ( c.hasKey( e.key ) )
00212       loadWidget( g, c, e );
00213   }
00214 }
00215 
00216 
00217 ConfigureDialog::ConfigureDialog( TQWidget *parent, const char *name, bool modal )
00218   : KCMultiDialog( KDialogBase::IconList, KGuiItem( i18n( "&Load Profile..." ) ),
00219                    KGuiItem(), User2, i18n( "Configure" ), parent, name, modal )
00220   , mProfileDialog( 0 )
00221 {
00222   KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
00223   showButton( User1, true );
00224 
00225   addModule ( "kmail_config_identity", false );
00226   addModule ( "kmail_config_accounts", false );
00227   addModule ( "kmail_config_appearance", false );
00228   addModule ( "kmail_config_composer", false );
00229   addModule ( "kmail_config_security", false );
00230   addModule ( "kmail_config_misc", false );
00231 
00232   // We store the size of the dialog on hide, because otherwise
00233   // the KCMultiDialog starts with the size of the first kcm, not
00234   // the largest one. This way at least after the first showing of
00235   // the largest kcm the size is kept.
00236   KConfigGroup geometry( KMKernel::config(), "Geometry" );
00237   int width = geometry.readNumEntry( "ConfigureDialogWidth" );
00238   int height = geometry.readNumEntry( "ConfigureDialogHeight" );
00239   if ( width != 0 && height != 0 ) {
00240      setMinimumSize( width, height );
00241   }
00242 
00243 }
00244 
00245 void ConfigureDialog::hideEvent( TQHideEvent *ev ) {
00246   KConfigGroup geometry( KMKernel::config(), "Geometry" );
00247   geometry.writeEntry( "ConfigureDialogWidth", width() );
00248   geometry.writeEntry( "ConfigureDialogHeight",height() );
00249   KDialogBase::hideEvent( ev );
00250 }
00251 
00252 ConfigureDialog::~ConfigureDialog() {
00253 }
00254 
00255 void ConfigureDialog::slotApply() {
00256   KCMultiDialog::slotApply();
00257   GlobalSettings::self()->writeConfig();
00258   emit configChanged();
00259 }
00260 
00261 void ConfigureDialog::slotOk() {
00262   KCMultiDialog::slotOk();
00263   GlobalSettings::self()->writeConfig();
00264   emit configChanged();
00265 }
00266 
00267 void ConfigureDialog::slotUser2() {
00268   if ( mProfileDialog ) {
00269     mProfileDialog->raise();
00270     return;
00271   }
00272   mProfileDialog = new ProfileDialog( this, "mProfileDialog" );
00273   connect( mProfileDialog, TQT_SIGNAL(profileSelected(KConfig*)),
00274                 this, TQT_SIGNAL(installProfile(KConfig*)) );
00275   mProfileDialog->show();
00276 }
00277 
00278 // *************************************************************
00279 // *                                                           *
00280 // *                      IdentityPage                         *
00281 // *                                                           *
00282 // *************************************************************
00283 TQString IdentityPage::helpAnchor() const {
00284   return TQString::fromLatin1("configure-identity");
00285 }
00286 
00287 IdentityPage::IdentityPage( TQWidget * parent, const char * name )
00288   : ConfigModule( parent, name ),
00289     mIdentityDialog( 0 )
00290 {
00291   TQHBoxLayout * hlay = new TQHBoxLayout( this, 0, KDialog::spacingHint() );
00292 
00293   mIdentityList = new IdentityListView( this );
00294   connect( mIdentityList, TQT_SIGNAL(selectionChanged()),
00295            TQT_SLOT(slotIdentitySelectionChanged()) );
00296   connect( mIdentityList, TQT_SIGNAL(itemRenamed(TQListViewItem*,const TQString&,int)),
00297            TQT_SLOT(slotRenameIdentity(TQListViewItem*,const TQString&,int)) );
00298   connect( mIdentityList, TQT_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&,int)),
00299            TQT_SLOT(slotModifyIdentity()) );
00300   connect( mIdentityList, TQT_SIGNAL(contextMenu(KListView*,TQListViewItem*,const TQPoint&)),
00301            TQT_SLOT(slotContextMenu(KListView*,TQListViewItem*,const TQPoint&)) );
00302   // ### connect dragged(...), ...
00303 
00304   hlay->addWidget( mIdentityList, 1 );
00305 
00306   TQVBoxLayout * vlay = new TQVBoxLayout( hlay ); // inherits spacing
00307 
00308   TQPushButton * button = new TQPushButton( i18n("&Add..."), this );
00309   mModifyButton = new TQPushButton( i18n("&Modify..."), this );
00310   mRenameButton = new TQPushButton( i18n("&Rename"), this );
00311   mRemoveButton = new TQPushButton( i18n("Remo&ve"), this );
00312   mSetAsDefaultButton = new TQPushButton( i18n("Set as &Default"), this );
00313   button->setAutoDefault( false );
00314   mModifyButton->setAutoDefault( false );
00315   mModifyButton->setEnabled( false );
00316   mRenameButton->setAutoDefault( false );
00317   mRenameButton->setEnabled( false );
00318   mRemoveButton->setAutoDefault( false );
00319   mRemoveButton->setEnabled( false );
00320   mSetAsDefaultButton->setAutoDefault( false );
00321   mSetAsDefaultButton->setEnabled( false );
00322   connect( button, TQT_SIGNAL(clicked()),
00323            this, TQT_SLOT(slotNewIdentity()) );
00324   connect( mModifyButton, TQT_SIGNAL(clicked()),
00325            this, TQT_SLOT(slotModifyIdentity()) );
00326   connect( mRenameButton, TQT_SIGNAL(clicked()),
00327            this, TQT_SLOT(slotRenameIdentity()) );
00328   connect( mRemoveButton, TQT_SIGNAL(clicked()),
00329            this, TQT_SLOT(slotRemoveIdentity()) );
00330   connect( mSetAsDefaultButton, TQT_SIGNAL(clicked()),
00331            this, TQT_SLOT(slotSetAsDefault()) );
00332   vlay->addWidget( button );
00333   vlay->addWidget( mModifyButton );
00334   vlay->addWidget( mRenameButton );
00335   vlay->addWidget( mRemoveButton );
00336   vlay->addWidget( mSetAsDefaultButton );
00337   vlay->addStretch( 1 );
00338   load();
00339 }
00340 
00341 void IdentityPage::load()
00342 {
00343   KPIM::IdentityManager * im = kmkernel->identityManager();
00344   mOldNumberOfIdentities = im->shadowIdentities().count();
00345   // Fill the list:
00346   mIdentityList->clear();
00347   TQListViewItem * item = 0;
00348   for ( KPIM::IdentityManager::Iterator it = im->modifyBegin() ; it != im->modifyEnd() ; ++it )
00349     item = new IdentityListViewItem( mIdentityList, item, *it  );
00350   mIdentityList->setSelected( mIdentityList->currentItem(), true );
00351 }
00352 
00353 void IdentityPage::save() {
00354   assert( !mIdentityDialog );
00355 
00356   kmkernel->identityManager()->sort();
00357   kmkernel->identityManager()->commit();
00358 
00359   if( mOldNumberOfIdentities < 2 && mIdentityList->childCount() > 1 ) {
00360     // have more than one identity, so better show the combo in the
00361     // composer now:
00362     KConfigGroup composer( KMKernel::config(), "Composer" );
00363     int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
00364     showHeaders |= HDR_IDENTITY;
00365     composer.writeEntry( "headers", showHeaders );
00366   }
00367   // and now the reverse
00368   if( mOldNumberOfIdentities > 1 && mIdentityList->childCount() < 2 ) {
00369     // have only one identity, so remove the combo in the composer:
00370     KConfigGroup composer( KMKernel::config(), "Composer" );
00371     int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
00372     showHeaders &= ~HDR_IDENTITY;
00373     composer.writeEntry( "headers", showHeaders );
00374   }
00375 }
00376 
00377 void IdentityPage::slotNewIdentity()
00378 {
00379   assert( !mIdentityDialog );
00380 
00381   KPIM::IdentityManager * im = kmkernel->identityManager();
00382   NewIdentityDialog dialog( im->shadowIdentities(), this, "new", true );
00383 
00384   if( dialog.exec() == TQDialog::Accepted ) {
00385     TQString identityName = dialog.identityName().stripWhiteSpace();
00386     assert( !identityName.isEmpty() );
00387 
00388     //
00389     // Construct a new Identity:
00390     //
00391     switch ( dialog.duplicateMode() ) {
00392     case NewIdentityDialog::ExistingEntry:
00393       {
00394         KPIM::Identity & dupThis = im->modifyIdentityForName( dialog.duplicateIdentity() );
00395         im->newFromExisting( dupThis, identityName );
00396         break;
00397       }
00398     case NewIdentityDialog::ControlCenter:
00399       im->newFromControlCenter( identityName );
00400       break;
00401     case NewIdentityDialog::Empty:
00402       im->newFromScratch( identityName );
00403     default: ;
00404     }
00405 
00406     //
00407     // Insert into listview:
00408     //
00409     KPIM::Identity & newIdent = im->modifyIdentityForName( identityName );
00410     TQListViewItem * item = mIdentityList->selectedItem();
00411     if ( item )
00412       item = item->itemAbove();
00413     mIdentityList->setSelected( new IdentityListViewItem( mIdentityList,
00414                                                           /*after*/ item,
00415                                                           newIdent ), true );
00416     slotModifyIdentity();
00417   }
00418 }
00419 
00420 void IdentityPage::slotModifyIdentity() {
00421   assert( !mIdentityDialog );
00422 
00423   IdentityListViewItem * item =
00424     dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
00425   if ( !item ) return;
00426 
00427   mIdentityDialog = new IdentityDialog( this );
00428   mIdentityDialog->setIdentity( item->identity() );
00429 
00430   // Hmm, an unmodal dialog would be nicer, but a modal one is easier ;-)
00431   if ( mIdentityDialog->exec() == TQDialog::Accepted ) {
00432     mIdentityDialog->updateIdentity( item->identity() );
00433     item->redisplay();
00434     emit changed(true);
00435   }
00436 
00437   delete mIdentityDialog;
00438   mIdentityDialog = 0;
00439 }
00440 
00441 void IdentityPage::slotRemoveIdentity()
00442 {
00443   assert( !mIdentityDialog );
00444 
00445   KPIM::IdentityManager * im = kmkernel->identityManager();
00446   kdFatal( im->shadowIdentities().count() < 2 )
00447     << "Attempted to remove the last identity!" << endl;
00448 
00449   IdentityListViewItem * item =
00450     dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
00451   if ( !item ) return;
00452 
00453   TQString msg = i18n("<qt>Do you really want to remove the identity named "
00454                      "<b>%1</b>?</qt>").arg( item->identity().identityName() );
00455   if( KMessageBox::warningContinueCancel( this, msg, i18n("Remove Identity"),
00456    KGuiItem(i18n("&Remove"),"editdelete") ) == KMessageBox::Continue )
00457     if ( im->removeIdentity( item->identity().identityName() ) ) {
00458       delete item;
00459       mIdentityList->setSelected( mIdentityList->currentItem(), true );
00460       refreshList();
00461     }
00462 }
00463 
00464 void IdentityPage::slotRenameIdentity() {
00465   assert( !mIdentityDialog );
00466 
00467   TQListViewItem * item = mIdentityList->selectedItem();
00468   if ( !item ) return;
00469 
00470   mIdentityList->rename( item, 0 );
00471 }
00472 
00473 void IdentityPage::slotRenameIdentity( TQListViewItem * i,
00474                                        const TQString & s, int col ) {
00475   assert( col == 0 );
00476   Q_UNUSED( col );
00477 
00478   IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
00479   if ( !item ) return;
00480 
00481   TQString newName = s.stripWhiteSpace();
00482   if ( !newName.isEmpty() &&
00483        !kmkernel->identityManager()->shadowIdentities().contains( newName ) ) {
00484     KPIM::Identity & ident = item->identity();
00485     ident.setIdentityName( newName );
00486     emit changed(true);
00487   }
00488   item->redisplay();
00489 }
00490 
00491 void IdentityPage::slotContextMenu( KListView *, TQListViewItem * i,
00492                                     const TQPoint & pos ) {
00493   IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
00494 
00495   TQPopupMenu * menu = new TQPopupMenu( this );
00496   menu->insertItem( i18n("Add..."), this, TQT_SLOT(slotNewIdentity()) );
00497   if ( item ) {
00498     menu->insertItem( i18n("Modify..."), this, TQT_SLOT(slotModifyIdentity()) );
00499     if ( mIdentityList->childCount() > 1 )
00500       menu->insertItem( i18n("Remove"), this, TQT_SLOT(slotRemoveIdentity()) );
00501     if ( !item->identity().isDefault() )
00502       menu->insertItem( i18n("Set as Default"), this, TQT_SLOT(slotSetAsDefault()) );
00503   }
00504   menu->exec( pos );
00505   delete menu;
00506 }
00507 
00508 
00509 void IdentityPage::slotSetAsDefault() {
00510   assert( !mIdentityDialog );
00511 
00512   IdentityListViewItem * item =
00513     dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
00514   if ( !item ) return;
00515 
00516   KPIM::IdentityManager * im = kmkernel->identityManager();
00517   im->setAsDefault( item->identity().identityName() );
00518   refreshList();
00519 }
00520 
00521 void IdentityPage::refreshList() {
00522   for ( TQListViewItemIterator it( mIdentityList ) ; it.current() ; ++it ) {
00523     IdentityListViewItem * item =
00524       dynamic_cast<IdentityListViewItem*>(it.current());
00525     if ( item )
00526       item->redisplay();
00527   }
00528   emit changed(true);
00529 }
00530 
00531 void IdentityPage::slotIdentitySelectionChanged()
00532 {
00533   IdentityListViewItem *item =
00534     dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
00535 
00536   mRemoveButton->setEnabled( item && mIdentityList->childCount() > 1 );
00537   mModifyButton->setEnabled( item );
00538   mRenameButton->setEnabled( item );
00539   mSetAsDefaultButton->setEnabled( item && !item->identity().isDefault() );
00540 }
00541 
00542 void IdentityPage::slotUpdateTransportCombo( const TQStringList & sl )
00543 {
00544   if ( mIdentityDialog ) mIdentityDialog->slotUpdateTransportCombo( sl );
00545 }
00546 
00547 
00548 
00549 // *************************************************************
00550 // *                                                           *
00551 // *                       AccountsPage                         *
00552 // *                                                           *
00553 // *************************************************************
00554 TQString AccountsPage::helpAnchor() const {
00555   return TQString::fromLatin1("configure-accounts");
00556 }
00557 
00558 AccountsPage::AccountsPage( TQWidget * parent, const char * name )
00559   : ConfigModuleWithTabs( parent, name )
00560 {
00561   //
00562   // "Receiving" tab:
00563   //
00564   mReceivingTab = new ReceivingTab();
00565   addTab( mReceivingTab, i18n( "&Receiving" ) );
00566   connect( mReceivingTab, TQT_SIGNAL(accountListChanged(const TQStringList &)),
00567            this, TQT_SIGNAL(accountListChanged(const TQStringList &)) );
00568 
00569   //
00570   // "Sending" tab:
00571   //
00572   mSendingTab = new SendingTab();
00573   addTab( mSendingTab, i18n( "&Sending" ) );
00574   connect( mSendingTab, TQT_SIGNAL(transportListChanged(const TQStringList&)),
00575            this, TQT_SIGNAL(transportListChanged(const TQStringList&)) );
00576 
00577   load();
00578 }
00579 
00580 TQString AccountsPage::SendingTab::helpAnchor() const {
00581   return TQString::fromLatin1("configure-accounts-sending");
00582 }
00583 
00584 AccountsPageSendingTab::AccountsPageSendingTab( TQWidget * parent, const char * name )
00585   : ConfigModuleTab( parent, name )
00586 {
00587   mTransportInfoList.setAutoDelete( true );
00588   // temp. vars:
00589   TQVBoxLayout *vlay;
00590   TQVBoxLayout *btn_vlay;
00591   TQHBoxLayout *hlay;
00592   TQGridLayout *glay;
00593   TQPushButton *button;
00594   TQGroupBox   *group;
00595 
00596   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
00597   // label: zero stretch ### FIXME more
00598   vlay->addWidget( new TQLabel( i18n("Outgoing accounts (add at least one):"), this ) );
00599 
00600   // hbox layout: stretch 10, spacing inherited from vlay
00601   hlay = new TQHBoxLayout();
00602   vlay->addLayout( hlay, 10 ); // high stretch b/c of the groupbox's sizeHint
00603 
00604   // transport list: left widget in hlay; stretch 1
00605   // ### FIXME: allow inline renaming of the account:
00606   mTransportList = new ListView( this, "transportList", 5 );
00607   mTransportList->addColumn( i18n("Name") );
00608   mTransportList->addColumn( i18n("Type") );
00609   mTransportList->setAllColumnsShowFocus( true );
00610   mTransportList->setSorting( -1 );
00611   connect( mTransportList, TQT_SIGNAL(selectionChanged()),
00612            this, TQT_SLOT(slotTransportSelected()) );
00613   connect( mTransportList, TQT_SIGNAL(doubleClicked( TQListViewItem *)),
00614            this, TQT_SLOT(slotModifySelectedTransport()) );
00615   hlay->addWidget( mTransportList, 1 );
00616 
00617   // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
00618   btn_vlay = new TQVBoxLayout( hlay );
00619 
00620   // "add..." button: stretch 0
00621   button = new TQPushButton( i18n("A&dd..."), this );
00622   button->setAutoDefault( false );
00623   connect( button, TQT_SIGNAL(clicked()),
00624            this, TQT_SLOT(slotAddTransport()) );
00625   btn_vlay->addWidget( button );
00626 
00627   // "modify..." button: stretch 0
00628   mModifyTransportButton = new TQPushButton( i18n("&Modify..."), this );
00629   mModifyTransportButton->setAutoDefault( false );
00630   mModifyTransportButton->setEnabled( false ); // b/c no item is selected yet
00631   connect( mModifyTransportButton, TQT_SIGNAL(clicked()),
00632            this, TQT_SLOT(slotModifySelectedTransport()) );
00633   btn_vlay->addWidget( mModifyTransportButton );
00634 
00635   // "remove" button: stretch 0
00636   mRemoveTransportButton = new TQPushButton( i18n("R&emove"), this );
00637   mRemoveTransportButton->setAutoDefault( false );
00638   mRemoveTransportButton->setEnabled( false ); // b/c no item is selected yet
00639   connect( mRemoveTransportButton, TQT_SIGNAL(clicked()),
00640            this, TQT_SLOT(slotRemoveSelectedTransport()) );
00641   btn_vlay->addWidget( mRemoveTransportButton );
00642 
00643   mSetDefaultTransportButton = new TQPushButton( i18n("Set Default"), this );
00644   mSetDefaultTransportButton->setAutoDefault( false );
00645   mSetDefaultTransportButton->setEnabled( false );
00646   connect ( mSetDefaultTransportButton, TQT_SIGNAL(clicked()),
00647             this, TQT_SLOT(slotSetDefaultTransport()) );
00648   btn_vlay->addWidget( mSetDefaultTransportButton );
00649   btn_vlay->addStretch( 1 ); // spacer
00650 
00651   // "Common options" groupbox:
00652   group = new TQGroupBox( 0, Qt::Vertical,
00653                          i18n("Common Options"), this );
00654   vlay->addWidget(group);
00655 
00656   // a grid layout for the contents of the "common options" group box
00657   glay = new TQGridLayout( group->layout(), 5, 3, KDialog::spacingHint() );
00658   glay->setColStretch( 2, 10 );
00659 
00660   // "confirm before send" check box:
00661   mConfirmSendCheck = new TQCheckBox( i18n("Confirm &before send"), group );
00662   glay->addMultiCellWidget( mConfirmSendCheck, 0, 0, 0, 1 );
00663   connect( mConfirmSendCheck, TQT_SIGNAL( stateChanged( int ) ),
00664            this, TQT_SLOT( slotEmitChanged( void ) ) );
00665 
00666   // "send on check" combo:
00667   mSendOnCheckCombo = new TQComboBox( false, group );
00668   mSendOnCheckCombo->insertStringList( TQStringList()
00669                                       << i18n("Never Automatically")
00670                                       << i18n("On Manual Mail Checks")
00671                                       << i18n("On All Mail Checks") );
00672   glay->addWidget( mSendOnCheckCombo, 1, 1 );
00673   connect( mSendOnCheckCombo, TQT_SIGNAL( activated( int ) ),
00674            this, TQT_SLOT( slotEmitChanged( void ) ) );
00675 
00676   // "default send method" combo:
00677   mSendMethodCombo = new TQComboBox( false, group );
00678   mSendMethodCombo->insertStringList( TQStringList()
00679                                       << i18n("Send Now")
00680                                       << i18n("Send Later") );
00681   glay->addWidget( mSendMethodCombo, 2, 1 );
00682   connect( mSendMethodCombo, TQT_SIGNAL( activated( int ) ),
00683            this, TQT_SLOT( slotEmitChanged( void ) ) );
00684 
00685 
00686   // "message property" combo:
00687   // ### FIXME: remove completely?
00688   mMessagePropertyCombo = new TQComboBox( false, group );
00689   mMessagePropertyCombo->insertStringList( TQStringList()
00690                      << i18n("Allow 8-bit")
00691                      << i18n("MIME Compliant (Quoted Printable)") );
00692   glay->addWidget( mMessagePropertyCombo, 3, 1 );
00693   connect( mMessagePropertyCombo, TQT_SIGNAL( activated( int ) ),
00694            this, TQT_SLOT( slotEmitChanged( void ) ) );
00695 
00696   // "default domain" input field:
00697   mDefaultDomainEdit = new KLineEdit( group );
00698   glay->addMultiCellWidget( mDefaultDomainEdit, 4, 4, 1, 2 );
00699   connect( mDefaultDomainEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
00700            this, TQT_SLOT( slotEmitChanged( void ) ) );
00701 
00702   // labels:
00703   TQLabel *l =  new TQLabel( mSendOnCheckCombo, /*buddy*/
00704                             i18n("Send &messages in outbox folder:"), group );
00705   glay->addWidget( l, 1, 0 );
00706 
00707   TQString msg = i18n( GlobalSettings::self()->sendOnCheckItem()->whatsThis().utf8() );
00708   TQWhatsThis::add( l, msg );
00709   TQWhatsThis::add( mSendOnCheckCombo, msg );
00710 
00711   glay->addWidget( new TQLabel( mSendMethodCombo, /*buddy*/
00712                                i18n("Defa&ult send method:"), group ), 2, 0 );
00713   glay->addWidget( new TQLabel( mMessagePropertyCombo, /*buddy*/
00714                                i18n("Message &property:"), group ), 3, 0 );
00715   l = new TQLabel( mDefaultDomainEdit, /*buddy*/
00716                           i18n("Defaul&t domain:"), group );
00717   glay->addWidget( l, 4, 0 );
00718 
00719   // and now: add TQWhatsThis:
00720   msg = i18n( "<qt><p>The default domain is used to complete email "
00721               "addresses that only consist of the user's name."
00722               "</p></qt>" );
00723   TQWhatsThis::add( l, msg );
00724   TQWhatsThis::add( mDefaultDomainEdit, msg );
00725 }
00726 
00727 
00728 void AccountsPage::SendingTab::slotTransportSelected()
00729 {
00730   TQListViewItem *cur = mTransportList->selectedItem();
00731   mModifyTransportButton->setEnabled( cur );
00732   mRemoveTransportButton->setEnabled( cur );
00733   mSetDefaultTransportButton->setEnabled( cur );
00734 }
00735 
00736 // adds a number to @p name to make the name unique
00737 static inline TQString uniqueName( const TQStringList & list,
00738                                   const TQString & name )
00739 {
00740   int suffix = 1;
00741   TQString result = name;
00742   while ( list.find( result ) != list.end() ) {
00743     result = i18n("%1: name; %2: number appended to it to make it unique "
00744                   "among a list of names", "%1 %2")
00745       .arg( name ).arg( suffix );
00746     suffix++;
00747   }
00748   return result;
00749 }
00750 
00751 void AccountsPage::SendingTab::slotSetDefaultTransport()
00752 {
00753   TQListViewItem *item = mTransportList->selectedItem();
00754   if ( !item ) return;
00755 
00756   KMTransportInfo ti;
00757 
00758   TQListViewItemIterator it( mTransportList );
00759   for ( ; it.current(); ++it ) {
00760   ti.readConfig( KMTransportInfo::findTransport( it.current()->text(0) ));
00761   if ( ti.type != "sendmail" ) {
00762     it.current()->setText( 1, "smtp" );
00763   } else {
00764     it.current()->setText( 1, "sendmail" );
00765     }
00766   }
00767 
00768   if ( item->text(1) != "sendmail" ) {
00769     item->setText( 1, i18n( "smtp (Default)" ));
00770   } else {
00771     item->setText( 1, i18n( "sendmail (Default)" ));
00772   }
00773   GlobalSettings::self()->setDefaultTransport( item->text(0) );
00774 
00775 }
00776 
00777 void AccountsPage::SendingTab::slotAddTransport()
00778 {
00779   int transportType;
00780 
00781   { // limit scope of selDialog
00782     KMTransportSelDlg selDialog( this );
00783     if ( selDialog.exec() != TQDialog::Accepted ) return;
00784     transportType = selDialog.selected();
00785   }
00786 
00787   KMTransportInfo *transportInfo = new KMTransportInfo();
00788   switch ( transportType ) {
00789   case 0: // smtp
00790     transportInfo->type = TQString::fromLatin1("smtp");
00791     break;
00792   case 1: // sendmail
00793     transportInfo->type = TQString::fromLatin1("sendmail");
00794     transportInfo->name = i18n("Sendmail");
00795     transportInfo->host = _PATH_SENDMAIL; // ### FIXME: use const, not #define
00796     break;
00797   default:
00798     assert( 0 );
00799   }
00800 
00801   KMTransportDialog dialog( i18n("Add Transport"), transportInfo, this );
00802 
00803   // create list of names:
00804   // ### move behind dialog.exec()?
00805   TQStringList transportNames;
00806   TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
00807   for ( it.toFirst() ; it.current() ; ++it )
00808     transportNames << (*it)->name;
00809 
00810   if( dialog.exec() != TQDialog::Accepted ) {
00811     delete transportInfo;
00812     return;
00813   }
00814 
00815   // disambiguate the name by appending a number:
00816   // ### FIXME: don't allow this error to happen in the first place!
00817   transportInfo->name = uniqueName( transportNames, transportInfo->name );
00818   // append to names and transportinfo lists:
00819   transportNames << transportInfo->name;
00820   mTransportInfoList.append( transportInfo );
00821 
00822   // append to listview:
00823   // ### FIXME: insert before the selected item, append on empty selection
00824   TQListViewItem *lastItem = mTransportList->firstChild();
00825   TQString typeDisplayName;
00826   if ( lastItem ) {
00827     typeDisplayName = transportInfo->type;
00828   } else {
00829     typeDisplayName = i18n("%1: type of transport. Result used in "
00830                            "Configure->Accounts->Sending listview, \"type\" "
00831                            "column, first row, to indicate that this is the "
00832                            "default transport", "%1 (Default)")
00833       .arg( transportInfo->type );
00834     GlobalSettings::self()->setDefaultTransport( transportInfo->name );
00835   }
00836   (void) new TQListViewItem( mTransportList, lastItem, transportInfo->name,
00837                             typeDisplayName );
00838 
00839   // notify anyone who cares:
00840   emit transportListChanged( transportNames );
00841   emit changed( true );
00842 }
00843 
00844 void AccountsPage::SendingTab::slotModifySelectedTransport()
00845 {
00846   TQListViewItem *item = mTransportList->selectedItem();
00847   if ( !item ) return;
00848 
00849   const TQString& originalTransport = item->text(0);
00850 
00851   TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
00852   for ( it.toFirst() ; it.current() ; ++it )
00853     if ( (*it)->name == item->text(0) ) break;
00854   if ( !it.current() ) return;
00855 
00856   KMTransportDialog dialog( i18n("Modify Transport"), (*it), this );
00857 
00858   if ( dialog.exec() != TQDialog::Accepted ) return;
00859 
00860   // create the list of names of transports, but leave out the current
00861   // item:
00862   TQStringList transportNames;
00863   TQPtrListIterator<KMTransportInfo> jt( mTransportInfoList );
00864   int entryLocation = -1;
00865   for ( jt.toFirst() ; jt.current() ; ++jt )
00866     if ( jt != it )
00867       transportNames << (*jt)->name;
00868     else
00869       entryLocation = transportNames.count();
00870   assert( entryLocation >= 0 );
00871 
00872   // make the new name unique by appending a high enough number:
00873   (*it)->name = uniqueName( transportNames, (*it)->name );
00874   // change the list item to the new name
00875   item->setText( 0, (*it)->name );
00876   // and insert the new name at the position of the old in the list of
00877   // strings; then broadcast the new list:
00878   transportNames.insert( transportNames.at( entryLocation ), (*it)->name );
00879   const TQString& newTransportName = (*it)->name;
00880 
00881   TQStringList changedIdents;
00882   KPIM::IdentityManager * im = kmkernel->identityManager();
00883   for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
00884     if ( originalTransport == (*it).transport() ) {
00885       (*it).setTransport( newTransportName );
00886       changedIdents += (*it).identityName();
00887     }
00888   }
00889 
00890   if ( !changedIdents.isEmpty() ) {
00891     TQString information = i18n( "This identity has been changed to use the modified transport:",
00892                           "These %n identities have been changed to use the modified transport:",
00893                           changedIdents.count() );
00894     KMessageBox::informationList( this, information, changedIdents );
00895   }
00896 
00897   emit transportListChanged( transportNames );
00898   emit changed( true );
00899 }
00900 
00901 void AccountsPage::SendingTab::slotRemoveSelectedTransport()
00902 {
00903   TQListViewItem *item = mTransportList->selectedItem();
00904   if ( !item ) return;
00905 
00906   bool selectedTransportWasDefault = false;
00907   if ( item->text( 0 ) == GlobalSettings::self()->defaultTransport() ) {
00908       selectedTransportWasDefault = true;
00909   }
00910   TQStringList changedIdents;
00911   KPIM::IdentityManager * im = kmkernel->identityManager();
00912   for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
00913     if ( item->text( 0 ) == (*it).transport() ) {
00914       (*it).setTransport( TQString::null );
00915       changedIdents += (*it).identityName();
00916     }
00917   }
00918 
00919   // if the deleted transport is the currently used transport reset it to default
00920   const TQString& currentTransport = GlobalSettings::self()->currentTransport();
00921   if ( item->text( 0 ) == currentTransport ) {
00922     GlobalSettings::self()->setCurrentTransport( TQString::null );
00923   }
00924 
00925   if ( !changedIdents.isEmpty() ) {
00926     TQString information = i18n( "This identity has been changed to use the default transport:",
00927                           "These %n identities have been changed to use the default transport:",
00928                           changedIdents.count() );
00929     KMessageBox::informationList( this, information, changedIdents );
00930   }
00931 
00932   TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
00933   for ( it.toFirst() ; it.current() ; ++it )
00934     if ( (*it)->name == item->text(0) ) break;
00935   if ( !it.current() ) return;
00936 
00937   KMTransportInfo ti;
00938 
00939   if( selectedTransportWasDefault )
00940   {
00941     TQListViewItem *newCurrent = item->itemBelow();
00942     if ( !newCurrent ) newCurrent = item->itemAbove();
00943     //mTransportList->removeItem( item );
00944     if ( newCurrent ) {
00945       mTransportList->setCurrentItem( newCurrent );
00946       mTransportList->setSelected( newCurrent, true );
00947       GlobalSettings::self()->setDefaultTransport( newCurrent->text(0) );
00948       ti.readConfig( KMTransportInfo::findTransport( newCurrent->text(0) ));
00949       if ( ti.type != "sendmail" ) {
00950         newCurrent->setText( 1, i18n("smtp (Default)") );
00951       } else {
00952         newCurrent->setText( 1, i18n("sendmail (Default)" ));
00953       }
00954     } else {
00955       GlobalSettings::self()->setDefaultTransport( TQString::null );
00956     }
00957   }
00958   delete item;
00959   mTransportInfoList.remove( it );
00960 
00961   TQStringList transportNames;
00962   for ( it.toFirst() ; it.current() ; ++it )
00963     transportNames << (*it)->name;
00964   emit transportListChanged( transportNames );
00965   emit changed( true );
00966 }
00967 
00968 void AccountsPage::SendingTab::doLoadFromGlobalSettings() {
00969   mSendOnCheckCombo->setCurrentItem( GlobalSettings::self()->sendOnCheck() );
00970 }
00971 
00972 void AccountsPage::SendingTab::doLoadOther() {
00973   KConfigGroup general( KMKernel::config(), "General");
00974   KConfigGroup composer( KMKernel::config(), "Composer");
00975 
00976   int numTransports = general.readNumEntry("transports", 0);
00977 
00978   TQListViewItem *top = 0;
00979   mTransportInfoList.clear();
00980   mTransportList->clear();
00981   TQStringList transportNames;
00982   for ( int i = 1 ; i <= numTransports ; i++ ) {
00983     KMTransportInfo *ti = new KMTransportInfo();
00984     ti->readConfig(i);
00985     mTransportInfoList.append( ti );
00986     transportNames << ti->name;
00987     top = new TQListViewItem( mTransportList, top, ti->name, ti->type );
00988   }
00989   emit transportListChanged( transportNames );
00990 
00991   const TQString &defaultTransport = GlobalSettings::self()->defaultTransport();
00992 
00993   TQListViewItemIterator it( mTransportList );
00994   for ( ; it.current(); ++it ) {
00995     if ( it.current()->text(0) == defaultTransport ) {
00996       if ( it.current()->text(1) != "sendmail" ) {
00997         it.current()->setText( 1, i18n( "smtp (Default)" ));
00998       } else {
00999         it.current()->setText( 1, i18n( "sendmail (Default)" ));
01000       }
01001     } else {
01002       if ( it.current()->text(1) != "sendmail" ) {
01003         it.current()->setText( 1, "smtp" );
01004       } else {
01005         it.current()->setText( 1, "sendmail" );
01006       }
01007     }
01008   }
01009 
01010   mSendMethodCombo->setCurrentItem(
01011                 kmkernel->msgSender()->sendImmediate() ? 0 : 1 );
01012   mMessagePropertyCombo->setCurrentItem(
01013                 kmkernel->msgSender()->sendQuotedPrintable() ? 1 : 0 );
01014 
01015   mConfirmSendCheck->setChecked( composer.readBoolEntry( "confirm-before-send",
01016                                                          false ) );
01017   TQString str = general.readEntry( "Default domain" );
01018   if( str.isEmpty() )
01019   {
01020     //### FIXME: Use the global convenience function instead of the homebrewed
01021     //           solution once we can rely on HEAD kdelibs.
01022     //str = KGlobal::hostname(); ???????
01023     char buffer[256];
01024     if ( !gethostname( buffer, 255 ) )
01025       // buffer need not be NUL-terminated if it has full length
01026       buffer[255] = 0;
01027     else
01028       buffer[0] = 0;
01029     str = TQString::fromLatin1( *buffer ? buffer : "localhost" );
01030   }
01031   mDefaultDomainEdit->setText( str );
01032 }
01033 
01034 void AccountsPage::SendingTab::save() {
01035   KConfigGroup general( KMKernel::config(), "General" );
01036   KConfigGroup composer( KMKernel::config(), "Composer" );
01037 
01038   // Save transports:
01039   general.writeEntry( "transports", mTransportInfoList.count() );
01040   TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
01041   for ( int i = 1 ; it.current() ; ++it, ++i )
01042     (*it)->writeConfig(i);
01043 
01044   // Save common options:
01045   GlobalSettings::self()->setSendOnCheck( mSendOnCheckCombo->currentItem() );
01046   kmkernel->msgSender()->setSendImmediate(
01047                              mSendMethodCombo->currentItem() == 0 );
01048   kmkernel->msgSender()->setSendQuotedPrintable(
01049                              mMessagePropertyCombo->currentItem() == 1 );
01050   kmkernel->msgSender()->writeConfig( false ); // don't sync
01051   composer.writeEntry("confirm-before-send", mConfirmSendCheck->isChecked() );
01052   general.writeEntry( "Default domain", mDefaultDomainEdit->text() );
01053 }
01054 
01055 TQString AccountsPage::ReceivingTab::helpAnchor() const {
01056   return TQString::fromLatin1("configure-accounts-receiving");
01057 }
01058 
01059 AccountsPageReceivingTab::AccountsPageReceivingTab( TQWidget * parent, const char * name )
01060   : ConfigModuleTab ( parent, name )
01061 {
01062   // temp. vars:
01063   TQVBoxLayout *vlay;
01064   TQVBoxLayout *btn_vlay;
01065   TQHBoxLayout *hlay;
01066   TQPushButton *button;
01067   TQGroupBox   *group;
01068 
01069   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
01070 
01071   // label: zero stretch
01072   vlay->addWidget( new TQLabel( i18n("Incoming accounts (add at least one):"), this ) );
01073 
01074   // hbox layout: stretch 10, spacing inherited from vlay
01075   hlay = new TQHBoxLayout();
01076   vlay->addLayout( hlay, 10 ); // high stretch to suppress groupbox's growing
01077 
01078   // account list: left widget in hlay; stretch 1
01079   mAccountList = new ListView( this, "accountList", 5 );
01080   mAccountList->addColumn( i18n("Name") );
01081   mAccountList->addColumn( i18n("Type") );
01082   mAccountList->addColumn( i18n("Folder") );
01083   mAccountList->setAllColumnsShowFocus( true );
01084   mAccountList->setSorting( -1 );
01085   connect( mAccountList, TQT_SIGNAL(selectionChanged()),
01086            this, TQT_SLOT(slotAccountSelected()) );
01087   connect( mAccountList, TQT_SIGNAL(doubleClicked( TQListViewItem *)),
01088            this, TQT_SLOT(slotModifySelectedAccount()) );
01089   hlay->addWidget( mAccountList, 1 );
01090 
01091   // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
01092   btn_vlay = new TQVBoxLayout( hlay );
01093 
01094   // "add..." button: stretch 0
01095   button = new TQPushButton( i18n("A&dd..."), this );
01096   button->setAutoDefault( false );
01097   connect( button, TQT_SIGNAL(clicked()),
01098            this, TQT_SLOT(slotAddAccount()) );
01099   btn_vlay->addWidget( button );
01100 
01101   // "modify..." button: stretch 0
01102   mModifyAccountButton = new TQPushButton( i18n("&Modify..."), this );
01103   mModifyAccountButton->setAutoDefault( false );
01104   mModifyAccountButton->setEnabled( false ); // b/c no item is selected yet
01105   connect( mModifyAccountButton, TQT_SIGNAL(clicked()),
01106            this, TQT_SLOT(slotModifySelectedAccount()) );
01107   btn_vlay->addWidget( mModifyAccountButton );
01108 
01109   // "remove..." button: stretch 0
01110   mRemoveAccountButton = new TQPushButton( i18n("R&emove"), this );
01111   mRemoveAccountButton->setAutoDefault( false );
01112   mRemoveAccountButton->setEnabled( false ); // b/c no item is selected yet
01113   connect( mRemoveAccountButton, TQT_SIGNAL(clicked()),
01114            this, TQT_SLOT(slotRemoveSelectedAccount()) );
01115   btn_vlay->addWidget( mRemoveAccountButton );
01116   btn_vlay->addStretch( 1 ); // spacer
01117 
01118   mCheckmailStartupCheck = new TQCheckBox( i18n("Chec&k mail on startup"), this );
01119   vlay->addWidget( mCheckmailStartupCheck );
01120   connect( mCheckmailStartupCheck, TQT_SIGNAL( stateChanged( int ) ),
01121            this, TQT_SLOT( slotEmitChanged( void ) ) );
01122 
01123   // "New Mail Notification" group box: stretch 0
01124   group = new TQVGroupBox( i18n("New Mail Notification"), this );
01125   vlay->addWidget( group );
01126   group->layout()->setSpacing( KDialog::spacingHint() );
01127 
01128   // "beep on new mail" check box:
01129   mBeepNewMailCheck = new TQCheckBox(i18n("&Beep"), group );
01130   mBeepNewMailCheck->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
01131                                                  TQSizePolicy::Fixed ) );
01132   connect( mBeepNewMailCheck, TQT_SIGNAL( stateChanged( int ) ),
01133            this, TQT_SLOT( slotEmitChanged( void ) ) );
01134 
01135   // "Detailed new mail notification" check box
01136   mVerboseNotificationCheck =
01137     new TQCheckBox( i18n( "Deta&iled new mail notification" ), group );
01138   mVerboseNotificationCheck->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
01139                                                          TQSizePolicy::Fixed ) );
01140   TQToolTip::add( mVerboseNotificationCheck,
01141                  i18n( "Show for each folder the number of newly arrived "
01142                        "messages" ) );
01143   TQWhatsThis::add( mVerboseNotificationCheck,
01144     GlobalSettings::self()->verboseNewMailNotificationItem()->whatsThis() );
01145   connect( mVerboseNotificationCheck, TQT_SIGNAL( stateChanged( int ) ),
01146            this, TQT_SLOT( slotEmitChanged() ) );
01147 
01148   // "Other Actions" button:
01149   mOtherNewMailActionsButton = new TQPushButton( i18n("Other Actio&ns"), group );
01150   mOtherNewMailActionsButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed,
01151                                                           TQSizePolicy::Fixed ) );
01152   connect( mOtherNewMailActionsButton, TQT_SIGNAL(clicked()),
01153            this, TQT_SLOT(slotEditNotifications()) );
01154 }
01155 
01156 AccountsPageReceivingTab::~AccountsPageReceivingTab()
01157 {
01158   // When hitting Cancel or closing the dialog with the window-manager-button,
01159   // we have a number of things to clean up:
01160 
01161   // The newly created accounts
01162   TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
01163   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
01164     delete (*it);
01165   }
01166   mNewAccounts.clear();
01167 
01168   // The modified accounts
01169   TQValueList<ModifiedAccountsType*>::Iterator j;
01170   for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
01171     delete (*j)->newAccount;
01172     delete (*j);
01173   }
01174   mModifiedAccounts.clear();
01175 
01176 
01177 }
01178 
01179 void AccountsPage::ReceivingTab::slotAccountSelected()
01180 {
01181   TQListViewItem * item = mAccountList->selectedItem();
01182   mModifyAccountButton->setEnabled( item );
01183   mRemoveAccountButton->setEnabled( item );
01184 }
01185 
01186 TQStringList AccountsPage::ReceivingTab::occupiedNames()
01187 {
01188   TQStringList accountNames = kmkernel->acctMgr()->getAccounts();
01189 
01190   TQValueList<ModifiedAccountsType*>::Iterator k;
01191   for (k = mModifiedAccounts.begin(); k != mModifiedAccounts.end(); ++k )
01192     if ((*k)->oldAccount)
01193       accountNames.remove( (*k)->oldAccount->name() );
01194 
01195   TQValueList< TQGuardedPtr<KMAccount> >::Iterator l;
01196   for (l = mAccountsToDelete.begin(); l != mAccountsToDelete.end(); ++l )
01197     if (*l)
01198       accountNames.remove( (*l)->name() );
01199 
01200   TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
01201   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it )
01202     if (*it)
01203       accountNames += (*it)->name();
01204 
01205   TQValueList<ModifiedAccountsType*>::Iterator j;
01206   for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
01207     accountNames += (*j)->newAccount->name();
01208 
01209   return accountNames;
01210 }
01211 
01212 void AccountsPage::ReceivingTab::slotAddAccount() {
01213   KMAcctSelDlg accountSelectorDialog( this );
01214   if( accountSelectorDialog.exec() != TQDialog::Accepted ) return;
01215 
01216   const char *accountType = 0;
01217   switch ( accountSelectorDialog.selected() ) {
01218     case 0: accountType = "local";      break;
01219     case 1: accountType = "pop";        break;
01220     case 2: accountType = "imap";       break;
01221     case 3: accountType = "cachedimap"; break;
01222     case 4: accountType = "maildir";    break;
01223 
01224     default:
01225       // ### FIXME: How should this happen???
01226       // replace with assert.
01227       KMessageBox::sorry( this, i18n("Unknown account type selected") );
01228       return;
01229   }
01230 
01231   KMAccount *account
01232     = kmkernel->acctMgr()->create( TQString::fromLatin1( accountType ) );
01233   if ( !account ) {
01234     // ### FIXME: Give the user more information. Is this error
01235     // recoverable?
01236     KMessageBox::sorry( this, i18n("Unable to create account") );
01237     return;
01238   }
01239 
01240   account->init(); // fill the account fields with good default values
01241 
01242   AccountDialog dialog( i18n("Add Account"), account, this );
01243 
01244   TQStringList accountNames = occupiedNames();
01245 
01246   if( dialog.exec() != TQDialog::Accepted ) {
01247     delete account;
01248     return;
01249   }
01250 
01251   account->deinstallTimer();
01252   account->setName( uniqueName( accountNames, account->name() ) );
01253 
01254   TQListViewItem *after = mAccountList->firstChild();
01255   while ( after && after->nextSibling() )
01256     after = after->nextSibling();
01257 
01258   TQListViewItem *listItem =
01259     new TQListViewItem( mAccountList, after, account->name(), account->type() );
01260   if( account->folder() )
01261     listItem->setText( 2, account->folder()->label() );
01262 
01263   mNewAccounts.append( account );
01264   emit changed( true );
01265 }
01266 
01267 
01268 
01269 void AccountsPage::ReceivingTab::slotModifySelectedAccount()
01270 {
01271   TQListViewItem *listItem = mAccountList->selectedItem();
01272   if( !listItem ) return;
01273 
01274   KMAccount *account = 0;
01275   TQValueList<ModifiedAccountsType*>::Iterator j;
01276   for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
01277     if ( (*j)->newAccount->name() == listItem->text(0) ) {
01278       account = (*j)->newAccount;
01279       break;
01280     }
01281 
01282   if ( !account ) {
01283     TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
01284     for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
01285       if ( (*it)->name() == listItem->text(0) ) {
01286         account = *it;
01287         break;
01288       }
01289 
01290     if ( !account ) {
01291       account = kmkernel->acctMgr()->findByName( listItem->text(0) );
01292       if( !account ) {
01293         // ### FIXME: How should this happen? See above.
01294         KMessageBox::sorry( this, i18n("Unable to locate account") );
01295         return;
01296       }
01297       if ( account->type() == "imap" || account->type() == "cachedimap" )
01298       {
01299         ImapAccountBase* ai = static_cast<ImapAccountBase*>( account );
01300         if ( ai->namespaces().isEmpty() || ai->namespaceToDelimiter().isEmpty() )
01301         {
01302           // connect to server - the namespaces are fetched automatically
01303           kdDebug(5006) << "slotModifySelectedAccount - connect" << endl;
01304           ai->makeConnection();
01305         }
01306       }
01307 
01308       ModifiedAccountsType *mod = new ModifiedAccountsType;
01309       mod->oldAccount = account;
01310       mod->newAccount = kmkernel->acctMgr()->create( account->type(),
01311                                                    account->name() );
01312       mod->newAccount->pseudoAssign( account );
01313       mModifiedAccounts.append( mod );
01314       account = mod->newAccount;
01315     }
01316   }
01317 
01318   TQStringList accountNames = occupiedNames();
01319   accountNames.remove( account->name() );
01320 
01321   AccountDialog dialog( i18n("Modify Account"), account, this );
01322 
01323   if( dialog.exec() != TQDialog::Accepted ) return;
01324 
01325   account->setName( uniqueName( accountNames, account->name() ) );
01326 
01327   listItem->setText( 0, account->name() );
01328   listItem->setText( 1, account->type() );
01329   if( account->folder() )
01330     listItem->setText( 2, account->folder()->label() );
01331 
01332   emit changed( true );
01333 }
01334 
01335 
01336 
01337 void AccountsPage::ReceivingTab::slotRemoveSelectedAccount() {
01338   TQListViewItem *listItem = mAccountList->selectedItem();
01339   if( !listItem ) return;
01340 
01341   KMAccount *acct = 0;
01342   TQValueList<ModifiedAccountsType*>::Iterator j;
01343   for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j )
01344     if ( (*j)->newAccount->name() == listItem->text(0) ) {
01345       acct = (*j)->oldAccount;
01346       mAccountsToDelete.append( acct );
01347       mModifiedAccounts.remove( j );
01348       break;
01349     }
01350   if ( !acct ) {
01351     TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
01352     for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
01353       if ( (*it)->name() == listItem->text(0) ) {
01354         acct = *it;
01355         mNewAccounts.remove( it );
01356         break;
01357       }
01358   }
01359   if ( !acct ) {
01360     acct = kmkernel->acctMgr()->findByName( listItem->text(0) );
01361     if ( acct )
01362       mAccountsToDelete.append( acct );
01363   }
01364   if ( !acct ) {
01365     // ### FIXME: see above
01366     KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
01367                         .arg(listItem->text(0)) );
01368     return;
01369   }
01370 
01371   TQListViewItem * item = listItem->itemBelow();
01372   if ( !item ) item = listItem->itemAbove();
01373   delete listItem;
01374 
01375   if ( item )
01376     mAccountList->setSelected( item, true );
01377 
01378   emit changed( true );
01379 }
01380 
01381 void AccountsPage::ReceivingTab::slotEditNotifications()
01382 {
01383   if(kmkernel->xmlGuiInstance())
01384     KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
01385   else
01386     KNotifyDialog::configure(this);
01387 }
01388 
01389 void AccountsPage::ReceivingTab::doLoadFromGlobalSettings() {
01390   mVerboseNotificationCheck->setChecked( GlobalSettings::self()->verboseNewMailNotification() );
01391 }
01392 
01393 void AccountsPage::ReceivingTab::doLoadOther() {
01394   KConfigGroup general( KMKernel::config(), "General" );
01395 
01396   mAccountList->clear();
01397   TQListViewItem *top = 0;
01398 
01399   for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
01400        a = kmkernel->acctMgr()->next() ) {
01401     TQListViewItem *listItem =
01402       new TQListViewItem( mAccountList, top, a->name(), a->type() );
01403     if( a->folder() )
01404       listItem->setText( 2, a->folder()->label() );
01405     top = listItem;
01406   }
01407   TQListViewItem *listItem = mAccountList->firstChild();
01408   if ( listItem ) {
01409     mAccountList->setCurrentItem( listItem );
01410     mAccountList->setSelected( listItem, true );
01411   }
01412 
01413   mBeepNewMailCheck->setChecked( general.readBoolEntry("beep-on-mail", false ) );
01414   mCheckmailStartupCheck->setChecked( general.readBoolEntry("checkmail-startup", false) );
01415   TQTimer::singleShot( 0, this, TQT_SLOT( slotTweakAccountList() ) );
01416 }
01417 
01418 void AccountsPage::ReceivingTab::slotTweakAccountList()
01419 {
01420   // Force the contentsWidth of mAccountList to be recalculated so that items can be
01421   // selected in the normal way. It would be best if this were not necessary.
01422   mAccountList->resizeContents( mAccountList->visibleWidth(), mAccountList->contentsHeight() );
01423 }
01424 
01425 void AccountsPage::ReceivingTab::save() {
01426   // Add accounts marked as new
01427   TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
01428   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
01429     kmkernel->acctMgr()->add( *it ); // calls installTimer too
01430   }
01431 
01432   // Update accounts that have been modified
01433   TQValueList<ModifiedAccountsType*>::Iterator j;
01434   for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
01435     (*j)->oldAccount->pseudoAssign( (*j)->newAccount );
01436     delete (*j)->newAccount;
01437     delete (*j);
01438   }
01439   mModifiedAccounts.clear();
01440 
01441   // Delete accounts marked for deletion
01442   for ( it = mAccountsToDelete.begin() ;
01443         it != mAccountsToDelete.end() ; ++it ) {
01444     kmkernel->acctMgr()->writeConfig( true );
01445     if ( (*it) && !kmkernel->acctMgr()->remove(*it) )
01446       KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
01447                           .arg( (*it)->name() ) );
01448   }
01449   mAccountsToDelete.clear();
01450 
01451   // Incoming mail
01452   kmkernel->acctMgr()->writeConfig( false );
01453   kmkernel->cleanupImapFolders();
01454 
01455   // Save Mail notification settings
01456   KConfigGroup general( KMKernel::config(), "General" );
01457   general.writeEntry( "beep-on-mail", mBeepNewMailCheck->isChecked() );
01458   GlobalSettings::self()->setVerboseNewMailNotification( mVerboseNotificationCheck->isChecked() );
01459 
01460   general.writeEntry( "checkmail-startup", mCheckmailStartupCheck->isChecked() );
01461 
01462   // Sync new IMAP accounts ASAP:
01463   for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
01464     KMAccount *macc = (*it);
01465     ImapAccountBase *acc = dynamic_cast<ImapAccountBase*> (macc);
01466     if ( acc ) {
01467       AccountUpdater *au = new AccountUpdater( acc );
01468       au->update();
01469     }
01470   }
01471   mNewAccounts.clear();
01472 
01473 }
01474 
01475 // *************************************************************
01476 // *                                                           *
01477 // *                     AppearancePage                        *
01478 // *                                                           *
01479 // *************************************************************
01480 TQString AppearancePage::helpAnchor() const {
01481   return TQString::fromLatin1("configure-appearance");
01482 }
01483 
01484 AppearancePage::AppearancePage( TQWidget * parent, const char * name )
01485   : ConfigModuleWithTabs( parent, name )
01486 {
01487   //
01488   // "Fonts" tab:
01489   //
01490   mFontsTab = new FontsTab();
01491   addTab( mFontsTab, i18n("&Fonts") );
01492 
01493   //
01494   // "Colors" tab:
01495   //
01496   mColorsTab = new ColorsTab();
01497   addTab( mColorsTab, i18n("Color&s") );
01498 
01499   //
01500   // "Layout" tab:
01501   //
01502   mLayoutTab = new LayoutTab();
01503   addTab( mLayoutTab, i18n("La&yout") );
01504 
01505   //
01506   // "Headers" tab:
01507   //
01508   mHeadersTab = new HeadersTab();
01509   addTab( mHeadersTab, i18n("M&essage List") );
01510 
01511   //
01512   // "Reader window" tab:
01513   //
01514   mReaderTab = new ReaderTab();
01515   addTab( mReaderTab, i18n("Message W&indow") );
01516 
01517   //
01518   // "System Tray" tab:
01519   //
01520   mSystemTrayTab = new SystemTrayTab();
01521   addTab( mSystemTrayTab, i18n("System &Tray") );
01522 
01523   load();
01524 }
01525 
01526 
01527 TQString AppearancePage::FontsTab::helpAnchor() const {
01528   return TQString::fromLatin1("configure-appearance-fonts");
01529 }
01530 
01531 static const struct {
01532   const char * configName;
01533   const char * displayName;
01534   bool   enableFamilyAndSize;
01535   bool   onlyFixed;
01536 } fontNames[] = {
01537   { "body-font", I18N_NOOP("Message Body"), true, false },
01538   { "list-font", I18N_NOOP("Message List"), true, false },
01539   { "list-new-font", I18N_NOOP("Message List - New Messages"), true, false },
01540   { "list-unread-font", I18N_NOOP("Message List - Unread Messages"), true, false },
01541   { "list-important-font", I18N_NOOP("Message List - Important Messages"), true, false },
01542   { "list-todo-font", I18N_NOOP("Message List - Todo Messages"), true, false },
01543   { "list-date-font", I18N_NOOP("Message List - Date Field"), true, false },
01544   { "folder-font", I18N_NOOP("Folder List"), true, false },
01545   { "quote1-font", I18N_NOOP("Quoted Text - First Level"), false, false },
01546   { "quote2-font", I18N_NOOP("Quoted Text - Second Level"), false, false },
01547   { "quote3-font", I18N_NOOP("Quoted Text - Third Level"), false, false },
01548   { "fixed-font", I18N_NOOP("Fixed Width Font"), true, true },
01549   { "composer-font", I18N_NOOP("Composer"), true, false },
01550   { "print-font",  I18N_NOOP("Printing Output"), true, false },
01551 };
01552 static const int numFontNames = sizeof fontNames / sizeof *fontNames;
01553 
01554 AppearancePageFontsTab::AppearancePageFontsTab( TQWidget * parent, const char * name )
01555   : ConfigModuleTab( parent, name ), mActiveFontIndex( -1 )
01556 {
01557   assert( numFontNames == sizeof mFont / sizeof *mFont );
01558   // tmp. vars:
01559   TQVBoxLayout *vlay;
01560   TQHBoxLayout *hlay;
01561   TQLabel      *label;
01562 
01563   // "Use custom fonts" checkbox, followed by <hr>
01564   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
01565   mCustomFontCheck = new TQCheckBox( i18n("&Use custom fonts"), this );
01566   vlay->addWidget( mCustomFontCheck );
01567   vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
01568   connect ( mCustomFontCheck, TQT_SIGNAL( stateChanged( int ) ),
01569             this, TQT_SLOT( slotEmitChanged( void ) ) );
01570 
01571   // "font location" combo box and label:
01572   hlay = new TQHBoxLayout( vlay ); // inherites spacing
01573   mFontLocationCombo = new TQComboBox( false, this );
01574   mFontLocationCombo->setEnabled( false ); // !mCustomFontCheck->isChecked()
01575 
01576   TQStringList fontDescriptions;
01577   for ( int i = 0 ; i < numFontNames ; i++ )
01578     fontDescriptions << i18n( fontNames[i].displayName );
01579   mFontLocationCombo->insertStringList( fontDescriptions );
01580 
01581   label = new TQLabel( mFontLocationCombo, i18n("Apply &to:"), this );
01582   label->setEnabled( false ); // since !mCustomFontCheck->isChecked()
01583   hlay->addWidget( label );
01584 
01585   hlay->addWidget( mFontLocationCombo );
01586   hlay->addStretch( 10 );
01587   vlay->addSpacing( KDialog::spacingHint() );
01588   mFontChooser = new KFontChooser( this, "font", false, TQStringList(),
01589                                    false, 4 );
01590   mFontChooser->setEnabled( false ); // since !mCustomFontCheck->isChecked()
01591   vlay->addWidget( mFontChooser );
01592   connect ( mFontChooser, TQT_SIGNAL( fontSelected( const TQFont& ) ),
01593             this, TQT_SLOT( slotEmitChanged( void ) ) );
01594 
01595 
01596   // {en,dis}able widgets depending on the state of mCustomFontCheck:
01597   connect( mCustomFontCheck, TQT_SIGNAL(toggled(bool)),
01598            label, TQT_SLOT(setEnabled(bool)) );
01599   connect( mCustomFontCheck, TQT_SIGNAL(toggled(bool)),
01600            mFontLocationCombo, TQT_SLOT(setEnabled(bool)) );
01601   connect( mCustomFontCheck, TQT_SIGNAL(toggled(bool)),
01602            mFontChooser, TQT_SLOT(setEnabled(bool)) );
01603   // load the right font settings into mFontChooser:
01604   connect( mFontLocationCombo, TQT_SIGNAL(activated(int) ),
01605            this, TQT_SLOT(slotFontSelectorChanged(int)) );
01606 }
01607 
01608 
01609 void AppearancePage::FontsTab::slotFontSelectorChanged( int index )
01610 {
01611   kdDebug(5006) << "slotFontSelectorChanged() called" << endl;
01612   if( index < 0 || index >= mFontLocationCombo->count() )
01613     return; // Should never happen, but it is better to check.
01614 
01615   // Save current fontselector setting before we install the new:
01616   if( mActiveFontIndex == 0 ) {
01617     mFont[0] = mFontChooser->font();
01618     // hardcode the family and size of "message body" dependant fonts:
01619     for ( int i = 0 ; i < numFontNames ; i++ )
01620       if ( !fontNames[i].enableFamilyAndSize ) {
01621         // ### shall we copy the font and set the save and re-set
01622         // {regular,italic,bold,bold italic} property or should we
01623         // copy only family and pointSize?
01624         mFont[i].setFamily( mFont[0].family() );
01625         mFont[i].setPointSize/*Float?*/( mFont[0].pointSize/*Float?*/() );
01626       }
01627   } else if ( mActiveFontIndex > 0 )
01628     mFont[ mActiveFontIndex ] = mFontChooser->font();
01629   mActiveFontIndex = index;
01630 
01631   // Disonnect so the "Apply" button is not activated by the change
01632   disconnect ( mFontChooser, TQT_SIGNAL( fontSelected( const TQFont& ) ),
01633             this, TQT_SLOT( slotEmitChanged( void ) ) );
01634 
01635   // Display the new setting:
01636   mFontChooser->setFont( mFont[index], fontNames[index].onlyFixed );
01637 
01638   connect ( mFontChooser, TQT_SIGNAL( fontSelected( const TQFont& ) ),
01639             this, TQT_SLOT( slotEmitChanged( void ) ) );
01640 
01641   // Disable Family and Size list if we have selected a quote font:
01642   mFontChooser->enableColumn( KFontChooser::FamilyList|KFontChooser::SizeList,
01643                               fontNames[ index ].enableFamilyAndSize );
01644 }
01645 
01646 void AppearancePage::FontsTab::doLoadOther() {
01647   KConfigGroup fonts( KMKernel::config(), "Fonts" );
01648 
01649   mFont[0] = KGlobalSettings::generalFont();
01650   TQFont fixedFont = KGlobalSettings::fixedFont();
01651   for ( int i = 0 ; i < numFontNames ; i++ )
01652     mFont[i] = fonts.readFontEntry( fontNames[i].configName,
01653       (fontNames[i].onlyFixed) ? &fixedFont : &mFont[0] );
01654 
01655   mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts", true ) );
01656   mFontLocationCombo->setCurrentItem( 0 );
01657   slotFontSelectorChanged( 0 );
01658 }
01659 
01660 void AppearancePage::FontsTab::installProfile( KConfig * profile ) {
01661   KConfigGroup fonts( profile, "Fonts" );
01662 
01663   // read fonts that are defined in the profile:
01664   bool needChange = false;
01665   for ( int i = 0 ; i < numFontNames ; i++ )
01666     if ( fonts.hasKey( fontNames[i].configName ) ) {
01667       needChange = true;
01668       mFont[i] = fonts.readFontEntry( fontNames[i].configName );
01669       kdDebug(5006) << "got font \"" << fontNames[i].configName
01670                 << "\" thusly: \"" << mFont[i].toString() << "\"" << endl;
01671     }
01672   if ( needChange && mFontLocationCombo->currentItem() > 0 )
01673     mFontChooser->setFont( mFont[ mFontLocationCombo->currentItem() ],
01674       fontNames[ mFontLocationCombo->currentItem() ].onlyFixed );
01675 
01676   if ( fonts.hasKey( "defaultFonts" ) )
01677     mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts" ) );
01678 }
01679 
01680 void AppearancePage::FontsTab::save() {
01681   KConfigGroup fonts( KMKernel::config(), "Fonts" );
01682 
01683   // read the current font (might have been modified)
01684   if ( mActiveFontIndex >= 0 )
01685     mFont[ mActiveFontIndex ] = mFontChooser->font();
01686 
01687   bool customFonts = mCustomFontCheck->isChecked();
01688   fonts.writeEntry( "defaultFonts", !customFonts );
01689   for ( int i = 0 ; i < numFontNames ; i++ )
01690     if ( customFonts || fonts.hasKey( fontNames[i].configName ) )
01691       // Don't write font info when we use default fonts, but write
01692       // if it's already there:
01693       fonts.writeEntry( fontNames[i].configName, mFont[i] );
01694 }
01695 
01696 TQString AppearancePage::ColorsTab::helpAnchor() const {
01697   return TQString::fromLatin1("configure-appearance-colors");
01698 }
01699 
01700 
01701 static const struct {
01702   const char * configName;
01703   const char * displayName;
01704 } colorNames[] = { // adjust setup() if you change this:
01705   { "BackgroundColor", I18N_NOOP("Composer Background") },
01706   { "AltBackgroundColor", I18N_NOOP("Alternative Background Color") },
01707   { "ForegroundColor", I18N_NOOP("Normal Text") },
01708   { "QuotedText1", I18N_NOOP("Quoted Text - First Level") },
01709   { "QuotedText2", I18N_NOOP("Quoted Text - Second Level") },
01710   { "QuotedText3", I18N_NOOP("Quoted Text - Third Level") },
01711   { "LinkColor", I18N_NOOP("Link") },
01712   { "FollowedColor", I18N_NOOP("Followed Link") },
01713   { "MisspelledColor", I18N_NOOP("Misspelled Words") },
01714   { "NewMessage", I18N_NOOP("New Message") },
01715   { "UnreadMessage", I18N_NOOP("Unread Message") },
01716   { "FlagMessage", I18N_NOOP("Important Message") },
01717   { "TodoMessage", I18N_NOOP("Todo Message") },
01718   { "PGPMessageEncr", I18N_NOOP("OpenPGP Message - Encrypted") },
01719   { "PGPMessageOkKeyOk", I18N_NOOP("OpenPGP Message - Valid Signature with Trusted Key") },
01720   { "PGPMessageOkKeyBad", I18N_NOOP("OpenPGP Message - Valid Signature with Untrusted Key") },
01721   { "PGPMessageWarn", I18N_NOOP("OpenPGP Message - Unchecked Signature") },
01722   { "PGPMessageErr", I18N_NOOP("OpenPGP Message - Bad Signature") },
01723   { "HTMLWarningColor", I18N_NOOP("Border Around Warning Prepending HTML Messages") },
01724   { "CloseToQuotaColor", I18N_NOOP("Folder Name and Size When Close to Quota") },
01725   { "ColorbarBackgroundPlain", I18N_NOOP("HTML Status Bar Background - No HTML Message") },
01726   { "ColorbarForegroundPlain", I18N_NOOP("HTML Status Bar Foreground - No HTML Message") },
01727   { "ColorbarBackgroundHTML",  I18N_NOOP("HTML Status Bar Background - HTML Message") },
01728   { "ColorbarForegroundHTML",  I18N_NOOP("HTML Status Bar Foreground - HTML Message") },
01729 };
01730 static const int numColorNames = sizeof colorNames / sizeof *colorNames;
01731 
01732 AppearancePageColorsTab::AppearancePageColorsTab( TQWidget * parent, const char * name )
01733   : ConfigModuleTab( parent, name )
01734 {
01735   // tmp. vars:
01736   TQVBoxLayout *vlay;
01737 
01738   // "use custom colors" check box
01739   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
01740   mCustomColorCheck = new TQCheckBox( i18n("&Use custom colors"), this );
01741   vlay->addWidget( mCustomColorCheck );
01742   connect( mCustomColorCheck, TQT_SIGNAL( stateChanged( int ) ),
01743            this, TQT_SLOT( slotEmitChanged( void ) ) );
01744 
01745   // color list box:
01746   mColorList = new ColorListBox( this );
01747   mColorList->setEnabled( false ); // since !mCustomColorCheck->isChecked()
01748   TQStringList modeList;
01749   for ( int i = 0 ; i < numColorNames ; i++ )
01750     mColorList->insertItem( new ColorListItem( i18n( colorNames[i].displayName ) ) );
01751   vlay->addWidget( mColorList, 1 );
01752 
01753   // "recycle colors" check box:
01754   mRecycleColorCheck =
01755     new TQCheckBox( i18n("Recycle colors on deep &quoting"), this );
01756   mRecycleColorCheck->setEnabled( false );
01757   vlay->addWidget( mRecycleColorCheck );
01758   connect( mRecycleColorCheck, TQT_SIGNAL( stateChanged( int ) ),
01759            this, TQT_SLOT( slotEmitChanged( void ) ) );
01760 
01761   // close to quota threshold
01762   TQHBoxLayout *hbox = new TQHBoxLayout(vlay);
01763   TQLabel *l = new TQLabel( i18n("Close to quota threshold"), this );
01764   hbox->addWidget( l );
01765   l->setEnabled( false );
01766   mCloseToQuotaThreshold = new TQSpinBox( 0, 100, 1, this );
01767   connect( mCloseToQuotaThreshold, TQT_SIGNAL( valueChanged( int ) ),
01768            this, TQT_SLOT( slotEmitChanged( void ) ) );
01769   mCloseToQuotaThreshold->setEnabled( false );
01770   mCloseToQuotaThreshold->setSuffix( i18n("%"));
01771   hbox->addWidget( mCloseToQuotaThreshold );
01772   hbox->addWidget( new TQWidget(this), 2 );
01773 
01774   // {en,dir}able widgets depending on the state of mCustomColorCheck:
01775   connect( mCustomColorCheck, TQT_SIGNAL(toggled(bool)),
01776            mColorList, TQT_SLOT(setEnabled(bool)) );
01777   connect( mCustomColorCheck, TQT_SIGNAL(toggled(bool)),
01778            mRecycleColorCheck, TQT_SLOT(setEnabled(bool)) );
01779   connect( mCustomColorCheck, TQT_SIGNAL(toggled(bool)),
01780            l, TQT_SLOT(setEnabled(bool)) );
01781   connect( mCustomColorCheck, TQT_SIGNAL(toggled(bool)),
01782        mCloseToQuotaThreshold, TQT_SLOT(setEnabled(bool)) );
01783 
01784   connect( mCustomColorCheck, TQT_SIGNAL( stateChanged( int ) ),
01785            this, TQT_SLOT( slotEmitChanged( void ) ) );
01786 }
01787 
01788 void AppearancePage::ColorsTab::doLoadOther() {
01789   KConfigGroup reader( KMKernel::config(), "Reader" );
01790 
01791   mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors", true ) );
01792   mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors", false ) );
01793   mCloseToQuotaThreshold->setValue( GlobalSettings::closeToQuotaThreshold() );
01794 
01795   static const TQColor defaultColor[ numColorNames ] = {
01796     kapp->palette().active().base(), // bg
01797     KGlobalSettings::alternateBackgroundColor(), // alt bg
01798     kapp->palette().active().text(), // fg
01799     TQColor( 0x00, 0x80, 0x00 ), // quoted l1
01800     TQColor( 0x00, 0x70, 0x00 ), // quoted l2
01801     TQColor( 0x00, 0x60, 0x00 ), // quoted l3
01802     KGlobalSettings::linkColor(), // link
01803     KGlobalSettings::visitedLinkColor(), // visited link
01804     Qt::red, // misspelled words
01805     Qt::red, // new msg
01806     Qt::blue, // unread mgs
01807     TQColor( 0x00, 0x7F, 0x00 ), // important msg
01808     Qt::blue, // todo mgs
01809     TQColor( 0x00, 0x80, 0xFF ), // light blue // pgp encrypted
01810     TQColor( 0x40, 0xFF, 0x40 ), // light green // pgp ok, trusted key
01811     TQColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp ok, untrusted key
01812     TQColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp unchk
01813     Qt::red, // pgp bad
01814     TQColor( 0xFF, 0x40, 0x40 ), // warning text color: light red
01815     Qt::red, // close to quota
01816     Qt::lightGray, // colorbar plain bg
01817     Qt::black,     // colorbar plain fg
01818     Qt::black,     // colorbar html  bg
01819     Qt::white,     // colorbar html  fg
01820   };
01821 
01822   for ( int i = 0 ; i < numColorNames ; i++ ) {
01823     mColorList->setColor( i,
01824       reader.readColorEntry( colorNames[i].configName, &defaultColor[i] ) );
01825   }
01826   connect( mColorList, TQT_SIGNAL( changed( ) ),
01827            this, TQT_SLOT( slotEmitChanged( void ) ) );
01828 }
01829 
01830 void AppearancePage::ColorsTab::installProfile( KConfig * profile ) {
01831   KConfigGroup reader( profile, "Reader" );
01832 
01833   if ( reader.hasKey( "defaultColors" ) )
01834     mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors" ) );
01835   if ( reader.hasKey( "RecycleQuoteColors" ) )
01836     mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors" ) );
01837 
01838   for ( int i = 0 ; i < numColorNames ; i++ )
01839     if ( reader.hasKey( colorNames[i].configName ) )
01840       mColorList->setColor( i, reader.readColorEntry( colorNames[i].configName ) );
01841 }
01842 
01843 void AppearancePage::ColorsTab::save() {
01844   KConfigGroup reader( KMKernel::config(), "Reader" );
01845 
01846   bool customColors = mCustomColorCheck->isChecked();
01847   reader.writeEntry( "defaultColors", !customColors );
01848 
01849   for ( int i = 0 ; i < numColorNames ; i++ )
01850     // Don't write color info when we use default colors, but write
01851     // if it's already there:
01852     if ( customColors || reader.hasKey( colorNames[i].configName ) )
01853       reader.writeEntry( colorNames[i].configName, mColorList->color(i) );
01854 
01855   reader.writeEntry( "RecycleQuoteColors", mRecycleColorCheck->isChecked() );
01856   GlobalSettings::setCloseToQuotaThreshold( mCloseToQuotaThreshold->value() );
01857 }
01858 
01859 TQString AppearancePage::LayoutTab::helpAnchor() const {
01860   return TQString::fromLatin1("configure-appearance-layout");
01861 }
01862 
01863 static const EnumConfigEntryItem folderListModes[] = {
01864   { "long", I18N_NOOP("Lon&g folder list") },
01865   { "short", I18N_NOOP("Shor&t folder list" ) }
01866 };
01867 static const EnumConfigEntry folderListMode = {
01868   "Geometry", "FolderList", I18N_NOOP("Folder List"),
01869   folderListModes, DIM(folderListModes), 0
01870 };
01871 
01872 
01873 static const EnumConfigEntryItem mimeTreeLocations[] = {
01874   { "top", I18N_NOOP("Abo&ve the message pane") },
01875   { "bottom", I18N_NOOP("&Below the message pane") }
01876 };
01877 static const EnumConfigEntry mimeTreeLocation = {
01878   "Reader", "MimeTreeLocation", I18N_NOOP("Message Structure Viewer Placement"),
01879   mimeTreeLocations, DIM(mimeTreeLocations), 1
01880 };
01881 
01882 static const EnumConfigEntryItem mimeTreeModes[] = {
01883   { "never", I18N_NOOP("Show &never") },
01884   { "smart", I18N_NOOP("Show only for non-plaintext &messages") },
01885   { "always", I18N_NOOP("Show alway&s") }
01886 };
01887 static const EnumConfigEntry mimeTreeMode = {
01888   "Reader", "MimeTreeMode", I18N_NOOP("Message Structure Viewer"),
01889   mimeTreeModes, DIM(mimeTreeModes), 1
01890 };
01891 
01892 
01893 static const EnumConfigEntryItem readerWindowModes[] = {
01894   { "hide", I18N_NOOP("&Do not show a message preview pane") },
01895   { "below", I18N_NOOP("Show the message preview pane belo&w the message list") },
01896   { "right", I18N_NOOP("Show the message preview pane ne&xt to the message list") }
01897 };
01898 static const EnumConfigEntry readerWindowMode = {
01899   "Geometry", "readerWindowMode", I18N_NOOP("Message Preview Pane"),
01900   readerWindowModes, DIM(readerWindowModes), 1
01901 };
01902 
01903 AppearancePageLayoutTab::AppearancePageLayoutTab( TQWidget * parent, const char * name )
01904   : ConfigModuleTab( parent, name )
01905 {
01906   // tmp. vars:
01907   TQVBoxLayout * vlay;
01908 
01909   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
01910 
01911   // "folder list" radio buttons:
01912   populateButtonGroup( mFolderListGroup = new TQHButtonGroup( this ), folderListMode );
01913   vlay->addWidget( mFolderListGroup );
01914   connect( mFolderListGroup, TQT_SIGNAL ( clicked( int ) ),
01915            this, TQT_SLOT( slotEmitChanged() ) );
01916 
01917   mFavoriteFolderViewCB = new TQCheckBox( i18n("Show favorite folder view"), this );
01918   connect( mFavoriteFolderViewCB, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
01919   vlay->addWidget( mFavoriteFolderViewCB );
01920 
01921   // "show reader window" radio buttons:
01922   populateButtonGroup( mReaderWindowModeGroup = new TQVButtonGroup( this ), readerWindowMode );
01923   vlay->addWidget( mReaderWindowModeGroup );
01924   connect( mReaderWindowModeGroup, TQT_SIGNAL ( clicked( int ) ),
01925            this, TQT_SLOT( slotEmitChanged() ) );
01926 
01927   // "Show MIME Tree" radio buttons:
01928   populateButtonGroup( mMIMETreeModeGroup = new TQVButtonGroup( this ), mimeTreeMode );
01929   vlay->addWidget( mMIMETreeModeGroup );
01930   connect( mMIMETreeModeGroup, TQT_SIGNAL ( clicked( int ) ),
01931            this, TQT_SLOT( slotEmitChanged() ) );
01932 
01933   // "MIME Tree Location" radio buttons:
01934   populateButtonGroup( mMIMETreeLocationGroup = new TQHButtonGroup( this ), mimeTreeLocation );
01935   vlay->addWidget( mMIMETreeLocationGroup );
01936   connect( mMIMETreeLocationGroup, TQT_SIGNAL ( clicked( int ) ),
01937            this, TQT_SLOT( slotEmitChanged() ) );
01938 
01939   vlay->addStretch( 10 ); // spacer
01940 }
01941 
01942 void AppearancePage::LayoutTab::doLoadOther() {
01943   const KConfigGroup reader( KMKernel::config(), "Reader" );
01944   const KConfigGroup geometry( KMKernel::config(), "Geometry" );
01945 
01946   loadWidget( mFolderListGroup, geometry, folderListMode );
01947   loadWidget( mMIMETreeLocationGroup, reader, mimeTreeLocation );
01948   loadWidget( mMIMETreeModeGroup, reader, mimeTreeMode );
01949   loadWidget( mReaderWindowModeGroup, geometry, readerWindowMode );
01950   mFavoriteFolderViewCB->setChecked( GlobalSettings::self()->enableFavoriteFolderView() );
01951 }
01952 
01953 void AppearancePage::LayoutTab::installProfile( KConfig * profile ) {
01954   const KConfigGroup reader( profile, "Reader" );
01955   const KConfigGroup geometry( profile, "Geometry" );
01956 
01957   loadProfile( mFolderListGroup, geometry, folderListMode );
01958   loadProfile( mMIMETreeLocationGroup, reader, mimeTreeLocation );
01959   loadProfile( mMIMETreeModeGroup, reader, mimeTreeMode );
01960   loadProfile( mReaderWindowModeGroup, geometry, readerWindowMode );
01961 }
01962 
01963 void AppearancePage::LayoutTab::save() {
01964   KConfigGroup reader( KMKernel::config(), "Reader" );
01965   KConfigGroup geometry( KMKernel::config(), "Geometry" );
01966 
01967   saveButtonGroup( mFolderListGroup, geometry, folderListMode );
01968   saveButtonGroup( mMIMETreeLocationGroup, reader, mimeTreeLocation );
01969   saveButtonGroup( mMIMETreeModeGroup, reader, mimeTreeMode );
01970   saveButtonGroup( mReaderWindowModeGroup, geometry, readerWindowMode );
01971   GlobalSettings::self()->setEnableFavoriteFolderView( mFavoriteFolderViewCB->isChecked() );
01972 }
01973 
01974 //
01975 // Appearance Message List
01976 //
01977 
01978 TQString AppearancePage::HeadersTab::helpAnchor() const {
01979   return TQString::fromLatin1("configure-appearance-headers");
01980 }
01981 
01982 static const struct {
01983   const char * displayName;
01984   DateFormatter::FormatType dateDisplay;
01985 } dateDisplayConfig[] = {
01986   { I18N_NOOP("Sta&ndard format (%1)"), KMime::DateFormatter::CTime },
01987   { I18N_NOOP("Locali&zed format (%1)"), KMime::DateFormatter::Localized },
01988   { I18N_NOOP("Fancy for&mat (%1)"), KMime::DateFormatter::Fancy },
01989   { I18N_NOOP("C&ustom format (Shift+F1 for help):"),
01990     KMime::DateFormatter::Custom }
01991 };
01992 static const int numDateDisplayConfig =
01993   sizeof dateDisplayConfig / sizeof *dateDisplayConfig;
01994 
01995 AppearancePageHeadersTab::AppearancePageHeadersTab( TQWidget * parent, const char * name )
01996   : ConfigModuleTab( parent, name ),
01997     mCustomDateFormatEdit( 0 )
01998 {
01999   // tmp. vars:
02000   TQButtonGroup * group;
02001   TQRadioButton * radio;
02002 
02003   TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
02004 
02005   // "General Options" group:
02006   group = new TQVButtonGroup( i18n( "General Options" ), this );
02007   group->layout()->setSpacing( KDialog::spacingHint() );
02008 
02009   mMessageSizeCheck = new TQCheckBox( i18n("Display messa&ge sizes"), group );
02010 
02011   mCryptoIconsCheck = new TQCheckBox( i18n( "Show crypto &icons" ), group );
02012 
02013   mAttachmentCheck = new TQCheckBox( i18n("Show attachment icon"), group );
02014 
02015   mNestedMessagesCheck =
02016     new TQCheckBox( i18n("&Threaded message list"), group );
02017 
02018   connect( mMessageSizeCheck, TQT_SIGNAL( stateChanged( int ) ),
02019            this, TQT_SLOT( slotEmitChanged( void ) ) );
02020   connect( mAttachmentCheck, TQT_SIGNAL( stateChanged( int ) ),
02021            this, TQT_SLOT( slotEmitChanged( void ) ) );
02022   connect( mCryptoIconsCheck, TQT_SIGNAL( stateChanged( int ) ),
02023            this, TQT_SLOT( slotEmitChanged( void ) ) );
02024   connect( mNestedMessagesCheck, TQT_SIGNAL( stateChanged( int ) ),
02025            this, TQT_SLOT( slotEmitChanged( void ) ) );
02026 
02027 
02028   vlay->addWidget( group );
02029 
02030   // "Message Header Threading Options" group:
02031   mNestingPolicy =
02032     new TQVButtonGroup( i18n("Threaded Message List Options"), this );
02033   mNestingPolicy->layout()->setSpacing( KDialog::spacingHint() );
02034 
02035   mNestingPolicy->insert(
02036     new TQRadioButton( i18n("Always &keep threads open"),
02037                       mNestingPolicy ), 0 );
02038   mNestingPolicy->insert(
02039     new TQRadioButton( i18n("Threads default to o&pen"),
02040                       mNestingPolicy ), 1 );
02041   mNestingPolicy->insert(
02042     new TQRadioButton( i18n("Threads default to closed"),
02043                       mNestingPolicy ), 2 );
02044   mNestingPolicy->insert(
02045     new TQRadioButton( i18n("Open threads that contain ne&w, unread "
02046                            "or important messages and open watched threads."),
02047                       mNestingPolicy ), 3 );
02048 
02049   vlay->addWidget( mNestingPolicy );
02050 
02051   connect( mNestingPolicy, TQT_SIGNAL( clicked( int ) ),
02052            this, TQT_SLOT( slotEmitChanged( void ) ) );
02053 
02054   // "Date Display" group:
02055   mDateDisplay = new TQVButtonGroup( i18n("Date Display"), this );
02056   mDateDisplay->layout()->setSpacing( KDialog::spacingHint() );
02057 
02058   for ( int i = 0 ; i < numDateDisplayConfig ; i++ ) {
02059     TQString buttonLabel = i18n(dateDisplayConfig[i].displayName);
02060     if ( buttonLabel.contains("%1") )
02061       buttonLabel = buttonLabel.arg( DateFormatter::formatCurrentDate( dateDisplayConfig[i].dateDisplay ) );
02062     radio = new TQRadioButton( buttonLabel, mDateDisplay );
02063     mDateDisplay->insert( radio, i );
02064     if ( dateDisplayConfig[i].dateDisplay == DateFormatter::Custom ) {
02065       mCustomDateFormatEdit = new KLineEdit( mDateDisplay );
02066       mCustomDateFormatEdit->setEnabled( false );
02067       connect( radio, TQT_SIGNAL(toggled(bool)),
02068                mCustomDateFormatEdit, TQT_SLOT(setEnabled(bool)) );
02069       connect( mCustomDateFormatEdit, TQT_SIGNAL(textChanged(const TQString&)),
02070                this, TQT_SLOT(slotEmitChanged(void)) );
02071       TQString customDateWhatsThis =
02072         i18n("<qt><p><strong>These expressions may be used for the date:"
02073              "</strong></p>"
02074              "<ul>"
02075              "<li>d - the day as a number without a leading zero (1-31)</li>"
02076              "<li>dd - the day as a number with a leading zero (01-31)</li>"
02077              "<li>ddd - the abbreviated day name (Mon - Sun)</li>"
02078              "<li>dddd - the long day name (Monday - Sunday)</li>"
02079              "<li>M - the month as a number without a leading zero (1-12)</li>"
02080              "<li>MM - the month as a number with a leading zero (01-12)</li>"
02081              "<li>MMM - the abbreviated month name (Jan - Dec)</li>"
02082              "<li>MMMM - the long month name (January - December)</li>"
02083              "<li>yy - the year as a two digit number (00-99)</li>"
02084              "<li>yyyy - the year as a four digit number (0000-9999)</li>"
02085              "</ul>"
02086              "<p><strong>These expressions may be used for the time:"
02087              "</string></p> "
02088              "<ul>"
02089              "<li>h - the hour without a leading zero (0-23 or 1-12 if AM/PM display)</li>"
02090              "<li>hh - the hour with a leading zero (00-23 or 01-12 if AM/PM display)</li>"
02091              "<li>m - the minutes without a leading zero (0-59)</li>"
02092              "<li>mm - the minutes with a leading zero (00-59)</li>"
02093              "<li>s - the seconds without a leading zero (0-59)</li>"
02094              "<li>ss - the seconds with a leading zero (00-59)</li>"
02095              "<li>z - the milliseconds without leading zeroes (0-999)</li>"
02096              "<li>zzz - the milliseconds with leading zeroes (000-999)</li>"
02097              "<li>AP - switch to AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</li>"
02098              "<li>ap - switch to AM/PM display. ap will be replaced by either \"am\" or \"pm\".</li>"
02099              "<li>Z - time zone in numeric form (-0500)</li>"
02100              "</ul>"
02101              "<p><strong>All other input characters will be ignored."
02102              "</strong></p></qt>");
02103       TQWhatsThis::add( mCustomDateFormatEdit, customDateWhatsThis );
02104       TQWhatsThis::add( radio, customDateWhatsThis );
02105     }
02106   } // end for loop populating mDateDisplay
02107 
02108   vlay->addWidget( mDateDisplay );
02109   connect( mDateDisplay, TQT_SIGNAL( clicked( int ) ),
02110            this, TQT_SLOT( slotEmitChanged( void ) ) );
02111 
02112 
02113   vlay->addStretch( 10 ); // spacer
02114 }
02115 
02116 void AppearancePage::HeadersTab::doLoadOther() {
02117   KConfigGroup general( KMKernel::config(), "General" );
02118   KConfigGroup geometry( KMKernel::config(), "Geometry" );
02119 
02120   // "General Options":
02121   mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages", false ) );
02122   mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize", false ) );
02123   mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons", false ) );
02124   mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon", true ) );
02125 
02126   // "Message Header Threading Options":
02127   int num = geometry.readNumEntry( "nestingPolicy", 3 );
02128   if ( num < 0 || num > 3 ) num = 3;
02129   mNestingPolicy->setButton( num );
02130 
02131   // "Date Display":
02132   setDateDisplay( general.readNumEntry( "dateFormat", DateFormatter::Fancy ),
02133                   general.readEntry( "customDateFormat" ) );
02134 }
02135 
02136 void AppearancePage::HeadersTab::setDateDisplay( int num, const TQString & format ) {
02137   DateFormatter::FormatType dateDisplay =
02138     static_cast<DateFormatter::FormatType>( num );
02139 
02140   // special case: needs text for the line edit:
02141   if ( dateDisplay == DateFormatter::Custom )
02142     mCustomDateFormatEdit->setText( format );
02143 
02144   for ( int i = 0 ; i < numDateDisplayConfig ; i++ )
02145     if ( dateDisplay == dateDisplayConfig[i].dateDisplay ) {
02146       mDateDisplay->setButton( i );
02147       return;
02148     }
02149   // fell through since none found:
02150   mDateDisplay->setButton( numDateDisplayConfig - 2 ); // default
02151 }
02152 
02153 void AppearancePage::HeadersTab::installProfile( KConfig * profile ) {
02154   KConfigGroup general( profile, "General" );
02155   KConfigGroup geometry( profile, "Geometry" );
02156 
02157   if ( geometry.hasKey( "nestedMessages" ) )
02158     mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages" ) );
02159   if ( general.hasKey( "showMessageSize" ) )
02160     mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize" ) );
02161 
02162   if( general.hasKey( "showCryptoIcons" ) )
02163     mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons" ) );
02164   if ( general.hasKey( "showAttachmentIcon" ) )
02165     mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon" ) );
02166 
02167   if ( geometry.hasKey( "nestingPolicy" ) ) {
02168     int num = geometry.readNumEntry( "nestingPolicy" );
02169     if ( num < 0 || num > 3 ) num = 3;
02170     mNestingPolicy->setButton( num );
02171   }
02172 
02173   if ( general.hasKey( "dateFormat" ) )
02174     setDateDisplay( general.readNumEntry( "dateFormat" ),
02175                    general.readEntry( "customDateFormat" ) );
02176 }
02177 
02178 void AppearancePage::HeadersTab::save() {
02179   KConfigGroup general( KMKernel::config(), "General" );
02180   KConfigGroup geometry( KMKernel::config(), "Geometry" );
02181 
02182   if ( geometry.readBoolEntry( "nestedMessages", false )
02183        != mNestedMessagesCheck->isChecked() ) {
02184     int result = KMessageBox::warningContinueCancel( this,
02185                    i18n("Changing the global threading setting will override "
02186                         "all folder specific values."),
02187                    TQString::null, KStdGuiItem::cont(), "threadOverride" );
02188     if ( result == KMessageBox::Continue ) {
02189       geometry.writeEntry( "nestedMessages", mNestedMessagesCheck->isChecked() );
02190       // remove all threadMessagesOverride keys from all [Folder-*] groups:
02191       TQStringList groups = KMKernel::config()->groupList().grep( TQRegExp("^Folder-") );
02192       kdDebug(5006) << "groups.count() == " << groups.count() << endl;
02193       for ( TQStringList::const_iterator it = groups.begin() ; it != groups.end() ; ++it ) {
02194         KConfigGroup group( KMKernel::config(), *it );
02195         group.deleteEntry( "threadMessagesOverride" );
02196       }
02197     }
02198   }
02199 
02200   geometry.writeEntry( "nestingPolicy",
02201                        mNestingPolicy->id( mNestingPolicy->selected() ) );
02202   general.writeEntry( "showMessageSize", mMessageSizeCheck->isChecked() );
02203   general.writeEntry( "showCryptoIcons", mCryptoIconsCheck->isChecked() );
02204   general.writeEntry( "showAttachmentIcon", mAttachmentCheck->isChecked() );
02205 
02206   int dateDisplayID = mDateDisplay->id( mDateDisplay->selected() );
02207   // check bounds:
02208   assert( dateDisplayID >= 0 ); assert( dateDisplayID < numDateDisplayConfig );
02209   general.writeEntry( "dateFormat",
02210                       dateDisplayConfig[ dateDisplayID ].dateDisplay );
02211   general.writeEntry( "customDateFormat", mCustomDateFormatEdit->text() );
02212 }
02213 
02214 
02215 //
02216 // Message Window
02217 //
02218 
02219 
02220 static const BoolConfigEntry closeAfterReplyOrForward = {
02221   "Reader", "CloseAfterReplyOrForward", I18N_NOOP("Close message window after replying or forwarding"), false
02222 };
02223 
02224 static const BoolConfigEntry showColorbarMode = {
02225   "Reader", "showColorbar", I18N_NOOP("Show HTML stat&us bar"), false
02226 };
02227 
02228 static const BoolConfigEntry showSpamStatusMode = {
02229   "Reader", "showSpamStatus", I18N_NOOP("Show s&pam status in fancy headers"), true
02230 };
02231 
02232 static const BoolConfigEntry showEmoticons = {
02233   "Reader", "ShowEmoticons", I18N_NOOP("Replace smileys by emoticons"), true
02234 };
02235 
02236 static const BoolConfigEntry shrinkQuotes = {
02237   "Reader", "ShrinkQuotes", I18N_NOOP("Use smaller font for quoted text"), false
02238 };
02239 
02240 static const BoolConfigEntry showExpandQuotesMark= {
02241   "Reader", "ShowExpandQuotesMark", I18N_NOOP("Show expand/collapse quote marks"), false
02242 };
02243 
02244 static const BoolConfigEntry showCurrentTime = {
02245   "Reader", "ShowCurrentTime", I18N_NOOP("Show current sender time"), true
02246 };
02247 
02248 TQString AppearancePage::ReaderTab::helpAnchor() const {
02249   return TQString::fromLatin1("configure-appearance-reader");
02250 }
02251 
02252 AppearancePageReaderTab::AppearancePageReaderTab( TQWidget * parent,
02253                                                   const char * name )
02254   : ConfigModuleTab( parent, name )
02255 {
02256   TQVBoxLayout *vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
02257 
02258   // "close message window after replying or forwarding" checkbox
02259   populateCheckBox( mCloseAfterReplyOrForwardCheck = new TQCheckBox( this ),
02260                     closeAfterReplyOrForward );
02261   TQToolTip::add( mCloseAfterReplyOrForwardCheck,
02262                  i18n( "Close the standalone message window after replying or forwarding the message" ) );
02263   vlay->addWidget( mCloseAfterReplyOrForwardCheck );
02264   connect( mCloseAfterReplyOrForwardCheck, TQT_SIGNAL ( stateChanged( int ) ),
02265            this, TQT_SLOT( slotEmitChanged() ) );
02266 
02267   // "show colorbar" check box:
02268   populateCheckBox( mShowColorbarCheck = new TQCheckBox( this ), showColorbarMode );
02269   vlay->addWidget( mShowColorbarCheck );
02270   connect( mShowColorbarCheck, TQT_SIGNAL ( stateChanged( int ) ),
02271            this, TQT_SLOT( slotEmitChanged() ) );
02272 
02273   // "show spam status" check box;
02274   populateCheckBox( mShowSpamStatusCheck = new TQCheckBox( this ), showSpamStatusMode );
02275   vlay->addWidget( mShowSpamStatusCheck );
02276   connect( mShowSpamStatusCheck, TQT_SIGNAL ( stateChanged( int ) ),
02277            this, TQT_SLOT( slotEmitChanged() ) );
02278 
02279   // "replace smileys by emoticons" check box;
02280   populateCheckBox( mShowEmoticonsCheck = new TQCheckBox( this ), showEmoticons );
02281   vlay->addWidget( mShowEmoticonsCheck );
02282   connect( mShowEmoticonsCheck, TQT_SIGNAL ( stateChanged( int ) ),
02283            this, TQT_SLOT( slotEmitChanged() ) );
02284 
02285   // "Use smaller font for quoted text" check box
02286   mShrinkQuotesCheck = new TQCheckBox( i18n( shrinkQuotes.desc ), this,
02287                                       "kcfg_ShrinkQuotes" );
02288   vlay->addWidget( mShrinkQuotesCheck );
02289   connect( mShrinkQuotesCheck, TQT_SIGNAL( stateChanged( int ) ),
02290            this, TQT_SLOT( slotEmitChanged() ) );
02291 
02292   // "Show expand/collaps quote marks" check box;
02293   TQHBoxLayout *hlay= new TQHBoxLayout( vlay ); // inherits spacing
02294   populateCheckBox( mShowExpandQuotesMark= new TQCheckBox( this ), showExpandQuotesMark);
02295   hlay->addWidget( mShowExpandQuotesMark);
02296   connect( mShowExpandQuotesMark, TQT_SIGNAL ( stateChanged( int ) ),
02297            this, TQT_SLOT( slotEmitChanged() ) );
02298 
02299   hlay->addStretch( 1 );
02300   mCollapseQuoteLevelSpin = new KIntSpinBox( 0/*min*/,10/*max*/,1/*step*/,
02301       3/*init*/,10/*base*/,this );
02302 
02303   TQLabel *label = new TQLabel( mCollapseQuoteLevelSpin,
02304            GlobalSettings::self()->collapseQuoteLevelSpinItem()->label(), this );
02305 
02306   hlay->addWidget( label );
02307 
02308   mCollapseQuoteLevelSpin->setEnabled( false ); //since !mShowExpandQuotesMark->isCheckec()
02309   connect(  mCollapseQuoteLevelSpin, TQT_SIGNAL( valueChanged( int ) ),
02310       this, TQT_SLOT( slotEmitChanged( void ) ) );
02311   hlay->addWidget( mCollapseQuoteLevelSpin);
02312 
02313   connect( mShowExpandQuotesMark, TQT_SIGNAL( toggled( bool ) ),
02314       mCollapseQuoteLevelSpin, TQT_SLOT( setEnabled( bool ) ) );
02315 
02316   // Fallback Character Encoding
02317   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02318   mCharsetCombo = new TQComboBox( this );
02319   mCharsetCombo->insertStringList( KMMsgBase::supportedEncodings( false ) );
02320 
02321   connect( mCharsetCombo, TQT_SIGNAL( activated( int ) ),
02322            this, TQT_SLOT( slotEmitChanged( void ) ) );
02323 
02324   TQString fallbackCharsetWhatsThis =
02325     i18n( GlobalSettings::self()->fallbackCharacterEncodingItem()->whatsThis().utf8() );
02326   TQWhatsThis::add( mCharsetCombo, fallbackCharsetWhatsThis );
02327 
02328   label = new TQLabel( i18n("Fallback ch&aracter encoding:"), this );
02329   label->setBuddy( mCharsetCombo );
02330 
02331   hlay->addWidget( label );
02332   hlay->addWidget( mCharsetCombo );
02333 
02334   // Override Character Encoding
02335   TQHBoxLayout *hlay2 = new TQHBoxLayout( vlay ); // inherits spacing
02336   mOverrideCharsetCombo = new TQComboBox( this );
02337   TQStringList encodings = KMMsgBase::supportedEncodings( false );
02338   encodings.prepend( i18n( "Auto" ) );
02339   mOverrideCharsetCombo->insertStringList( encodings );
02340   mOverrideCharsetCombo->setCurrentItem(0);
02341 
02342   connect( mOverrideCharsetCombo, TQT_SIGNAL( activated( int ) ),
02343            this, TQT_SLOT( slotEmitChanged( void ) ) );
02344 
02345   TQString overrideCharsetWhatsThis =
02346     i18n( GlobalSettings::self()->overrideCharacterEncodingItem()->whatsThis().utf8() );
02347   TQWhatsThis::add( mOverrideCharsetCombo, overrideCharsetWhatsThis );
02348 
02349   label = new TQLabel( i18n("&Override character encoding:"), this );
02350   label->setBuddy( mOverrideCharsetCombo );
02351 
02352   hlay2->addWidget( label );
02353   hlay2->addWidget( mOverrideCharsetCombo );
02354 
02355   populateCheckBox( mShowCurrentTimeCheck = new TQCheckBox( this ), showCurrentTime );
02356   vlay->addWidget( mShowCurrentTimeCheck );
02357   connect( mShowCurrentTimeCheck, TQT_SIGNAL ( stateChanged( int ) ),
02358            this, TQT_SLOT( slotEmitChanged() ) );
02359 
02360   vlay->addStretch( 100 ); // spacer
02361 }
02362 
02363 
02364 void AppearancePage::ReaderTab::readCurrentFallbackCodec()
02365 {
02366   TQStringList encodings = KMMsgBase::supportedEncodings( false );
02367   TQStringList::ConstIterator it( encodings.begin() );
02368   TQStringList::ConstIterator end( encodings.end() );
02369   TQString currentEncoding = GlobalSettings::self()->fallbackCharacterEncoding();
02370   currentEncoding = currentEncoding.replace( "iso ", "iso-", false );
02372   int i = 0;
02373   int indexOfLatin9 = 0;
02374   bool found = false;
02375   for( ; it != end; ++it)
02376   {
02377     const TQString encoding = KGlobal::charsets()->encodingForName(*it);
02378     if ( encoding == "iso-8859-15" )
02379         indexOfLatin9 = i;
02380     if( encoding == currentEncoding )
02381     {
02382       mCharsetCombo->setCurrentItem( i );
02383       found = true;
02384       break;
02385     }
02386     i++;
02387   }
02388   if ( !found ) // nothing matched, use latin9
02389     mCharsetCombo->setCurrentItem( indexOfLatin9 );
02390 }
02391 
02392 void AppearancePage::ReaderTab::readCurrentOverrideCodec()
02393 {
02394   const TQString &currentOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
02395   if ( currentOverrideEncoding.isEmpty() ) {
02396     mOverrideCharsetCombo->setCurrentItem( 0 );
02397     return;
02398   }
02399   TQStringList encodings = KMMsgBase::supportedEncodings( false );
02400   encodings.prepend( i18n( "Auto" ) );
02401   TQStringList::Iterator it( encodings.begin() );
02402   TQStringList::Iterator end( encodings.end() );
02403   uint i = 0;
02404   for( ; it != end; ++it)
02405   {
02406     if( KGlobal::charsets()->encodingForName(*it) == currentOverrideEncoding )
02407     {
02408       mOverrideCharsetCombo->setCurrentItem( i );
02409       break;
02410     }
02411     i++;
02412   }
02413   if ( i == encodings.size() ) {
02414     // the current value of overrideCharacterEncoding is an unknown encoding => reset to Auto
02415     kdWarning(5006) << "Unknown override character encoding \"" << currentOverrideEncoding
02416                     << "\". Resetting to Auto." << endl;
02417     mOverrideCharsetCombo->setCurrentItem( 0 );
02418     GlobalSettings::self()->setOverrideCharacterEncoding( TQString::null );
02419   }
02420 }
02421 
02422 void AppearancePage::ReaderTab::doLoadFromGlobalSettings()
02423 {
02424   mCloseAfterReplyOrForwardCheck->setChecked( GlobalSettings::self()->closeAfterReplyOrForward() );
02425   mShowEmoticonsCheck->setChecked( GlobalSettings::self()->showEmoticons() );
02426   mShrinkQuotesCheck->setChecked( GlobalSettings::self()->shrinkQuotes() );
02427   mShowExpandQuotesMark->setChecked( GlobalSettings::self()->showExpandQuotesMark() );
02428   mCollapseQuoteLevelSpin->setValue( GlobalSettings::self()->collapseQuoteLevelSpin() );
02429   readCurrentFallbackCodec();
02430   readCurrentOverrideCodec();
02431   mShowCurrentTimeCheck->setChecked( GlobalSettings::self()->showCurrentTime() );
02432 }
02433 
02434 void AppearancePage::ReaderTab::doLoadOther()
02435 {
02436   const KConfigGroup reader( KMKernel::config(), "Reader" );
02437   loadWidget( mShowColorbarCheck, reader, showColorbarMode );
02438   loadWidget( mShowSpamStatusCheck, reader, showSpamStatusMode );
02439 }
02440 
02441 
02442 void AppearancePage::ReaderTab::save() {
02443   KConfigGroup reader( KMKernel::config(), "Reader" );
02444   saveCheckBox( mShowColorbarCheck, reader, showColorbarMode );
02445   saveCheckBox( mShowSpamStatusCheck, reader, showSpamStatusMode );
02446   GlobalSettings::self()->setCloseAfterReplyOrForward( mCloseAfterReplyOrForwardCheck->isChecked() );
02447   GlobalSettings::self()->setShowEmoticons( mShowEmoticonsCheck->isChecked() );
02448   GlobalSettings::self()->setShrinkQuotes( mShrinkQuotesCheck->isChecked() );
02449   GlobalSettings::self()->setShowExpandQuotesMark( mShowExpandQuotesMark->isChecked() );
02450 
02451   GlobalSettings::self()->setCollapseQuoteLevelSpin( mCollapseQuoteLevelSpin->value() );
02452   GlobalSettings::self()->setFallbackCharacterEncoding(
02453       KGlobal::charsets()->encodingForName( mCharsetCombo->currentText() ) );
02454   GlobalSettings::self()->setOverrideCharacterEncoding(
02455       mOverrideCharsetCombo->currentItem() == 0 ?
02456         TQString() :
02457         KGlobal::charsets()->encodingForName( mOverrideCharsetCombo->currentText() ) );
02458   GlobalSettings::self()->setShowCurrentTime( mShowCurrentTimeCheck->isChecked() );
02459 }
02460 
02461 
02462 void AppearancePage::ReaderTab::installProfile( KConfig * /* profile */ ) {
02463   const KConfigGroup reader( KMKernel::config(), "Reader" );
02464   loadProfile( mCloseAfterReplyOrForwardCheck, reader, closeAfterReplyOrForward );
02465   loadProfile( mShowColorbarCheck, reader, showColorbarMode );
02466   loadProfile( mShowSpamStatusCheck, reader, showSpamStatusMode );
02467   loadProfile( mShowEmoticonsCheck, reader, showEmoticons );
02468   loadProfile( mShrinkQuotesCheck, reader, shrinkQuotes );
02469   loadProfile( mShowExpandQuotesMark, reader, showExpandQuotesMark);
02470   loadProfile( mShowCurrentTimeCheck, reader, showCurrentTime );
02471 }
02472 
02473 
02474 TQString AppearancePage::SystemTrayTab::helpAnchor() const {
02475   return TQString::fromLatin1("configure-appearance-systemtray");
02476 }
02477 
02478 AppearancePageSystemTrayTab::AppearancePageSystemTrayTab( TQWidget * parent,
02479                                                           const char * name )
02480   : ConfigModuleTab( parent, name )
02481 {
02482   TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(),
02483                                         KDialog::spacingHint() );
02484 
02485   // "Enable system tray applet" check box
02486   mSystemTrayCheck = new TQCheckBox( i18n("Enable system tray icon"), this );
02487   vlay->addWidget( mSystemTrayCheck );
02488   connect( mSystemTrayCheck, TQT_SIGNAL( stateChanged( int ) ),
02489            this, TQT_SLOT( slotEmitChanged( void ) ) );
02490 
02491   // System tray modes
02492   mSystemTrayGroup = new TQVButtonGroup( i18n("System Tray Mode"), this );
02493   mSystemTrayGroup->layout()->setSpacing( KDialog::spacingHint() );
02494   vlay->addWidget( mSystemTrayGroup );
02495   connect( mSystemTrayGroup, TQT_SIGNAL( clicked( int ) ),
02496            this, TQT_SLOT( slotEmitChanged( void ) ) );
02497   connect( mSystemTrayCheck, TQT_SIGNAL( toggled( bool ) ),
02498            mSystemTrayGroup, TQT_SLOT( setEnabled( bool ) ) );
02499 
02500   mSystemTrayGroup->insert( new TQRadioButton( i18n("Always show KMail in system tray"), mSystemTrayGroup ),
02501                             GlobalSettings::EnumSystemTrayPolicy::ShowAlways );
02502 
02503   mSystemTrayGroup->insert( new TQRadioButton( i18n("Only show KMail in system tray if there are unread messages"), mSystemTrayGroup ),
02504                             GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread );
02505 
02506   vlay->addStretch( 10 ); // spacer
02507 }
02508 
02509 void AppearancePage::SystemTrayTab::doLoadFromGlobalSettings() {
02510   mSystemTrayCheck->setChecked( GlobalSettings::self()->systemTrayEnabled() );
02511   mSystemTrayGroup->setButton( GlobalSettings::self()->systemTrayPolicy() );
02512   mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
02513 }
02514 
02515 void AppearancePage::SystemTrayTab::installProfile( KConfig * profile ) {
02516   KConfigGroup general( profile, "General" );
02517 
02518   if ( general.hasKey( "SystemTrayEnabled" ) ) {
02519     mSystemTrayCheck->setChecked( general.readBoolEntry( "SystemTrayEnabled" ) );
02520   }
02521   if ( general.hasKey( "SystemTrayPolicy" ) ) {
02522     mSystemTrayGroup->setButton( general.readNumEntry( "SystemTrayPolicy" ) );
02523   }
02524   mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
02525 }
02526 
02527 void AppearancePage::SystemTrayTab::save() {
02528   GlobalSettings::self()->setSystemTrayEnabled( mSystemTrayCheck->isChecked() );
02529   GlobalSettings::self()->setSystemTrayPolicy( mSystemTrayGroup->id( mSystemTrayGroup->selected() ) );
02530 }
02531 
02532 
02533 // *************************************************************
02534 // *                                                           *
02535 // *                      ComposerPage                         *
02536 // *                                                           *
02537 // *************************************************************
02538 
02539 TQString ComposerPage::helpAnchor() const {
02540   return TQString::fromLatin1("configure-composer");
02541 }
02542 
02543 ComposerPage::ComposerPage( TQWidget * parent, const char * name )
02544   : ConfigModuleWithTabs( parent, name )
02545 {
02546   //
02547   // "General" tab:
02548   //
02549   mGeneralTab = new GeneralTab();
02550   addTab( mGeneralTab, i18n("&General") );
02551   addConfig( GlobalSettings::self(), mGeneralTab );
02552 
02553   //
02554   // "Phrases" tab:
02555   //
02556   // mPhrasesTab = new PhrasesTab();
02557   // addTab( mPhrasesTab, i18n("&Phrases") );
02558 
02559   //
02560   // "Templates" tab:
02561   //
02562   mTemplatesTab = new TemplatesTab();
02563   addTab( mTemplatesTab, i18n("&Templates") );
02564 
02565   //
02566   // "Custom Templates" tab:
02567   //
02568   mCustomTemplatesTab = new CustomTemplatesTab();
02569   addTab( mCustomTemplatesTab, i18n("&Custom Templates") );
02570 
02571   //
02572   // "Subject" tab:
02573   //
02574   mSubjectTab = new SubjectTab();
02575   addTab( mSubjectTab, i18n("&Subject") );
02576   addConfig( GlobalSettings::self(), mSubjectTab );
02577 
02578   //
02579   // "Charset" tab:
02580   //
02581   mCharsetTab = new CharsetTab();
02582   addTab( mCharsetTab, i18n("Cha&rset") );
02583 
02584   //
02585   // "Headers" tab:
02586   //
02587   mHeadersTab = new HeadersTab();
02588   addTab( mHeadersTab, i18n("H&eaders") );
02589 
02590   //
02591   // "Attachments" tab:
02592   //
02593   mAttachmentsTab = new AttachmentsTab();
02594   addTab( mAttachmentsTab, i18n("Config->Composer->Attachments", "A&ttachments") );
02595   load();
02596 }
02597 
02598 TQString ComposerPage::GeneralTab::helpAnchor() const {
02599   return TQString::fromLatin1("configure-composer-general");
02600 }
02601 
02602 ComposerPageGeneralTab::ComposerPageGeneralTab( TQWidget * parent, const char * name )
02603   : ConfigModuleTab( parent, name )
02604 {
02605   // tmp. vars:
02606   TQVBoxLayout *vlay;
02607   TQHBoxLayout *hlay;
02608   TQGroupBox   *group;
02609   TQLabel      *label;
02610   TQHBox       *hbox;
02611   TQString      msg;
02612 
02613   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
02614 
02615   // some check buttons...
02616   mAutoAppSignFileCheck = new TQCheckBox(
02617            GlobalSettings::self()->autoTextSignatureItem()->label(),
02618            this );
02619   vlay->addWidget( mAutoAppSignFileCheck );
02620   connect( mAutoAppSignFileCheck, TQT_SIGNAL( stateChanged(int) ),
02621            this, TQT_SLOT( slotEmitChanged( void ) ) );
02622 
02623   mTopQuoteCheck =
02624     new TQCheckBox( GlobalSettings::self()->prependSignatureItem()->label(), this );
02625   vlay->addWidget( mTopQuoteCheck);
02626   connect( mTopQuoteCheck, TQT_SIGNAL( stateChanged(int) ),
02627            this, TQT_SLOT( slotEmitChanged( void ) ) );
02628 
02629   mSmartQuoteCheck = new TQCheckBox(
02630            GlobalSettings::self()->smartQuoteItem()->label(),
02631            this, "kcfg_SmartQuote" );
02632   TQToolTip::add( mSmartQuoteCheck,
02633                  i18n( "When replying, add quote signs in front of all lines of the quoted text,\n"
02634                        "even when the line was created by adding an additional linebreak while\n"
02635                        "word-wrapping the text." ) );
02636   vlay->addWidget( mSmartQuoteCheck );
02637   connect( mSmartQuoteCheck, TQT_SIGNAL( stateChanged(int) ),
02638            this, TQT_SLOT( slotEmitChanged( void ) ) );
02639 
02640   mQuoteSelectionOnlyCheck = new TQCheckBox( GlobalSettings::self()->quoteSelectionOnlyItem()->label(),
02641                                             this, "kcfg_QuoteSelectionOnly" );
02642   TQToolTip::add( mQuoteSelectionOnlyCheck,
02643                  i18n( "When replying, only quote the selected text instead of the complete message "
02644                        "when there is text selected in the message window." ) );
02645   vlay->addWidget( mQuoteSelectionOnlyCheck );
02646   connect( mQuoteSelectionOnlyCheck, TQT_SIGNAL( stateChanged(int) ),
02647            this, TQT_SLOT( slotEmitChanged(void) ) );
02648 
02649   mStripSignatureCheck = new TQCheckBox( GlobalSettings::self()->stripSignatureItem()->label(),
02650                                         this, "kcfg_StripSignature" );
02651   vlay->addWidget( mStripSignatureCheck );
02652   connect( mStripSignatureCheck, TQT_SIGNAL( stateChanged(int) ),
02653            this, TQT_SLOT( slotEmitChanged( void ) ) );
02654 
02655   mAutoRequestMDNCheck = new TQCheckBox(
02656            GlobalSettings::self()->requestMDNItem()->label(),
02657            this, "kcfg_RequestMDN" );
02658   vlay->addWidget( mAutoRequestMDNCheck );
02659   connect( mAutoRequestMDNCheck, TQT_SIGNAL( stateChanged(int) ),
02660            this, TQT_SLOT( slotEmitChanged( void ) ) );
02661 
02662   mShowRecentAddressesInComposer = new TQCheckBox(
02663            GlobalSettings::self()->showRecentAddressesInComposerItem()->label(),
02664            this, "kcfg_ShowRecentAddressesInComposer" );
02665   vlay->addWidget( mShowRecentAddressesInComposer );
02666   connect( mShowRecentAddressesInComposer, TQT_SIGNAL( stateChanged(int) ),
02667            this, TQT_SLOT( slotEmitChanged( void ) ) );
02668 
02669   // a checkbox for "word wrap" and a spinbox for the column in
02670   // which to wrap:
02671   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02672   mWordWrapCheck = new TQCheckBox(
02673            GlobalSettings::self()->wordWrapItem()->label(),
02674            this, "kcfg_WordWrap" );
02675   hlay->addWidget( mWordWrapCheck );
02676   connect( mWordWrapCheck, TQT_SIGNAL( stateChanged(int) ),
02677            this, TQT_SLOT( slotEmitChanged( void ) ) );
02678 
02679   mWrapColumnSpin = new KIntSpinBox( 30/*min*/, 78/*max*/, 1/*step*/,
02680            78/*init*/, 10 /*base*/, this, "kcfg_LineWrapWidth" );
02681   mWrapColumnSpin->setEnabled( false ); // since !mWordWrapCheck->isChecked()
02682   connect( mWrapColumnSpin, TQT_SIGNAL( valueChanged(int) ),
02683            this, TQT_SLOT( slotEmitChanged( void ) ) );
02684 
02685   hlay->addWidget( mWrapColumnSpin );
02686   hlay->addStretch( 1 );
02687   // only enable the spinbox if the checkbox is checked:
02688   connect( mWordWrapCheck, TQT_SIGNAL(toggled(bool)),
02689            mWrapColumnSpin, TQT_SLOT(setEnabled(bool)) );
02690 
02691   // a checkbox for "too many recipient warning" and a spinbox for the recipient threshold
02692   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02693   mRecipientCheck = new TQCheckBox(
02694            GlobalSettings::self()->tooManyRecipientsItem()->label(),
02695            this, "kcfg_TooManyRecipients" );
02696   hlay->addWidget( mRecipientCheck );
02697   connect( mRecipientCheck, TQT_SIGNAL( stateChanged(int) ),
02698            this, TQT_SLOT( slotEmitChanged( void ) ) );
02699 
02700   TQString recipientCheckWhatsthis =
02701     i18n( GlobalSettings::self()->tooManyRecipientsItem()->whatsThis().utf8() );
02702   TQWhatsThis::add( mRecipientCheck, recipientCheckWhatsthis );
02703   TQToolTip::add( mRecipientCheck,
02704                  i18n( "Warn if too many recipients are specified" ) );
02705 
02706   mRecipientSpin = new KIntSpinBox( 1/*min*/, 100/*max*/, 1/*step*/,
02707            5/*init*/, 10 /*base*/, this, "kcfg_RecipientThreshold" );
02708   mRecipientSpin->setEnabled( false );
02709   connect( mRecipientSpin, TQT_SIGNAL( valueChanged(int) ),
02710            this, TQT_SLOT( slotEmitChanged( void ) ) );
02711 
02712   TQString recipientWhatsthis =
02713     i18n( GlobalSettings::self()->recipientThresholdItem()->whatsThis().utf8() );
02714   TQWhatsThis::add( mRecipientSpin, recipientWhatsthis );
02715   TQToolTip::add( mRecipientSpin,
02716                  i18n( "Warn if more than this many recipients are specified" ) );
02717 
02718 
02719   hlay->addWidget( mRecipientSpin );
02720   hlay->addStretch( 1 );
02721   // only enable the spinbox if the checkbox is checked:
02722   connect( mRecipientCheck, TQT_SIGNAL(toggled(bool)),
02723            mRecipientSpin, TQT_SLOT(setEnabled(bool)) );
02724 
02725 
02726   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02727   mAutoSave = new KIntSpinBox( 0, 60, 1, 1, 10, this, "kcfg_AutosaveInterval" );
02728   label = new TQLabel( mAutoSave,
02729            GlobalSettings::self()->autosaveIntervalItem()->label(), this );
02730   hlay->addWidget( label );
02731   hlay->addWidget( mAutoSave );
02732   mAutoSave->setSpecialValueText( i18n("No autosave") );
02733   mAutoSave->setSuffix( i18n(" min") );
02734   hlay->addStretch( 1 );
02735   connect( mAutoSave, TQT_SIGNAL( valueChanged(int) ),
02736            this, TQT_SLOT( slotEmitChanged( void ) ) );
02737 
02738   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02739   mForwardTypeCombo = new KComboBox( false, this );
02740   label = new TQLabel( mForwardTypeCombo,
02741                       i18n( "Default Forwarding Type:" ),
02742                       this );
02743   mForwardTypeCombo->insertStringList( TQStringList()
02744                                        << i18n( "Inline" )
02745                                        << i18n( "As Attachment" ) );
02746   hlay->addWidget( label );
02747   hlay->addWidget( mForwardTypeCombo );
02748   hlay->addStretch( 1 );
02749   connect( mForwardTypeCombo, TQT_SIGNAL(activated(int)),
02750            this, TQT_SLOT( slotEmitChanged( void ) ) );
02751 
02752   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02753   TQPushButton *completionOrderBtn = new TQPushButton( i18n( "Configure Completion Order" ), this );
02754   connect( completionOrderBtn, TQT_SIGNAL( clicked() ),
02755            this, TQT_SLOT( slotConfigureCompletionOrder() ) );
02756   hlay->addWidget( completionOrderBtn );
02757   hlay->addItem( new TQSpacerItem(0, 0) );
02758 
02759   // recent addresses
02760   hlay = new TQHBoxLayout( vlay ); // inherits spacing
02761   TQPushButton *recentAddressesBtn = new TQPushButton( i18n( "Edit Recent Addresses..." ), this );
02762   connect( recentAddressesBtn, TQT_SIGNAL( clicked() ),
02763            this, TQT_SLOT( slotConfigureRecentAddresses() ) );
02764   hlay->addWidget( recentAddressesBtn );
02765   hlay->addItem( new TQSpacerItem(0, 0) );
02766 
02767   // The "external editor" group:
02768   group = new TQVGroupBox( i18n("External Editor"), this );
02769   group->layout()->setSpacing( KDialog::spacingHint() );
02770 
02771   mExternalEditorCheck = new TQCheckBox(
02772            GlobalSettings::self()->useExternalEditorItem()->label(),
02773            group, "kcfg_UseExternalEditor" );
02774   connect( mExternalEditorCheck, TQT_SIGNAL( toggled( bool ) ),
02775            this, TQT_SLOT( slotEmitChanged( void ) ) );
02776 
02777   hbox = new TQHBox( group );
02778   label = new TQLabel( GlobalSettings::self()->externalEditorItem()->label(),
02779                    hbox );
02780   mEditorRequester = new KURLRequester( hbox, "kcfg_ExternalEditor" );
02781   connect( mEditorRequester, TQT_SIGNAL( urlSelected(const TQString&) ),
02782            this, TQT_SLOT( slotEmitChanged( void ) ) );
02783   connect( mEditorRequester, TQT_SIGNAL( textChanged(const TQString&) ),
02784            this, TQT_SLOT( slotEmitChanged( void ) ) );
02785 
02786   hbox->setStretchFactor( mEditorRequester, 1 );
02787   label->setBuddy( mEditorRequester );
02788   label->setEnabled( false ); // since !mExternalEditorCheck->isChecked()
02789   // ### FIXME: allow only executables (x-bit when available..)
02790   mEditorRequester->setFilter( "application/x-executable "
02791                                "application/x-shellscript "
02792                                "application/x-desktop" );
02793   mEditorRequester->setEnabled( false ); // !mExternalEditorCheck->isChecked()
02794   connect( mExternalEditorCheck, TQT_SIGNAL(toggled(bool)),
02795            label, TQT_SLOT(setEnabled(bool)) );
02796   connect( mExternalEditorCheck, TQT_SIGNAL(toggled(bool)),
02797            mEditorRequester, TQT_SLOT(setEnabled(bool)) );
02798 
02799   label = new TQLabel( i18n("<b>%f</b> will be replaced with the "
02800                            "filename to edit."), group );
02801   label->setEnabled( false ); // see above
02802   connect( mExternalEditorCheck, TQT_SIGNAL(toggled(bool)),
02803            label, TQT_SLOT(setEnabled(bool)) );
02804 
02805   vlay->addWidget( group );
02806   vlay->addStretch( 100 );
02807 }
02808 
02809 void ComposerPage::GeneralTab::doLoadFromGlobalSettings() {
02810   // various check boxes:
02811 
02812   mAutoAppSignFileCheck->setChecked(
02813            GlobalSettings::self()->autoTextSignature()=="auto" );
02814   mTopQuoteCheck->setChecked( GlobalSettings::self()->prependSignature() );
02815   mSmartQuoteCheck->setChecked( GlobalSettings::self()->smartQuote() );
02816   mQuoteSelectionOnlyCheck->setChecked( GlobalSettings::self()->quoteSelectionOnly() );
02817   mStripSignatureCheck->setChecked( GlobalSettings::self()->stripSignature() );
02818   mAutoRequestMDNCheck->setChecked( GlobalSettings::self()->requestMDN() );
02819   mWordWrapCheck->setChecked( GlobalSettings::self()->wordWrap() );
02820 
02821   mWrapColumnSpin->setValue( GlobalSettings::self()->lineWrapWidth() );
02822   mRecipientCheck->setChecked( GlobalSettings::self()->tooManyRecipients() );
02823   mRecipientSpin->setValue( GlobalSettings::self()->recipientThreshold() );
02824   mAutoSave->setValue( GlobalSettings::self()->autosaveInterval() );
02825   if ( GlobalSettings::self()->forwardingInlineByDefault() )
02826     mForwardTypeCombo->setCurrentItem( 0 );
02827   else
02828     mForwardTypeCombo->setCurrentItem( 1 );
02829 
02830   // editor group:
02831   mExternalEditorCheck->setChecked( GlobalSettings::self()->useExternalEditor() );
02832   mEditorRequester->setURL( GlobalSettings::self()->externalEditor() );
02833 }
02834 
02835 void ComposerPage::GeneralTab::installProfile( KConfig * profile ) {
02836   KConfigGroup composer( profile, "Composer" );
02837   KConfigGroup general( profile, "General" );
02838 
02839   if ( composer.hasKey( "signature" ) ) {
02840     bool state = composer.readBoolEntry("signature");
02841     mAutoAppSignFileCheck->setChecked( state );
02842   }
02843   if ( composer.hasKey( "prepend-signature" ) )
02844     mTopQuoteCheck->setChecked( composer.readBoolEntry( "prepend-signature" ) );
02845   if ( composer.hasKey( "smart-quote" ) )
02846     mSmartQuoteCheck->setChecked( composer.readBoolEntry( "smart-quote" ) );
02847   if ( composer.hasKey( "StripSignature" ) )
02848     mStripSignatureCheck->setChecked( composer.readBoolEntry( "StripSignature" ) );
02849   if ( composer.hasKey( "QuoteSelectionOnly" ) )
02850     mQuoteSelectionOnlyCheck->setChecked( composer.readBoolEntry( "QuoteSelectionOnly" ) );
02851   if ( composer.hasKey( "request-mdn" ) )
02852     mAutoRequestMDNCheck->setChecked( composer.readBoolEntry( "request-mdn" ) );
02853   if ( composer.hasKey( "word-wrap" ) )
02854     mWordWrapCheck->setChecked( composer.readBoolEntry( "word-wrap" ) );
02855   if ( composer.hasKey( "break-at" ) )
02856     mWrapColumnSpin->setValue( composer.readNumEntry( "break-at" ) );
02857   if ( composer.hasKey( "too-many-recipients" ) )
02858     mRecipientCheck->setChecked( composer.readBoolEntry( "too-many-recipients" ) );
02859   if ( composer.hasKey( "recipient-threshold" ) )
02860     mRecipientSpin->setValue( composer.readNumEntry( "recipient-threshold" ) );
02861   if ( composer.hasKey( "autosave" ) )
02862     mAutoSave->setValue( composer.readNumEntry( "autosave" ) );
02863 
02864   if ( general.hasKey( "use-external-editor" )
02865        && general.hasKey( "external-editor" ) ) {
02866     mExternalEditorCheck->setChecked( general.readBoolEntry( "use-external-editor" ) );
02867     mEditorRequester->setURL( general.readPathEntry( "external-editor" ) );
02868   }
02869 }
02870 
02871 void ComposerPage::GeneralTab::save() {
02872   GlobalSettings::self()->setAutoTextSignature(
02873          mAutoAppSignFileCheck->isChecked() ? "auto" : "manual" );
02874   GlobalSettings::self()->setPrependSignature( mTopQuoteCheck->isChecked());
02875   GlobalSettings::self()->setSmartQuote( mSmartQuoteCheck->isChecked() );
02876   GlobalSettings::self()->setQuoteSelectionOnly( mQuoteSelectionOnlyCheck->isChecked() );
02877   GlobalSettings::self()->setStripSignature( mStripSignatureCheck->isChecked() );
02878   GlobalSettings::self()->setRequestMDN( mAutoRequestMDNCheck->isChecked() );
02879   GlobalSettings::self()->setWordWrap( mWordWrapCheck->isChecked() );
02880 
02881   GlobalSettings::self()->setLineWrapWidth( mWrapColumnSpin->value() );
02882   GlobalSettings::self()->setTooManyRecipients( mRecipientCheck->isChecked() );
02883   GlobalSettings::self()->setRecipientThreshold( mRecipientSpin->value() );
02884   GlobalSettings::self()->setAutosaveInterval( mAutoSave->value() );
02885   GlobalSettings::self()->setForwardingInlineByDefault( mForwardTypeCombo->currentItem() == 0 );
02886 
02887   // editor group:
02888   GlobalSettings::self()->setUseExternalEditor( mExternalEditorCheck->isChecked() );
02889   GlobalSettings::self()->setExternalEditor( mEditorRequester->url() );
02890 }
02891 
02892 void ComposerPage::GeneralTab::slotConfigureRecentAddresses( )
02893 {
02894   KRecentAddress::RecentAddressDialog dlg( this );
02895   dlg.setAddresses( RecentAddresses::self( KMKernel::config() )->addresses() );
02896   if ( dlg.exec() ) {
02897     RecentAddresses::self( KMKernel::config() )->clear();
02898     const TQStringList &addrList = dlg.addresses();
02899     TQStringList::ConstIterator it;
02900     for ( it = addrList.constBegin(); it != addrList.constEnd(); ++it )
02901       RecentAddresses::self( KMKernel::config() )->add( *it );
02902   }
02903 }
02904 
02905 void ComposerPage::GeneralTab::slotConfigureCompletionOrder( )
02906 {
02907   KPIM::LdapSearch search;
02908   KPIM::CompletionOrderEditor editor( &search, this );
02909   editor.exec();
02910 }
02911 
02912 TQString ComposerPage::PhrasesTab::helpAnchor() const {
02913   return TQString::fromLatin1("configure-composer-phrases");
02914 }
02915 
02916 ComposerPagePhrasesTab::ComposerPagePhrasesTab( TQWidget * parent, const char * name )
02917   : ConfigModuleTab( parent, name )
02918 {
02919   // tmp. vars:
02920   TQGridLayout *glay;
02921   TQPushButton *button;
02922 
02923   glay = new TQGridLayout( this, 7, 3, KDialog::spacingHint() );
02924   glay->setMargin( KDialog::marginHint() );
02925   glay->setColStretch( 1, 1 );
02926   glay->setColStretch( 2, 1 );
02927   glay->setRowStretch( 7, 1 );
02928 
02929   // row 0: help text
02930   glay->addMultiCellWidget( new TQLabel( i18n("<qt>The following placeholders are "
02931                                              "supported in the reply phrases:<br>"
02932                                              "<b>%D</b>: date, <b>%S</b>: subject,<br>"
02933                                              "<b>%e</b>: sender's address, <b>%F</b>: sender's name, <b>%f</b>: sender's initials,<br>"
02934                                              "<b>%T</b>: recipient's name, <b>%t</b>: recipient's name and address,<br>"
02935                                              "<b>%C</b>: carbon copy names, <b>%c</b>: carbon copy names and addresses,<br>"
02936                                              "<b>%%</b>: percent sign, <b>%_</b>: space, "
02937                                              "<b>%L</b>: linebreak</qt>"), this ),
02938                             0, 0, 0, 2 ); // row 0; cols 0..2
02939 
02940   // row 1: label and language combo box:
02941   mPhraseLanguageCombo = new LanguageComboBox( false, this );
02942   glay->addWidget( new TQLabel( mPhraseLanguageCombo,
02943                                i18n("Lang&uage:"), this ), 1, 0 );
02944   glay->addMultiCellWidget( mPhraseLanguageCombo, 1, 1, 1, 2 );
02945   connect( mPhraseLanguageCombo, TQT_SIGNAL(activated(const TQString&)),
02946            this, TQT_SLOT(slotLanguageChanged(const TQString&)) );
02947 
02948   // row 2: "add..." and "remove" push buttons:
02949   button = new TQPushButton( i18n("A&dd..."), this );
02950   button->setAutoDefault( false );
02951   glay->addWidget( button, 2, 1 );
02952   mRemoveButton = new TQPushButton( i18n("Re&move"), this );
02953   mRemoveButton->setAutoDefault( false );
02954   mRemoveButton->setEnabled( false ); // combo doesn't contain anything...
02955   glay->addWidget( mRemoveButton, 2, 2 );
02956   connect( button, TQT_SIGNAL(clicked()),
02957            this, TQT_SLOT(slotNewLanguage()) );
02958   connect( mRemoveButton, TQT_SIGNAL(clicked()),
02959            this, TQT_SLOT(slotRemoveLanguage()) );
02960 
02961   // row 3: "reply to sender" line edit and label:
02962   mPhraseReplyEdit = new KLineEdit( this );
02963   connect( mPhraseReplyEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
02964            this, TQT_SLOT( slotEmitChanged( void ) ) );
02965   glay->addWidget( new TQLabel( mPhraseReplyEdit,
02966                                i18n("Reply to se&nder:"), this ), 3, 0 );
02967   glay->addMultiCellWidget( mPhraseReplyEdit, 3, 3, 1, 2 ); // cols 1..2
02968 
02969   // row 4: "reply to all" line edit and label:
02970   mPhraseReplyAllEdit = new KLineEdit( this );
02971   connect( mPhraseReplyAllEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
02972            this, TQT_SLOT( slotEmitChanged( void ) ) );
02973   glay->addWidget( new TQLabel( mPhraseReplyAllEdit,
02974                                i18n("Repl&y to all:"), this ), 4, 0 );
02975   glay->addMultiCellWidget( mPhraseReplyAllEdit, 4, 4, 1, 2 ); // cols 1..2
02976 
02977   // row 5: "forward" line edit and label:
02978   mPhraseForwardEdit = new KLineEdit( this );
02979   connect( mPhraseForwardEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
02980            this, TQT_SLOT( slotEmitChanged( void ) ) );
02981   glay->addWidget( new TQLabel( mPhraseForwardEdit,
02982                                i18n("&Forward:"), this ), 5, 0 );
02983   glay->addMultiCellWidget( mPhraseForwardEdit, 5, 5, 1, 2 ); // cols 1..2
02984 
02985   // row 6: "quote indicator" line edit and label:
02986   mPhraseIndentPrefixEdit = new KLineEdit( this );
02987   connect( mPhraseIndentPrefixEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
02988            this, TQT_SLOT( slotEmitChanged( void ) ) );
02989   glay->addWidget( new TQLabel( mPhraseIndentPrefixEdit,
02990                                i18n("&Quote indicator:"), this ), 6, 0 );
02991   glay->addMultiCellWidget( mPhraseIndentPrefixEdit, 6, 6, 1, 2 );
02992 
02993   // row 7: spacer
02994 }
02995 
02996 
02997 void ComposerPage::PhrasesTab::setLanguageItemInformation( int index ) {
02998   assert( 0 <= index && index < (int)mLanguageList.count() );
02999 
03000   LanguageItem &l = *mLanguageList.at( index );
03001 
03002   mPhraseReplyEdit->setText( l.mReply );
03003   mPhraseReplyAllEdit->setText( l.mReplyAll );
03004   mPhraseForwardEdit->setText( l.mForward );
03005   mPhraseIndentPrefixEdit->setText( l.mIndentPrefix );
03006 }
03007 
03008 void ComposerPage::PhrasesTab::saveActiveLanguageItem() {
03009   int index = mActiveLanguageItem;
03010   if (index == -1) return;
03011   assert( 0 <= index && index < (int)mLanguageList.count() );
03012 
03013   LanguageItem &l = *mLanguageList.at( index );
03014 
03015   l.mReply = mPhraseReplyEdit->text();
03016   l.mReplyAll = mPhraseReplyAllEdit->text();
03017   l.mForward = mPhraseForwardEdit->text();
03018   l.mIndentPrefix = mPhraseIndentPrefixEdit->text();
03019 }
03020 
03021 void ComposerPage::PhrasesTab::slotNewLanguage()
03022 {
03023   NewLanguageDialog dialog( mLanguageList, parentWidget(), "New", true );
03024   if ( dialog.exec() == TQDialog::Accepted ) slotAddNewLanguage( dialog.language() );
03025 }
03026 
03027 void ComposerPage::PhrasesTab::slotAddNewLanguage( const TQString& lang )
03028 {
03029   mPhraseLanguageCombo->setCurrentItem(
03030     mPhraseLanguageCombo->insertLanguage( lang ) );
03031   KLocale locale("kmail");
03032   locale.setLanguage( lang );
03033   mLanguageList.append(
03034      LanguageItem( lang,
03035                    locale.translate("On %D, you wrote:"),
03036                    locale.translate("On %D, %F wrote:"),
03037                    locale.translate("Forwarded Message"),
03038                    locale.translate(">%_") ) );
03039   mRemoveButton->setEnabled( true );
03040   slotLanguageChanged( TQString::null );
03041 }
03042 
03043 void ComposerPage::PhrasesTab::slotRemoveLanguage()
03044 {
03045   assert( mPhraseLanguageCombo->count() > 1 );
03046   int index = mPhraseLanguageCombo->currentItem();
03047   assert( 0 <= index && index < (int)mLanguageList.count() );
03048 
03049   // remove current item from internal list and combobox:
03050   mLanguageList.remove( mLanguageList.at( index ) );
03051   mPhraseLanguageCombo->removeItem( index );
03052 
03053   if ( index >= (int)mLanguageList.count() ) index--;
03054 
03055   mActiveLanguageItem = index;
03056   setLanguageItemInformation( index );
03057   mRemoveButton->setEnabled( mLanguageList.count() > 1 );
03058   emit changed( true );
03059 }
03060 
03061 void ComposerPage::PhrasesTab::slotLanguageChanged( const TQString& )
03062 {
03063   int index = mPhraseLanguageCombo->currentItem();
03064   assert( index < (int)mLanguageList.count() );
03065   saveActiveLanguageItem();
03066   mActiveLanguageItem = index;
03067   setLanguageItemInformation( index );
03068   emit changed( true );
03069 }
03070 
03071 
03072 void ComposerPage::PhrasesTab::doLoadFromGlobalSettings() {
03073   mLanguageList.clear();
03074   mPhraseLanguageCombo->clear();
03075   mActiveLanguageItem = -1;
03076 
03077   int numLang = GlobalSettings::self()->replyLanguagesCount();
03078   int currentNr = GlobalSettings::self()->replyCurrentLanguage();
03079 
03080   // build mLanguageList and mPhraseLanguageCombo:
03081   for ( int i = 0 ; i < numLang ; i++ ) {
03082     ReplyPhrases replyPhrases( TQString::number(i) );
03083     replyPhrases.readConfig();
03084     TQString lang = replyPhrases.language();
03085     mLanguageList.append(
03086          LanguageItem( lang,
03087                        replyPhrases.phraseReplySender(),
03088                        replyPhrases.phraseReplyAll(),
03089                        replyPhrases.phraseForward(),
03090                        replyPhrases.indentPrefix() ) );
03091     mPhraseLanguageCombo->insertLanguage( lang );
03092   }
03093 
03094   if ( currentNr >= numLang || currentNr < 0 )
03095     currentNr = 0;
03096 
03097   if ( numLang == 0 ) {
03098     slotAddNewLanguage( KGlobal::locale()->language() );
03099   }
03100 
03101   mPhraseLanguageCombo->setCurrentItem( currentNr );
03102   mActiveLanguageItem = currentNr;
03103   setLanguageItemInformation( currentNr );
03104   mRemoveButton->setEnabled( mLanguageList.count() > 1 );
03105 }
03106 
03107 void ComposerPage::PhrasesTab::save() {
03108   GlobalSettings::self()->setReplyLanguagesCount( mLanguageList.count() );
03109   GlobalSettings::self()->setReplyCurrentLanguage( mPhraseLanguageCombo->currentItem() );
03110 
03111   saveActiveLanguageItem();
03112   LanguageItemList::Iterator it = mLanguageList.begin();
03113   for ( int i = 0 ; it != mLanguageList.end() ; ++it, ++i ) {
03114     ReplyPhrases replyPhrases( TQString::number(i) );
03115     replyPhrases.setLanguage( (*it).mLanguage );
03116     replyPhrases.setPhraseReplySender( (*it).mReply );
03117     replyPhrases.setPhraseReplyAll( (*it).mReplyAll );
03118     replyPhrases.setPhraseForward( (*it).mForward );
03119     replyPhrases.setIndentPrefix( (*it).mIndentPrefix );
03120     replyPhrases.writeConfig();
03121   }
03122 }
03123 
03124 TQString ComposerPage::TemplatesTab::helpAnchor() const {
03125   return TQString::fromLatin1("configure-composer-templates");
03126 }
03127 
03128 ComposerPageTemplatesTab::ComposerPageTemplatesTab( TQWidget * parent, const char * name )
03129   : ConfigModuleTab ( parent, name )
03130 {
03131   TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
03132 
03133   mWidget = new TemplatesConfiguration( this );
03134   vlay->addWidget( mWidget );
03135 
03136   connect( mWidget, TQT_SIGNAL( changed() ),
03137            this, TQT_SLOT( slotEmitChanged( void ) ) );
03138 }
03139 
03140 void ComposerPage::TemplatesTab::doLoadFromGlobalSettings() {
03141     mWidget->loadFromGlobal();
03142 }
03143 
03144 void ComposerPage::TemplatesTab::save() {
03145     mWidget->saveToGlobal();
03146 }
03147 
03148 TQString ComposerPage::CustomTemplatesTab::helpAnchor() const {
03149   return TQString::fromLatin1("configure-composer-custom-templates");
03150 }
03151 
03152 ComposerPageCustomTemplatesTab::ComposerPageCustomTemplatesTab( TQWidget * parent, const char * name )
03153   : ConfigModuleTab ( parent, name )
03154 {
03155   TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
03156 
03157   mWidget = new CustomTemplates( this );
03158   vlay->addWidget( mWidget );
03159 
03160   connect( mWidget, TQT_SIGNAL( changed() ),
03161            this, TQT_SLOT( slotEmitChanged( void ) ) );
03162 }
03163 
03164 void ComposerPage::CustomTemplatesTab::doLoadFromGlobalSettings() {
03165     mWidget->load();
03166 }
03167 
03168 void ComposerPage::CustomTemplatesTab::save() {
03169     mWidget->save();
03170 }
03171 
03172 TQString ComposerPage::SubjectTab::helpAnchor() const {
03173   return TQString::fromLatin1("configure-composer-subject");
03174 }
03175 
03176 ComposerPageSubjectTab::ComposerPageSubjectTab( TQWidget * parent, const char * name )
03177   : ConfigModuleTab( parent, name )
03178 {
03179   // tmp. vars:
03180   TQVBoxLayout *vlay;
03181   TQGroupBox   *group;
03182   TQLabel      *label;
03183 
03184 
03185   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
03186 
03187   group = new TQVGroupBox( i18n("Repl&y Subject Prefixes"), this );
03188   group->layout()->setSpacing( KDialog::spacingHint() );
03189 
03190   // row 0: help text:
03191   label = new TQLabel( i18n("Recognize any sequence of the following prefixes\n"
03192                            "(entries are case-insensitive regular expressions):"), group );
03193   label->setAlignment( AlignLeft|WordBreak );
03194 
03195   // row 1, string list editor:
03196   SimpleStringListEditor::ButtonCode buttonCode =
03197     static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
03198   mReplyListEditor =
03199     new SimpleStringListEditor( group, 0, buttonCode,
03200                                 i18n("A&dd..."), i18n("Re&move"),
03201                                 i18n("Mod&ify..."),
03202                                 i18n("Enter new reply prefix:") );
03203   connect( mReplyListEditor, TQT_SIGNAL( changed( void ) ),
03204            this, TQT_SLOT( slotEmitChanged( void ) ) );
03205 
03206   // row 2: "replace [...]" check box:
03207   mReplaceReplyPrefixCheck = new TQCheckBox(
03208      GlobalSettings::self()->replaceReplyPrefixItem()->label(),
03209      group, "kcfg_ReplaceReplyPrefix" );
03210   connect( mReplaceReplyPrefixCheck, TQT_SIGNAL( stateChanged( int ) ),
03211            this, TQT_SLOT( slotEmitChanged( void ) ) );
03212 
03213   vlay->addWidget( group );
03214 
03215 
03216   group = new TQVGroupBox( i18n("For&ward Subject Prefixes"), this );
03217   group->layout()->setSpacing( KDialog::marginHint() );
03218 
03219   // row 0: help text:
03220   label= new TQLabel( i18n("Recognize any sequence of the following prefixes\n"
03221                           "(entries are case-insensitive regular expressions):"), group );
03222   label->setAlignment( AlignLeft|WordBreak );
03223 
03224   // row 1: string list editor
03225   mForwardListEditor =
03226     new SimpleStringListEditor( group, 0, buttonCode,
03227                                 i18n("Add..."),
03228                                 i18n("Remo&ve"),
03229                                 i18n("Modify..."),
03230                                 i18n("Enter new forward prefix:") );
03231   connect( mForwardListEditor, TQT_SIGNAL( changed( void ) ),
03232            this, TQT_SLOT( slotEmitChanged( void ) ) );
03233 
03234   // row 3: "replace [...]" check box:
03235   mReplaceForwardPrefixCheck = new TQCheckBox(
03236        GlobalSettings::self()->replaceForwardPrefixItem()->label(),
03237        group, "kcfg_ReplaceForwardPrefix" );
03238   connect( mReplaceForwardPrefixCheck, TQT_SIGNAL( stateChanged( int ) ),
03239            this, TQT_SLOT( slotEmitChanged( void ) ) );
03240 
03241   vlay->addWidget( group );
03242 }
03243 
03244 void ComposerPage::SubjectTab::doLoadFromGlobalSettings() {
03245   mReplyListEditor->setStringList( GlobalSettings::self()->replyPrefixes() );
03246   mReplaceReplyPrefixCheck->setChecked( GlobalSettings::self()->replaceReplyPrefix() );
03247   mForwardListEditor->setStringList( GlobalSettings::self()->forwardPrefixes() );
03248   mReplaceForwardPrefixCheck->setChecked( GlobalSettings::self()->replaceForwardPrefix() );
03249 }
03250 
03251 void ComposerPage::SubjectTab::save() {
03252   GlobalSettings::self()->setReplyPrefixes( mReplyListEditor->stringList() );
03253   GlobalSettings::self()->setForwardPrefixes( mForwardListEditor->stringList() );
03254 }
03255 
03256 TQString ComposerPage::CharsetTab::helpAnchor() const {
03257   return TQString::fromLatin1("configure-composer-charset");
03258 }
03259 
03260 ComposerPageCharsetTab::ComposerPageCharsetTab( TQWidget * parent, const char * name )
03261   : ConfigModuleTab( parent, name )
03262 {
03263   // tmp. vars:
03264   TQVBoxLayout *vlay;
03265   TQLabel      *label;
03266 
03267   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
03268 
03269   label = new TQLabel( i18n("This list is checked for every outgoing message "
03270                            "from the top to the bottom for a charset that "
03271                            "contains all required characters."), this );
03272   label->setAlignment( WordBreak);
03273   vlay->addWidget( label );
03274 
03275   mCharsetListEditor =
03276     new SimpleStringListEditor( this, 0, SimpleStringListEditor::All,
03277                                 i18n("A&dd..."), i18n("Remo&ve"),
03278                                 i18n("&Modify..."), i18n("Enter charset:") );
03279   connect( mCharsetListEditor, TQT_SIGNAL( changed( void ) ),
03280            this, TQT_SLOT( slotEmitChanged( void ) ) );
03281 
03282   vlay->addWidget( mCharsetListEditor, 1 );
03283 
03284   mKeepReplyCharsetCheck = new TQCheckBox( i18n("&Keep original charset when "
03285                                                 "replying or forwarding (if "
03286                                                 "possible)"), this );
03287   connect( mKeepReplyCharsetCheck, TQT_SIGNAL ( stateChanged( int ) ),
03288            this, TQT_SLOT( slotEmitChanged( void ) ) );
03289   vlay->addWidget( mKeepReplyCharsetCheck );
03290 
03291   connect( mCharsetListEditor, TQT_SIGNAL(aboutToAdd(TQString&)),
03292            this, TQT_SLOT(slotVerifyCharset(TQString&)) );
03293 }
03294 
03295 void ComposerPage::CharsetTab::slotVerifyCharset( TQString & charset ) {
03296   if ( charset.isEmpty() ) return;
03297 
03298   // KCharsets::codecForName("us-ascii") returns "iso-8859-1" (cf. Bug #49812)
03299   // therefore we have to treat this case specially
03300   if ( charset.lower() == TQString::fromLatin1("us-ascii") ) {
03301     charset = TQString::fromLatin1("us-ascii");
03302     return;
03303   }
03304 
03305   if ( charset.lower() == TQString::fromLatin1("locale") ) {
03306     charset =  TQString::fromLatin1("%1 (locale)")
03307       .arg( TQCString( kmkernel->networkCodec()->mimeName() ).lower() );
03308     return;
03309   }
03310 
03311   bool ok = false;
03312   TQTextCodec *codec = KGlobal::charsets()->codecForName( charset, ok );
03313   if ( ok && codec ) {
03314     charset = TQString::fromLatin1( codec->mimeName() ).lower();
03315     return;
03316   }
03317 
03318   KMessageBox::sorry( this, i18n("This charset is not supported.") );
03319   charset = TQString::null;
03320 }
03321 
03322 void ComposerPage::CharsetTab::doLoadOther() {
03323   KConfigGroup composer( KMKernel::config(), "Composer" );
03324 
03325   TQStringList charsets = composer.readListEntry( "pref-charsets" );
03326   for ( TQStringList::Iterator it = charsets.begin() ;
03327         it != charsets.end() ; ++it )
03328     if ( (*it) == TQString::fromLatin1("locale") ) {
03329       TQCString cset = kmkernel->networkCodec()->mimeName();
03330       KPIM::kAsciiToLower( cset.data() );
03331       (*it) = TQString("%1 (locale)").arg( cset );
03332     }
03333 
03334   mCharsetListEditor->setStringList( charsets );
03335   mKeepReplyCharsetCheck->setChecked( !composer.readBoolEntry( "force-reply-charset", false ) );
03336 }
03337 
03338 void ComposerPage::CharsetTab::save() {
03339   KConfigGroup composer( KMKernel::config(), "Composer" );
03340 
03341   TQStringList charsetList = mCharsetListEditor->stringList();
03342   TQStringList::Iterator it = charsetList.begin();
03343   for ( ; it != charsetList.end() ; ++it )
03344     if ( (*it).endsWith("(locale)") )
03345       (*it) = "locale";
03346   composer.writeEntry( "pref-charsets", charsetList );
03347   composer.writeEntry( "force-reply-charset",
03348                        !mKeepReplyCharsetCheck->isChecked() );
03349 }
03350 
03351 TQString ComposerPage::HeadersTab::helpAnchor() const {
03352   return TQString::fromLatin1("configure-composer-headers");
03353 }
03354 
03355 ComposerPageHeadersTab::ComposerPageHeadersTab( TQWidget * parent, const char * name )
03356   : ConfigModuleTab( parent, name )
03357 {
03358   // tmp. vars:
03359   TQVBoxLayout *vlay;
03360   TQHBoxLayout *hlay;
03361   TQGridLayout *glay;
03362   TQLabel      *label;
03363   TQPushButton *button;
03364 
03365   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
03366 
03367   // "Use custom Message-Id suffix" checkbox:
03368   mCreateOwnMessageIdCheck =
03369     new TQCheckBox( i18n("&Use custom message-id suffix"), this );
03370   connect( mCreateOwnMessageIdCheck, TQT_SIGNAL ( stateChanged( int ) ),
03371            this, TQT_SLOT( slotEmitChanged( void ) ) );
03372   vlay->addWidget( mCreateOwnMessageIdCheck );
03373 
03374   // "Message-Id suffix" line edit and label:
03375   hlay = new TQHBoxLayout( vlay ); // inherits spacing
03376   mMessageIdSuffixEdit = new KLineEdit( this );
03377   // only ASCII letters, digits, plus, minus and dots are allowed
03378   mMessageIdSuffixValidator =
03379     new TQRegExpValidator( TQRegExp( "[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*" ), this );
03380   mMessageIdSuffixEdit->setValidator( mMessageIdSuffixValidator );
03381   label = new TQLabel( mMessageIdSuffixEdit,
03382                       i18n("Custom message-&id suffix:"), this );
03383   label->setEnabled( false ); // since !mCreateOwnMessageIdCheck->isChecked()
03384   mMessageIdSuffixEdit->setEnabled( false );
03385   hlay->addWidget( label );
03386   hlay->addWidget( mMessageIdSuffixEdit, 1 );
03387   connect( mCreateOwnMessageIdCheck, TQT_SIGNAL(toggled(bool) ),
03388            label, TQT_SLOT(setEnabled(bool)) );
03389   connect( mCreateOwnMessageIdCheck, TQT_SIGNAL(toggled(bool) ),
03390            mMessageIdSuffixEdit, TQT_SLOT(setEnabled(bool)) );
03391   connect( mMessageIdSuffixEdit, TQT_SIGNAL( textChanged( const TQString& ) ),
03392            this, TQT_SLOT( slotEmitChanged( void ) ) );
03393 
03394   // horizontal rule and "custom header fields" label:
03395   vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
03396   vlay->addWidget( new TQLabel( i18n("Define custom mime header fields:"), this) );
03397 
03398   // "custom header fields" listbox:
03399   glay = new TQGridLayout( vlay, 5, 3 ); // inherits spacing
03400   glay->setRowStretch( 2, 1 );
03401   glay->setColStretch( 1, 1 );
03402   mTagList = new ListView( this, "tagList" );
03403   mTagList->addColumn( i18n("Name") );
03404   mTagList->addColumn( i18n("Value") );
03405   mTagList->setAllColumnsShowFocus( true );
03406   mTagList->setSorting( -1 );
03407   connect( mTagList, TQT_SIGNAL(selectionChanged()),
03408            this, TQT_SLOT(slotMimeHeaderSelectionChanged()) );
03409   glay->addMultiCellWidget( mTagList, 0, 2, 0, 1 );
03410 
03411   // "new" and "remove" buttons:
03412   button = new TQPushButton( i18n("Ne&w"), this );
03413   connect( button, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNewMimeHeader()) );
03414   button->setAutoDefault( false );
03415   glay->addWidget( button, 0, 2 );
03416   mRemoveHeaderButton = new TQPushButton( i18n("Re&move"), this );
03417   connect( mRemoveHeaderButton, TQT_SIGNAL(clicked()),
03418            this, TQT_SLOT(slotRemoveMimeHeader()) );
03419   button->setAutoDefault( false );
03420   glay->addWidget( mRemoveHeaderButton, 1, 2 );
03421 
03422   // "name" and "value" line edits and labels:
03423   mTagNameEdit = new KLineEdit( this );
03424   mTagNameEdit->setEnabled( false );
03425   mTagNameLabel = new TQLabel( mTagNameEdit, i18n("&Name:"), this );
03426   mTagNameLabel->setEnabled( false );
03427   glay->addWidget( mTagNameLabel, 3, 0 );
03428   glay->addWidget( mTagNameEdit, 3, 1 );
03429   connect( mTagNameEdit, TQT_SIGNAL(textChanged(const TQString&)),
03430            this, TQT_SLOT(slotMimeHeaderNameChanged(const TQString&)) );
03431 
03432   mTagValueEdit = new KLineEdit( this );
03433   mTagValueEdit->setEnabled( false );
03434   mTagValueLabel = new TQLabel( mTagValueEdit, i18n("&Value:"), this );
03435   mTagValueLabel->setEnabled( false );
03436   glay->addWidget( mTagValueLabel, 4, 0 );
03437   glay->addWidget( mTagValueEdit, 4, 1 );
03438   connect( mTagValueEdit, TQT_SIGNAL(textChanged(const TQString&)),
03439            this, TQT_SLOT(slotMimeHeaderValueChanged(const TQString&)) );
03440 }
03441 
03442 void ComposerPage::HeadersTab::slotMimeHeaderSelectionChanged()
03443 {
03444   TQListViewItem * item = mTagList->selectedItem();
03445 
03446   if ( item ) {
03447     mTagNameEdit->setText( item->text( 0 ) );
03448     mTagValueEdit->setText( item->text( 1 ) );
03449   } else {
03450     mTagNameEdit->clear();
03451     mTagValueEdit->clear();
03452   }
03453   mRemoveHeaderButton->setEnabled( item );
03454   mTagNameEdit->setEnabled( item );
03455   mTagValueEdit->setEnabled( item );
03456   mTagNameLabel->setEnabled( item );
03457   mTagValueLabel->setEnabled( item );
03458 }
03459 
03460 
03461 void ComposerPage::HeadersTab::slotMimeHeaderNameChanged( const TQString & text ) {
03462   // is called on ::setup(), when clearing the line edits. So be
03463   // prepared to not find a selection:
03464   TQListViewItem * item = mTagList->selectedItem();
03465   if ( item )
03466     item->setText( 0, text );
03467   emit changed( true );
03468 }
03469 
03470 
03471 void ComposerPage::HeadersTab::slotMimeHeaderValueChanged( const TQString & text ) {
03472   // is called on ::setup(), when clearing the line edits. So be
03473   // prepared to not find a selection:
03474   TQListViewItem * item = mTagList->selectedItem();
03475   if ( item )
03476     item->setText( 1, text );
03477   emit changed( true );
03478 }
03479 
03480 
03481 void ComposerPage::HeadersTab::slotNewMimeHeader()
03482 {
03483   TQListViewItem *listItem = new TQListViewItem( mTagList );
03484   mTagList->setCurrentItem( listItem );
03485   mTagList->setSelected( listItem, true );
03486   emit changed( true );
03487 }
03488 
03489 
03490 void ComposerPage::HeadersTab::slotRemoveMimeHeader()
03491 {
03492   // calling this w/o selection is a programming error:
03493   TQListViewItem * item = mTagList->selectedItem();
03494   if ( !item ) {
03495     kdDebug(5006) << "==================================================\n"
03496                   << "Error: Remove button was pressed although no custom header was selected\n"
03497                   << "==================================================\n";
03498     return;
03499   }
03500 
03501   TQListViewItem * below = item->nextSibling();
03502   delete item;
03503 
03504   if ( below )
03505     mTagList->setSelected( below, true );
03506   else if ( mTagList->lastItem() )
03507     mTagList->setSelected( mTagList->lastItem(), true );
03508   emit changed( true );
03509 }
03510 
03511 void ComposerPage::HeadersTab::doLoadOther() {
03512   KConfigGroup general( KMKernel::config(), "General" );
03513 
03514   TQString suffix = general.readEntry( "myMessageIdSuffix" );
03515   mMessageIdSuffixEdit->setText( suffix );
03516   bool state = ( !suffix.isEmpty() &&
03517             general.readBoolEntry( "useCustomMessageIdSuffix", false ) );
03518   mCreateOwnMessageIdCheck->setChecked( state );
03519 
03520   mTagList->clear();
03521   mTagNameEdit->clear();
03522   mTagValueEdit->clear();
03523 
03524   TQListViewItem * item = 0;
03525 
03526   int count = general.readNumEntry( "mime-header-count", 0 );
03527   for( int i = 0 ; i < count ; i++ ) {
03528     KConfigGroup config( KMKernel::config(),
03529                          TQCString("Mime #") + TQCString().setNum(i) );
03530     TQString name  = config.readEntry( "name" );
03531     TQString value = config.readEntry( "value" );
03532     if( !name.isEmpty() )
03533       item = new TQListViewItem( mTagList, item, name, value );
03534   }
03535   if ( mTagList->childCount() ) {
03536     mTagList->setCurrentItem( mTagList->firstChild() );
03537     mTagList->setSelected( mTagList->firstChild(), true );
03538   }
03539   else {
03540     // disable the "Remove" button
03541     mRemoveHeaderButton->setEnabled( false );
03542   }
03543 }
03544 
03545 void ComposerPage::HeadersTab::save() {
03546   KConfigGroup general( KMKernel::config(), "General" );
03547 
03548   general.writeEntry( "useCustomMessageIdSuffix",
03549                       mCreateOwnMessageIdCheck->isChecked() );
03550   general.writeEntry( "myMessageIdSuffix",
03551                       mMessageIdSuffixEdit->text() );
03552 
03553   int numValidEntries = 0;
03554   TQListViewItem * item = mTagList->firstChild();
03555   for ( ; item ; item = item->itemBelow() )
03556     if( !item->text(0).isEmpty() ) {
03557       KConfigGroup config( KMKernel::config(), TQCString("Mime #")
03558                              + TQCString().setNum( numValidEntries ) );
03559       config.writeEntry( "name",  item->text( 0 ) );
03560       config.writeEntry( "value", item->text( 1 ) );
03561       numValidEntries++;
03562     }
03563   general.writeEntry( "mime-header-count", numValidEntries );
03564 }
03565 
03566 TQString ComposerPage::AttachmentsTab::helpAnchor() const {
03567   return TQString::fromLatin1("configure-composer-attachments");
03568 }
03569 
03570 ComposerPageAttachmentsTab::ComposerPageAttachmentsTab( TQWidget * parent,
03571                                                         const char * name )
03572   : ConfigModuleTab( parent, name ) {
03573   // tmp. vars:
03574   TQVBoxLayout *vlay;
03575   TQLabel      *label;
03576 
03577   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
03578 
03579   // "Outlook compatible attachment naming" check box
03580   mOutlookCompatibleCheck =
03581     new TQCheckBox( i18n( "Outlook-compatible attachment naming" ), this );
03582   mOutlookCompatibleCheck->setChecked( false );
03583   TQToolTip::add( mOutlookCompatibleCheck, i18n(
03584     "Turn this option on to make Outlook(tm) understand attachment names "
03585     "containing non-English characters" ) );
03586   connect( mOutlookCompatibleCheck, TQT_SIGNAL( stateChanged( int ) ),
03587            this, TQT_SLOT( slotEmitChanged( void ) ) );
03588   connect( mOutlookCompatibleCheck, TQT_SIGNAL( clicked() ),
03589            this, TQT_SLOT( slotOutlookCompatibleClicked() ) );
03590   vlay->addWidget( mOutlookCompatibleCheck );
03591   vlay->addSpacing( 5 );
03592 
03593   // "Enable detection of missing attachments" check box
03594   mMissingAttachmentDetectionCheck =
03595     new TQCheckBox( i18n("E&nable detection of missing attachments"), this );
03596   mMissingAttachmentDetectionCheck->setChecked( true );
03597   connect( mMissingAttachmentDetectionCheck, TQT_SIGNAL( stateChanged( int ) ),
03598            this, TQT_SLOT( slotEmitChanged( void ) ) );
03599   vlay->addWidget( mMissingAttachmentDetectionCheck );
03600 
03601   // "Attachment key words" label and string list editor
03602   label = new TQLabel( i18n("Recognize any of the following key words as "
03603                            "intention to attach a file:"), this );
03604   label->setAlignment( AlignLeft|WordBreak );
03605   vlay->addWidget( label );
03606 
03607   SimpleStringListEditor::ButtonCode buttonCode =
03608     static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
03609   mAttachWordsListEditor =
03610     new SimpleStringListEditor( this, 0, buttonCode,
03611                                 i18n("A&dd..."), i18n("Re&move"),
03612                                 i18n("Mod&ify..."),
03613                                 i18n("Enter new key word:") );
03614   connect( mAttachWordsListEditor, TQT_SIGNAL( changed( void ) ),
03615            this, TQT_SLOT( slotEmitChanged( void ) ) );
03616   vlay->addWidget( mAttachWordsListEditor );
03617 
03618   connect( mMissingAttachmentDetectionCheck, TQT_SIGNAL(toggled(bool) ),
03619            label, TQT_SLOT(setEnabled(bool)) );
03620   connect( mMissingAttachmentDetectionCheck, TQT_SIGNAL(toggled(bool) ),
03621            mAttachWordsListEditor, TQT_SLOT(setEnabled(bool)) );
03622 }
03623 
03624 void ComposerPage::AttachmentsTab::doLoadFromGlobalSettings() {
03625   mOutlookCompatibleCheck->setChecked(
03626     GlobalSettings::self()->outlookCompatibleAttachments() );
03627   mMissingAttachmentDetectionCheck->setChecked(
03628     GlobalSettings::self()->showForgottenAttachmentWarning() );
03629   TQStringList attachWordsList = GlobalSettings::self()->attachmentKeywords();
03630   if ( attachWordsList.isEmpty() ) {
03631     // default value
03632     attachWordsList << TQString::fromLatin1("attachment")
03633                     << TQString::fromLatin1("attached");
03634     if ( TQString::fromLatin1("attachment") != i18n("attachment") )
03635       attachWordsList << i18n("attachment");
03636     if ( TQString::fromLatin1("attached") != i18n("attached") )
03637       attachWordsList << i18n("attached");
03638   }
03639 
03640   mAttachWordsListEditor->setStringList( attachWordsList );
03641 }
03642 
03643 void ComposerPage::AttachmentsTab::save() {
03644   GlobalSettings::self()->setOutlookCompatibleAttachments(
03645     mOutlookCompatibleCheck->isChecked() );
03646   GlobalSettings::self()->setShowForgottenAttachmentWarning(
03647     mMissingAttachmentDetectionCheck->isChecked() );
03648   GlobalSettings::self()->setAttachmentKeywords(
03649     mAttachWordsListEditor->stringList() );
03650 }
03651 
03652 void ComposerPageAttachmentsTab::slotOutlookCompatibleClicked()
03653 {
03654   if (mOutlookCompatibleCheck->isChecked()) {
03655     KMessageBox::information(0,i18n("You have chosen to "
03656     "encode attachment names containing non-English characters in a way that "
03657     "is understood by Outlook(tm) and other mail clients that do not "
03658     "support standard-compliant encoded attachment names.\n"
03659     "Note that KMail may create non-standard compliant messages, "
03660     "and consequently it is possible that your messages will not be "
03661     "understood by standard-compliant mail clients; so, unless you have no "
03662     "other choice, you should not enable this option." ) );
03663   }
03664 }
03665 
03666 // *************************************************************
03667 // *                                                           *
03668 // *                      SecurityPage                         *
03669 // *                                                           *
03670 // *************************************************************
03671 TQString SecurityPage::helpAnchor() const {
03672   return TQString::fromLatin1("configure-security");
03673 }
03674 
03675 SecurityPage::SecurityPage( TQWidget * parent, const char * name )
03676   : ConfigModuleWithTabs( parent, name )
03677 {
03678   //
03679   // "Reading" tab:
03680   //
03681   mGeneralTab = new GeneralTab(); //  @TODO: rename
03682   addTab( mGeneralTab, i18n("&Reading") );
03683 
03684   //
03685   // "Composing" tab:
03686   //
03687   mComposerCryptoTab = new ComposerCryptoTab();
03688   addTab( mComposerCryptoTab, i18n("Composing") );
03689 
03690   //
03691   // "Warnings" tab:
03692   //
03693   mWarningTab = new WarningTab();
03694   addTab( mWarningTab, i18n("Warnings") );
03695 
03696   //
03697   // "S/MIME Validation" tab:
03698   //
03699   mSMimeTab = new SMimeTab();
03700   addTab( mSMimeTab, i18n("S/MIME &Validation") );
03701 
03702   //
03703   // "Crypto Backends" tab:
03704   //
03705   mCryptPlugTab = new CryptPlugTab();
03706   addTab( mCryptPlugTab, i18n("Crypto Backe&nds") );
03707   load();
03708 }
03709 
03710 
03711 void SecurityPage::installProfile( KConfig * profile ) {
03712   mGeneralTab->installProfile( profile );
03713   mComposerCryptoTab->installProfile( profile );
03714   mWarningTab->installProfile( profile );
03715   mSMimeTab->installProfile( profile );
03716 }
03717 
03718 TQString SecurityPage::GeneralTab::helpAnchor() const {
03719   return TQString::fromLatin1("configure-security-reading");
03720 }
03721 
03722 SecurityPageGeneralTab::SecurityPageGeneralTab( TQWidget * parent, const char * name )
03723   : ConfigModuleTab ( parent, name )
03724 {
03725   // tmp. vars:
03726   TQVBoxLayout  *vlay;
03727   TQHBox        *hbox;
03728   TQGroupBox    *group;
03729   TQRadioButton *radio;
03730   KActiveLabel *label;
03731   TQWidget      *w;
03732   TQString       msg;
03733 
03734   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
03735 
03736   // QWhat'sThis texts
03737   TQString htmlWhatsThis = i18n( "<qt><p>Messages sometimes come in both formats. "
03738               "This option controls whether you want the HTML part or the plain "
03739               "text part to be displayed.</p>"
03740               "<p>Displaying the HTML part makes the message look better, "
03741               "but at the same time increases the risk of security holes "
03742               "being exploited.</p>"
03743               "<p>Displaying the plain text part loses much of the message's "
03744               "formatting, but makes it almost <em>impossible</em> "
03745               "to exploit security holes in the HTML renderer (Konqueror).</p>"
03746               "<p>The option below guards against one common misuse of HTML "
03747               "messages, but it cannot guard against security issues that were "
03748               "not known at the time this version of KMail was written.</p>"
03749               "<p>It is therefore advisable to <em>not</em> prefer HTML to "
03750               "plain text.</p>"
03751               "<p><b>Note:</b> You can set this option on a per-folder basis "
03752               "from the <i>Folder</i> menu of KMail's main window.</p></qt>" );
03753 
03754   TQString externalWhatsThis = i18n( "<qt><p>Some mail advertisements are in HTML "
03755               "and contain references to, for example, images that the advertisers"
03756               " employ to find out that you have read their message "
03757               "(&quot;web bugs&quot;).</p>"
03758               "<p>There is no valid reason to load images off the Internet like "
03759               "this, since the sender can always attach the required images "
03760               "directly to the message.</p>"
03761               "<p>To guard from such a misuse of the HTML displaying feature "
03762               "of KMail, this option is <em>disabled</em> by default.</p>"
03763               "<p>However, if you wish to, for example, view images in HTML "
03764               "messages that were not attached to it, you can enable this "
03765               "option, but you should be aware of the possible problem.</p></qt>" );
03766 
03767   TQString receiptWhatsThis = i18n( "<qt><h3>Message Disposition "
03768               "Notification Policy</h3>"
03769               "<p>MDNs are a generalization of what is commonly called <b>read "
03770               "receipt</b>. The message author requests a disposition "
03771               "notification to be sent and the receiver's mail program "
03772               "generates a reply from which the author can learn what "
03773               "happened to his message. Common disposition types include "
03774               "<b>displayed</b> (i.e. read), <b>deleted</b> and <b>dispatched</b> "
03775               "(e.g. forwarded).</p>"
03776               "<p>The following options are available to control KMail's "
03777               "sending of MDNs:</p>"
03778               "<ul>"
03779               "<li><em>Ignore</em>: Ignores any request for disposition "
03780               "notifications. No MDN will ever be sent automatically "
03781               "(recommended).</li>"
03782               "<li><em>Ask</em>: Answers requests only after asking the user "
03783               "for permission. This way, you can send MDNs for selected "
03784               "messages while denying or ignoring them for others.</li>"
03785               "<li><em>Deny</em>: Always sends a <b>denied</b> notification. This "
03786               "is only <em>slightly</em> better than always sending MDNs. "
03787               "The author will still know that the messages has been acted "
03788               "upon, he just cannot tell whether it was deleted or read etc.</li>"
03789               "<li><em>Always send</em>: Always sends the requested "
03790               "disposition notification. That means that the author of the "
03791               "message gets to know when the message was acted upon and, "
03792               "in addition, what happened to it (displayed, deleted, "
03793               "etc.). This option is strongly discouraged, but since it "
03794               "makes much sense e.g. for customer relationship management, "
03795               "it has been made available.</li>"
03796               "</ul></qt>" );
03797 
03798 
03799   // "HTML Messages" group box:
03800   group = new TQVGroupBox( i18n( "HTML Messages" ), this );
03801   group->layout()->setSpacing( KDialog::spacingHint() );
03802 
03803   mHtmlMailCheck = new TQCheckBox( i18n("Prefer H&TML to plain text"), group );
03804   TQWhatsThis::add( mHtmlMailCheck, htmlWhatsThis );
03805   connect( mHtmlMailCheck, TQT_SIGNAL( stateChanged( int ) ),
03806            this, TQT_SLOT( slotEmitChanged( void ) ) );
03807   mExternalReferences = new TQCheckBox( i18n("Allow messages to load e&xternal "
03808                                             "references from the Internet" ), group );
03809   TQWhatsThis::add( mExternalReferences, externalWhatsThis );
03810   connect( mExternalReferences, TQT_SIGNAL( stateChanged( int ) ),
03811            this, TQT_SLOT( slotEmitChanged( void ) ) );
03812   label = new KActiveLabel( i18n("<b>WARNING:</b> Allowing HTML in email may "
03813                            "increase the risk that your system will be "
03814                            "compromised by present and anticipated security "
03815                            "exploits. <a href=\"whatsthis:%1\">More about "
03816                            "HTML mails...</a> <a href=\"whatsthis:%2\">More "
03817                            "about external references...</a>")
03818                            .arg(htmlWhatsThis).arg(externalWhatsThis),
03819                            group );
03820 
03821   vlay->addWidget( group );
03822 
03823   // encrypted messages group
03824   group = new TQVGroupBox( i18n("Encrypted Messages"), this );
03825   group->layout()->setSpacing( KDialog::spacingHint() );
03826   mAlwaysDecrypt = new TQCheckBox( i18n( "Attempt decryption of encrypted messages when viewing" ), group );
03827   connect( mAlwaysDecrypt, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(slotEmitChanged()) );
03828   vlay->addWidget( group );
03829 
03830   // "Message Disposition Notification" groupbox:
03831   group = new TQVGroupBox( i18n("Message Disposition Notifications"), this );
03832   group->layout()->setSpacing( KDialog::spacingHint() );
03833 
03834 
03835   // "ignore", "ask", "deny", "always send" radiobutton line:
03836   mMDNGroup = new TQButtonGroup( group );
03837   mMDNGroup->hide();
03838   connect( mMDNGroup, TQT_SIGNAL( clicked( int ) ),
03839            this, TQT_SLOT( slotEmitChanged( void ) ) );
03840   hbox = new TQHBox( group );
03841   hbox->setSpacing( KDialog::spacingHint() );
03842 
03843   (void)new TQLabel( i18n("Send policy:"), hbox );
03844 
03845   radio = new TQRadioButton( i18n("&Ignore"), hbox );
03846   mMDNGroup->insert( radio );
03847 
03848   radio = new TQRadioButton( i18n("As&k"), hbox );
03849   mMDNGroup->insert( radio );
03850 
03851   radio = new TQRadioButton( i18n("&Deny"), hbox );
03852   mMDNGroup->insert( radio );
03853 
03854   radio = new TQRadioButton( i18n("Al&ways send"), hbox );
03855   mMDNGroup->insert( radio );
03856 
03857   for ( int i = 0 ; i < mMDNGroup->count() ; ++i )
03858       TQWhatsThis::add( mMDNGroup->find( i ), receiptWhatsThis );
03859 
03860   w = new TQWidget( hbox ); // spacer
03861   hbox->setStretchFactor( w, 1 );
03862 
03863   // "Original Message quote" radiobutton line:
03864   mOrigQuoteGroup = new TQButtonGroup( group );
03865   mOrigQuoteGroup->hide();
03866   connect( mOrigQuoteGroup, TQT_SIGNAL( clicked( int ) ),
03867            this, TQT_SLOT( slotEmitChanged( void ) ) );
03868 
03869   hbox = new TQHBox( group );
03870   hbox->setSpacing( KDialog::spacingHint() );
03871 
03872   (void)new TQLabel( i18n("Quote original message:"), hbox );
03873 
03874   radio = new TQRadioButton( i18n("Nothin&g"), hbox );
03875   mOrigQuoteGroup->insert( radio );
03876 
03877   radio = new TQRadioButton( i18n("&Full message"), hbox );
03878   mOrigQuoteGroup->insert( radio );
03879 
03880   radio = new TQRadioButton( i18n("Onl&y headers"), hbox );
03881   mOrigQuoteGroup->insert( radio );
03882 
03883   w = new TQWidget( hbox );
03884   hbox->setStretchFactor( w, 1 );
03885 
03886   mNoMDNsWhenEncryptedCheck = new TQCheckBox( i18n("Do not send MDNs in response to encrypted messages"), group );
03887   connect( mNoMDNsWhenEncryptedCheck, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
03888 
03889   // Warning label:
03890   label = new KActiveLabel( i18n("<b>WARNING:</b> Unconditionally returning "
03891                            "confirmations undermines your privacy. "
03892                            "<a href=\"whatsthis:%1\">More...</a>")
03893                              .arg(receiptWhatsThis),
03894                            group );
03895 
03896   vlay->addWidget( group );
03897 
03898   // "Attached keys" group box:
03899   group = new TQVGroupBox( i18n( "Certificate && Key Bundle Attachments" ), this );
03900   group->layout()->setSpacing( KDialog::spacingHint() );
03901 
03902   mAutomaticallyImportAttachedKeysCheck = new TQCheckBox( i18n("Automatically import keys and certificates"), group );
03903   connect( mAutomaticallyImportAttachedKeysCheck, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
03904 
03905   vlay->addWidget( group );
03906 
03907 
03908 
03909   vlay->addStretch( 10 ); // spacer
03910 }
03911 
03912 void SecurityPage::GeneralTab::doLoadOther() {
03913   const KConfigGroup reader( KMKernel::config(), "Reader" );
03914 
03915   mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail", false ) );
03916   mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal", false ) );
03917   mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys", false ) );
03918 
03919   mAlwaysDecrypt->setChecked( GlobalSettings::self()->alwaysDecrypt() );
03920 
03921   const KConfigGroup mdn( KMKernel::config(), "MDN" );
03922 
03923   int num = mdn.readNumEntry( "default-policy", 0 );
03924   if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
03925   mMDNGroup->setButton( num );
03926   num = mdn.readNumEntry( "quote-message", 0 );
03927   if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
03928   mOrigQuoteGroup->setButton( num );
03929   mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted", true ));
03930 }
03931 
03932 void SecurityPage::GeneralTab::installProfile( KConfig * profile ) {
03933   const KConfigGroup reader( profile, "Reader" );
03934   const KConfigGroup mdn( profile, "MDN" );
03935 
03936   if ( reader.hasKey( "htmlMail" ) )
03937     mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail" ) );
03938   if ( reader.hasKey( "htmlLoadExternal" ) )
03939     mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal" ) );
03940   if ( reader.hasKey( "AutoImportKeys" ) )
03941     mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys" ) );
03942 
03943   if ( mdn.hasKey( "default-policy" ) ) {
03944       int num = mdn.readNumEntry( "default-policy" );
03945       if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
03946       mMDNGroup->setButton( num );
03947   }
03948   if ( mdn.hasKey( "quote-message" ) ) {
03949       int num = mdn.readNumEntry( "quote-message" );
03950       if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
03951       mOrigQuoteGroup->setButton( num );
03952   }
03953   if ( mdn.hasKey( "not-send-when-encrypted" ) )
03954       mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted" ));
03955 }
03956 
03957 void SecurityPage::GeneralTab::save() {
03958   KConfigGroup reader( KMKernel::config(), "Reader" );
03959   KConfigGroup mdn( KMKernel::config(), "MDN" );
03960 
03961   if (reader.readBoolEntry( "htmlMail", false ) != mHtmlMailCheck->isChecked())
03962   {
03963     if (KMessageBox::warningContinueCancel(this, i18n("Changing the global "
03964       "HTML setting will override all folder specific values."), TQString::null,
03965       KStdGuiItem::cont(), "htmlMailOverride") == KMessageBox::Continue)
03966     {
03967       reader.writeEntry( "htmlMail", mHtmlMailCheck->isChecked() );
03968       TQStringList names;
03969       TQValueList<TQGuardedPtr<KMFolder> > folders;
03970       kmkernel->folderMgr()->createFolderList(&names, &folders);
03971       kmkernel->imapFolderMgr()->createFolderList(&names, &folders);
03972       kmkernel->dimapFolderMgr()->createFolderList(&names, &folders);
03973       kmkernel->searchFolderMgr()->createFolderList(&names, &folders);
03974       for (TQValueList<TQGuardedPtr<KMFolder> >::iterator it = folders.begin();
03975         it != folders.end(); ++it)
03976       {
03977         if (*it)
03978         {
03979           KConfigGroupSaver saver(KMKernel::config(),
03980             "Folder-" + (*it)->idString());
03981           KMKernel::config()->writeEntry("htmlMailOverride", false);
03982         }
03983       }
03984     }
03985   }
03986   reader.writeEntry( "htmlLoadExternal", mExternalReferences->isChecked() );
03987   reader.writeEntry( "AutoImportKeys", mAutomaticallyImportAttachedKeysCheck->isChecked() );
03988   mdn.writeEntry( "default-policy", mMDNGroup->id( mMDNGroup->selected() ) );
03989   mdn.writeEntry( "quote-message", mOrigQuoteGroup->id( mOrigQuoteGroup->selected() ) );
03990   mdn.writeEntry( "not-send-when-encrypted", mNoMDNsWhenEncryptedCheck->isChecked() );
03991   GlobalSettings::self()->setAlwaysDecrypt( mAlwaysDecrypt->isChecked() );
03992 }
03993 
03994 
03995 TQString SecurityPage::ComposerCryptoTab::helpAnchor() const {
03996   return TQString::fromLatin1("configure-security-composing");
03997 }
03998 
03999 SecurityPageComposerCryptoTab::SecurityPageComposerCryptoTab( TQWidget * parent, const char * name )
04000   : ConfigModuleTab ( parent, name )
04001 {
04002   // the margins are inside mWidget itself
04003   TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
04004 
04005   mWidget = new ComposerCryptoConfiguration( this );
04006   connect( mWidget->mAutoSignature, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04007   connect( mWidget->mEncToSelf, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04008   connect( mWidget->mShowEncryptionResult, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04009   connect( mWidget->mShowKeyApprovalDlg, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04010   connect( mWidget->mAutoEncrypt, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04011   connect( mWidget->mNeverEncryptWhenSavingInDrafts, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04012   connect( mWidget->mStoreEncrypted, TQT_SIGNAL( toggled(bool) ), this, TQT_SLOT( slotEmitChanged() ) );
04013   vlay->addWidget( mWidget );
04014 }
04015 
04016 void SecurityPage::ComposerCryptoTab::doLoadOther() {
04017   const KConfigGroup composer( KMKernel::config(), "Composer" );
04018 
04019   // If you change default values, sync messagecomposer.cpp too
04020 
04021   mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign", false ) );
04022 
04023   mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self", true ) );
04024   mWidget->mShowEncryptionResult->setChecked( false ); //composer.readBoolEntry( "crypto-show-encryption-result", true ) );
04025   mWidget->mShowEncryptionResult->hide();
04026   mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval", true ) );
04027 
04028   mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt", false ) );
04029   mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts", true ) );
04030 
04031   mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted", true ) );
04032 }
04033 
04034 void SecurityPage::ComposerCryptoTab::installProfile( KConfig * profile ) {
04035   const KConfigGroup composer( profile, "Composer" );
04036 
04037   if ( composer.hasKey( "pgp-auto-sign" ) )
04038     mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign" ) );
04039 
04040   if ( composer.hasKey( "crypto-encrypt-to-self" ) )
04041     mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self" ) );
04042   if ( composer.hasKey( "crypto-show-encryption-result" ) )
04043     mWidget->mShowEncryptionResult->setChecked( composer.readBoolEntry( "crypto-show-encryption-result" ) );
04044   if ( composer.hasKey( "crypto-show-keys-for-approval" ) )
04045     mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval" ) );
04046   if ( composer.hasKey( "pgp-auto-encrypt" ) )
04047     mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt" ) );
04048   if ( composer.hasKey( "never-encrypt-drafts" ) )
04049     mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts" ) );
04050 
04051   if ( composer.hasKey( "crypto-store-encrypted" ) )
04052     mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted" ) );
04053 }
04054 
04055 void SecurityPage::ComposerCryptoTab::save() {
04056   KConfigGroup composer( KMKernel::config(), "Composer" );
04057 
04058   composer.writeEntry( "pgp-auto-sign", mWidget->mAutoSignature->isChecked() );
04059 
04060   composer.writeEntry( "crypto-encrypt-to-self", mWidget->mEncToSelf->isChecked() );
04061   composer.writeEntry( "crypto-show-encryption-result", mWidget->mShowEncryptionResult->isChecked() );
04062   composer.writeEntry( "crypto-show-keys-for-approval", mWidget->mShowKeyApprovalDlg->isChecked() );
04063 
04064   composer.writeEntry( "pgp-auto-encrypt", mWidget->mAutoEncrypt->isChecked() );
04065   composer.writeEntry( "never-encrypt-drafts", mWidget->mNeverEncryptWhenSavingInDrafts->isChecked() );
04066 
04067   composer.writeEntry( "crypto-store-encrypted", mWidget->mStoreEncrypted->isChecked() );
04068 }
04069 
04070 TQString SecurityPage::WarningTab::helpAnchor() const {
04071   return TQString::fromLatin1("configure-security-warnings");
04072 }
04073 
04074 SecurityPageWarningTab::SecurityPageWarningTab( TQWidget * parent, const char * name )
04075   : ConfigModuleTab( parent, name )
04076 {
04077   // the margins are inside mWidget itself
04078   TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
04079 
04080   mWidget = new WarningConfiguration( this );
04081   vlay->addWidget( mWidget );
04082 
04083   connect( mWidget->warnGroupBox, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04084   connect( mWidget->mWarnUnsigned, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04085   connect( mWidget->warnUnencryptedCB, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04086   connect( mWidget->warnReceiverNotInCertificateCB, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04087   connect( mWidget->mWarnSignKeyExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04088   connect( mWidget->mWarnSignChainCertExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04089   connect( mWidget->mWarnSignRootCertExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04090 
04091   connect( mWidget->mWarnEncrKeyExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04092   connect( mWidget->mWarnEncrChainCertExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04093   connect( mWidget->mWarnEncrRootCertExpiresSB, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotEmitChanged() ) );
04094 
04095   connect( mWidget->enableAllWarningsPB, TQT_SIGNAL(clicked()),
04096            TQT_SLOT(slotReenableAllWarningsClicked()) );
04097 }
04098 
04099 void SecurityPage::WarningTab::doLoadOther() {
04100   const KConfigGroup composer( KMKernel::config(), "Composer" );
04101 
04102   mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted", false ) );
04103   mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned", false ) );
04104   mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert", true ) );
04105 
04106   // The "-int" part of the key name is because there used to be a separate boolean
04107   // config entry for enabling/disabling. This is done with the single bool value now.
04108   mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire", true ) );
04109 
04110   mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int", 14 ) );
04111   mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int", 14 ) );
04112   mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int", 14 ) );
04113 
04114   mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int", 14 ) );
04115   mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int", 14 ) );
04116   mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int", 14 ) );
04117 
04118   mWidget->enableAllWarningsPB->setEnabled( true );
04119 }
04120 
04121 void SecurityPage::WarningTab::installProfile( KConfig * profile ) {
04122   const KConfigGroup composer( profile, "Composer" );
04123 
04124   if ( composer.hasKey( "crypto-warning-unencrypted" ) )
04125     mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted" ) );
04126   if ( composer.hasKey( "crypto-warning-unsigned" ) )
04127     mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned" ) );
04128   if ( composer.hasKey( "crypto-warn-recv-not-in-cert" ) )
04129     mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert" ) );
04130 
04131   if ( composer.hasKey( "crypto-warn-when-near-expire" ) )
04132     mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire" ) );
04133 
04134   if ( composer.hasKey( "crypto-warn-sign-key-near-expire-int" ) )
04135     mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int" ) );
04136   if ( composer.hasKey( "crypto-warn-sign-chaincert-near-expire-int" ) )
04137     mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int" ) );
04138   if ( composer.hasKey( "crypto-warn-sign-root-near-expire-int" ) )
04139     mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int" ) );
04140 
04141   if ( composer.hasKey( "crypto-warn-encr-key-near-expire-int" ) )
04142     mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int" ) );
04143   if ( composer.hasKey( "crypto-warn-encr-chaincert-near-expire-int" ) )
04144     mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int" ) );
04145   if ( composer.hasKey( "crypto-warn-encr-root-near-expire-int" ) )
04146     mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int" ) );
04147 }
04148 
04149 void SecurityPage::WarningTab::save() {
04150   KConfigGroup composer( KMKernel::config(), "Composer" );
04151 
04152   composer.writeEntry( "crypto-warn-recv-not-in-cert", mWidget->warnReceiverNotInCertificateCB->isChecked() );
04153   composer.writeEntry( "crypto-warning-unencrypted", mWidget->warnUnencryptedCB->isChecked() );
04154   composer.writeEntry( "crypto-warning-unsigned", mWidget->mWarnUnsigned->isChecked() );
04155 
04156   composer.writeEntry( "crypto-warn-when-near-expire", mWidget->warnGroupBox->isChecked() );
04157   composer.writeEntry( "crypto-warn-sign-key-near-expire-int",
04158                        mWidget->mWarnSignKeyExpiresSB->value() );
04159   composer.writeEntry( "crypto-warn-sign-chaincert-near-expire-int",
04160                        mWidget->mWarnSignChainCertExpiresSB->value() );
04161   composer.writeEntry( "crypto-warn-sign-root-near-expire-int",
04162                        mWidget->mWarnSignRootCertExpiresSB->value() );
04163 
04164   composer.writeEntry( "crypto-warn-encr-key-near-expire-int",
04165                        mWidget->mWarnEncrKeyExpiresSB->value() );
04166   composer.writeEntry( "crypto-warn-encr-chaincert-near-expire-int",
04167                        mWidget->mWarnEncrChainCertExpiresSB->value() );
04168   composer.writeEntry( "crypto-warn-encr-root-near-expire-int",
04169                        mWidget->mWarnEncrRootCertExpiresSB->value() );
04170 }
04171 
04172 void SecurityPage::WarningTab::slotReenableAllWarningsClicked() {
04173   KMessageBox::enableAllMessages();
04174   mWidget->enableAllWarningsPB->setEnabled( false );
04175 }
04176 
04178 
04179 TQString SecurityPage::SMimeTab::helpAnchor() const {
04180   return TQString::fromLatin1("configure-security-smime-validation");
04181 }
04182 
04183 SecurityPageSMimeTab::SecurityPageSMimeTab( TQWidget * parent, const char * name )
04184   : ConfigModuleTab( parent, name )
04185 {
04186   // the margins are inside mWidget itself
04187   TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
04188 
04189   mWidget = new SMimeConfiguration( this );
04190   vlay->addWidget( mWidget );
04191 
04192   // Button-group for exclusive radiobuttons
04193   TQButtonGroup* bg = new TQButtonGroup( mWidget );
04194   bg->hide();
04195   bg->insert( mWidget->CRLRB );
04196   bg->insert( mWidget->OCSPRB );
04197 
04198   // Settings for the keyrequester custom widget
04199   mWidget->OCSPResponderSignature->setAllowedKeys(
04200      Kleo::KeySelectionDialog::SMIMEKeys
04201      | Kleo::KeySelectionDialog::TrustedKeys
04202      | Kleo::KeySelectionDialog::ValidKeys
04203      | Kleo::KeySelectionDialog::SigningKeys
04204      | Kleo::KeySelectionDialog::PublicKeys );
04205   mWidget->OCSPResponderSignature->setMultipleKeysEnabled( false );
04206 
04207   mConfig = Kleo::CryptoBackendFactory::instance()->config();
04208 
04209   connect( mWidget->CRLRB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04210   connect( mWidget->OCSPRB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04211   connect( mWidget->OCSPResponderURL, TQT_SIGNAL( textChanged( const TQString& ) ), this, TQT_SLOT( slotEmitChanged() ) );
04212   connect( mWidget->OCSPResponderSignature, TQT_SIGNAL( changed() ), this, TQT_SLOT( slotEmitChanged() ) );
04213   connect( mWidget->doNotCheckCertPolicyCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04214   connect( mWidget->neverConsultCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04215   connect( mWidget->fetchMissingCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04216 
04217   connect( mWidget->ignoreServiceURLCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04218   connect( mWidget->ignoreHTTPDPCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04219   connect( mWidget->disableHTTPCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04220   connect( mWidget->honorHTTPProxyRB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04221   connect( mWidget->useCustomHTTPProxyRB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04222   connect( mWidget->customHTTPProxy, TQT_SIGNAL( textChanged( const TQString& ) ), this, TQT_SLOT( slotEmitChanged() ) );
04223   connect( mWidget->ignoreLDAPDPCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04224   connect( mWidget->disableLDAPCB, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( slotEmitChanged() ) );
04225   connect( mWidget->customLDAPProxy, TQT_SIGNAL( textChanged( const TQString& ) ), this, TQT_SLOT( slotEmitChanged() ) );
04226 
04227   connect( mWidget->disableHTTPCB, TQT_SIGNAL( toggled( bool ) ),
04228            this, TQT_SLOT( slotUpdateHTTPActions() ) );
04229   connect( mWidget->ignoreHTTPDPCB, TQT_SIGNAL( toggled( bool ) ),
04230            this, TQT_SLOT( slotUpdateHTTPActions() ) );
04231 
04232   // Button-group for exclusive radiobuttons
04233   TQButtonGroup* bgHTTPProxy = new TQButtonGroup( mWidget );
04234   bgHTTPProxy->hide();
04235   bgHTTPProxy->insert( mWidget->honorHTTPProxyRB );
04236   bgHTTPProxy->insert( mWidget->useCustomHTTPProxyRB );
04237 
04238   if ( !connectDCOPSignal( 0, "KPIM::CryptoConfig", "changed()",
04239                            "load()", false ) )
04240     kdError(5650) << "SecurityPageSMimeTab: connection to CryptoConfig's changed() failed" << endl;
04241 
04242 }
04243 
04244 SecurityPageSMimeTab::~SecurityPageSMimeTab()
04245 {
04246 }
04247 
04248 static void disableDirmngrWidget( TQWidget* w ) {
04249   w->setEnabled( false );
04250   TQWhatsThis::remove( w );
04251   TQWhatsThis::add( w, i18n( "This option requires dirmngr >= 0.9.0" ) );
04252 }
04253 
04254 static void initializeDirmngrCheckbox( TQCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
04255   if ( entry )
04256     cb->setChecked( entry->boolValue() );
04257   else
04258     disableDirmngrWidget( cb );
04259 }
04260 
04261 struct SMIMECryptoConfigEntries {
04262   SMIMECryptoConfigEntries( Kleo::CryptoConfig* config )
04263     : mConfig( config ) {
04264 
04265     // Checkboxes
04266     mCheckUsingOCSPConfigEntry = configEntry( "gpgsm", "Security", "enable-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
04267     mEnableOCSPsendingConfigEntry = configEntry( "dirmngr", "OCSP", "allow-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
04268     mDoNotCheckCertPolicyConfigEntry = configEntry( "gpgsm", "Security", "disable-policy-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
04269     mNeverConsultConfigEntry = configEntry( "gpgsm", "Security", "disable-crl-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
04270     mFetchMissingConfigEntry = configEntry( "gpgsm", "Security", "auto-issuer-key-retrieve", Kleo::CryptoConfigEntry::ArgType_None, false );
04271     // dirmngr-0.9.0 options
04272     mIgnoreServiceURLEntry = configEntry( "dirmngr", "OCSP", "ignore-ocsp-service-url", Kleo::CryptoConfigEntry::ArgType_None, false );
04273     mIgnoreHTTPDPEntry = configEntry( "dirmngr", "HTTP", "ignore-http-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
04274     mDisableHTTPEntry = configEntry( "dirmngr", "HTTP", "disable-http", Kleo::CryptoConfigEntry::ArgType_None, false );
04275     mHonorHTTPProxy = configEntry( "dirmngr", "HTTP", "honor-http-proxy", Kleo::CryptoConfigEntry::ArgType_None, false );
04276 
04277     mIgnoreLDAPDPEntry = configEntry( "dirmngr", "LDAP", "ignore-ldap-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
04278     mDisableLDAPEntry = configEntry( "dirmngr", "LDAP", "disable-ldap", Kleo::CryptoConfigEntry::ArgType_None, false );
04279     // Other widgets
04280     mOCSPResponderURLConfigEntry = configEntry( "dirmngr", "OCSP", "ocsp-responder", Kleo::CryptoConfigEntry::ArgType_String, false );
04281     mOCSPResponderSignature = configEntry( "dirmngr", "OCSP", "ocsp-signer", Kleo::CryptoConfigEntry::ArgType_String, false );
04282     mCustomHTTPProxy = configEntry( "dirmngr", "HTTP", "http-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
04283     mCustomLDAPProxy = configEntry( "dirmngr", "LDAP", "ldap-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
04284   }
04285 
04286   Kleo::CryptoConfigEntry* configEntry( const char* componentName,
04287                                         const char* groupName,
04288                                         const char* entryName,
04289                                         int argType,
04290                                         bool isList );
04291 
04292   // Checkboxes
04293   Kleo::CryptoConfigEntry* mCheckUsingOCSPConfigEntry;
04294   Kleo::CryptoConfigEntry* mEnableOCSPsendingConfigEntry;
04295   Kleo::CryptoConfigEntry* mDoNotCheckCertPolicyConfigEntry;
04296   Kleo::CryptoConfigEntry* mNeverConsultConfigEntry;
04297   Kleo::CryptoConfigEntry* mFetchMissingConfigEntry;
04298   Kleo::CryptoConfigEntry* mIgnoreServiceURLEntry;
04299   Kleo::CryptoConfigEntry* mIgnoreHTTPDPEntry;
04300   Kleo::CryptoConfigEntry* mDisableHTTPEntry;
04301   Kleo::CryptoConfigEntry* mHonorHTTPProxy;
04302   Kleo::CryptoConfigEntry* mIgnoreLDAPDPEntry;
04303   Kleo::CryptoConfigEntry* mDisableLDAPEntry;
04304   // Other widgets
04305   Kleo::CryptoConfigEntry* mOCSPResponderURLConfigEntry;
04306   Kleo::CryptoConfigEntry* mOCSPResponderSignature;
04307   Kleo::CryptoConfigEntry* mCustomHTTPProxy;
04308   Kleo::CryptoConfigEntry* mCustomLDAPProxy;
04309 
04310   Kleo::CryptoConfig* mConfig;
04311 };
04312 
04313 void SecurityPage::SMimeTab::doLoadOther() {
04314   if ( !mConfig ) {
04315     setEnabled( false );
04316     return;
04317   }
04318 
04319   // Force re-parsing gpgconf data, in case e.g. kleopatra or "configure backend" was used
04320   // (which ends up calling us via dcop)
04321   mConfig->clear();
04322 
04323   // Create config entries
04324   // Don't keep them around, they'll get deleted by clear(), which could be
04325   // done by the "configure backend" button even before we save().
04326   SMIMECryptoConfigEntries e( mConfig );
04327 
04328   // Initialize GUI items from the config entries
04329 
04330   if ( e.mCheckUsingOCSPConfigEntry ) {
04331     bool b = e.mCheckUsingOCSPConfigEntry->boolValue();
04332     mWidget->OCSPRB->setChecked( b );
04333     mWidget->CRLRB->setChecked( !b );
04334     mWidget->OCSPGroupBox->setEnabled( b );
04335   } else {
04336     mWidget->OCSPGroupBox->setEnabled( false );
04337   }
04338   if ( e.mDoNotCheckCertPolicyConfigEntry )
04339     mWidget->doNotCheckCertPolicyCB->setChecked( e.mDoNotCheckCertPolicyConfigEntry->boolValue() );
04340   if ( e.mNeverConsultConfigEntry )
04341     mWidget->neverConsultCB->setChecked( e.mNeverConsultConfigEntry->boolValue() );
04342   if ( e.mFetchMissingConfigEntry )
04343     mWidget->fetchMissingCB->setChecked( e.mFetchMissingConfigEntry->boolValue() );
04344 
04345   if ( e.mOCSPResponderURLConfigEntry )
04346     mWidget->OCSPResponderURL->setText( e.mOCSPResponderURLConfigEntry->stringValue() );
04347   if ( e.mOCSPResponderSignature ) {
04348     mWidget->OCSPResponderSignature->setFingerprint( e.mOCSPResponderSignature->stringValue() );
04349   }
04350 
04351   // dirmngr-0.9.0 options
04352   initializeDirmngrCheckbox( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
04353   initializeDirmngrCheckbox( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
04354   initializeDirmngrCheckbox( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
04355   initializeDirmngrCheckbox( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
04356   initializeDirmngrCheckbox( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
04357   if ( e.mCustomHTTPProxy ) {
04358     TQString systemProxy = TQString::fromLocal8Bit( getenv( "http_proxy" ) );
04359     if ( systemProxy.isEmpty() )
04360       systemProxy = i18n( "no proxy" );
04361     mWidget->systemHTTPProxy->setText( i18n( "(Current system setting: %1)" ).arg( systemProxy ) );
04362     bool honor = e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue();
04363     mWidget->honorHTTPProxyRB->setChecked( honor );
04364     mWidget->useCustomHTTPProxyRB->setChecked( !honor );
04365     mWidget->customHTTPProxy->setText( e.mCustomHTTPProxy->stringValue() );
04366   } else {
04367     disableDirmngrWidget( mWidget->honorHTTPProxyRB );
04368     disableDirmngrWidget( mWidget->useCustomHTTPProxyRB );
04369     disableDirmngrWidget( mWidget->systemHTTPProxy );
04370     disableDirmngrWidget( mWidget->customHTTPProxy );
04371   }
04372   if ( e.mCustomLDAPProxy )
04373     mWidget->customLDAPProxy->setText( e.mCustomLDAPProxy->stringValue() );
04374   else {
04375     disableDirmngrWidget( mWidget->customLDAPProxy );
04376     disableDirmngrWidget( mWidget->customLDAPLabel );
04377   }
04378   slotUpdateHTTPActions();
04379 }
04380 
04381 void SecurityPage::SMimeTab::slotUpdateHTTPActions() {
04382   mWidget->ignoreHTTPDPCB->setEnabled( !mWidget->disableHTTPCB->isChecked() );
04383 
04384   // The proxy settings only make sense when "Ignore HTTP CRL DPs of certificate" is checked.
04385   bool enableProxySettings = !mWidget->disableHTTPCB->isChecked()
04386                           && mWidget->ignoreHTTPDPCB->isChecked();
04387   mWidget->systemHTTPProxy->setEnabled( enableProxySettings );
04388   mWidget->useCustomHTTPProxyRB->setEnabled( enableProxySettings );
04389   mWidget->honorHTTPProxyRB->setEnabled( enableProxySettings );
04390   mWidget->customHTTPProxy->setEnabled( enableProxySettings );
04391 }
04392 
04393 void SecurityPage::SMimeTab::installProfile( KConfig * ) {
04394 }
04395 
04396 static void saveCheckBoxToKleoEntry( TQCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
04397   const bool b = cb->isChecked();
04398   if ( entry && entry->boolValue() != b )
04399     entry->setBoolValue( b );
04400 }
04401 
04402 void SecurityPage::SMimeTab::save() {
04403   if ( !mConfig ) {
04404     return;
04405   }
04406   // Create config entries
04407   // Don't keep them around, they'll get deleted by clear(), which could be done by the
04408   // "configure backend" button.
04409   SMIMECryptoConfigEntries e( mConfig );
04410 
04411   bool b = mWidget->OCSPRB->isChecked();
04412   if ( e.mCheckUsingOCSPConfigEntry && e.mCheckUsingOCSPConfigEntry->boolValue() != b )
04413     e.mCheckUsingOCSPConfigEntry->setBoolValue( b );
04414   // Set allow-ocsp together with enable-ocsp
04415   if ( e.mEnableOCSPsendingConfigEntry && e.mEnableOCSPsendingConfigEntry->boolValue() != b )
04416     e.mEnableOCSPsendingConfigEntry->setBoolValue( b );
04417 
04418   saveCheckBoxToKleoEntry( mWidget->doNotCheckCertPolicyCB, e.mDoNotCheckCertPolicyConfigEntry );
04419   saveCheckBoxToKleoEntry( mWidget->neverConsultCB, e.mNeverConsultConfigEntry );
04420   saveCheckBoxToKleoEntry( mWidget->fetchMissingCB, e.mFetchMissingConfigEntry );
04421 
04422   TQString txt = mWidget->OCSPResponderURL->text();
04423   if ( e.mOCSPResponderURLConfigEntry && e.mOCSPResponderURLConfigEntry->stringValue() != txt )
04424     e.mOCSPResponderURLConfigEntry->setStringValue( txt );
04425 
04426   txt = mWidget->OCSPResponderSignature->fingerprint();
04427   if ( e.mOCSPResponderSignature && e.mOCSPResponderSignature->stringValue() != txt ) {
04428     e.mOCSPResponderSignature->setStringValue( txt );
04429   }
04430 
04431   //dirmngr-0.9.0 options
04432   saveCheckBoxToKleoEntry( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
04433   saveCheckBoxToKleoEntry( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
04434   saveCheckBoxToKleoEntry( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
04435   saveCheckBoxToKleoEntry( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
04436   saveCheckBoxToKleoEntry( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
04437   if ( e.mCustomHTTPProxy ) {
04438     const bool honor = mWidget->honorHTTPProxyRB->isChecked();
04439     if ( e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue() != honor )
04440         e.mHonorHTTPProxy->setBoolValue( honor );
04441 
04442     TQString chosenProxy = mWidget->customHTTPProxy->text();
04443     if ( chosenProxy != e.mCustomHTTPProxy->stringValue() )
04444       e.mCustomHTTPProxy->setStringValue( chosenProxy );
04445   }
04446   txt = mWidget->customLDAPProxy->text();
04447   if ( e.mCustomLDAPProxy && e.mCustomLDAPProxy->stringValue() != txt )
04448     e.mCustomLDAPProxy->setStringValue( mWidget->customLDAPProxy->text() );
04449 
04450   mConfig->sync( true );
04451 }
04452 
04453 bool SecurityPageSMimeTab::process(const TQCString &fun, const TQByteArray &data, TQCString& replyType, TQByteArray &replyData)
04454 {
04455     if ( fun == "load()" ) {
04456         replyType = "void";
04457         load();
04458     } else {
04459         return DCOPObject::process( fun, data, replyType, replyData );
04460     }
04461     return true;
04462 }
04463 
04464 QCStringList SecurityPageSMimeTab::interfaces()
04465 {
04466   QCStringList ifaces = DCOPObject::interfaces();
04467   ifaces += "SecurityPageSMimeTab";
04468   return ifaces;
04469 }
04470 
04471 QCStringList SecurityPageSMimeTab::functions()
04472 {
04473   // Hide our slot, just because it's simpler to do so.
04474   return DCOPObject::functions();
04475 }
04476 
04477 Kleo::CryptoConfigEntry* SMIMECryptoConfigEntries::configEntry( const char* componentName,
04478                                                                 const char* groupName,
04479                                                                 const char* entryName,
04480                                                                 int /*Kleo::CryptoConfigEntry::ArgType*/ argType,
04481                                                                 bool isList )
04482 {
04483     Kleo::CryptoConfigEntry* entry = mConfig->entry( componentName, groupName, entryName );
04484     if ( !entry ) {
04485         kdWarning(5006) << TQString( "Backend error: gpgconf doesn't seem to know the entry for %1/%2/%3" ).arg( componentName, groupName, entryName ) << endl;
04486         return 0;
04487     }
04488     if( entry->argType() != argType || entry->isList() != isList ) {
04489         kdWarning(5006) << TQString( "Backend error: gpgconf has wrong type for %1/%2/%3: %4 %5" ).arg( componentName, groupName, entryName ).arg( entry->argType() ).arg( entry->isList() ) << endl;
04490         return 0;
04491     }
04492     return entry;
04493 }
04494 
04496 
04497 TQString SecurityPage::CryptPlugTab::helpAnchor() const {
04498   return TQString::fromLatin1("configure-security-crypto-backends");
04499 }
04500 
04501 SecurityPageCryptPlugTab::SecurityPageCryptPlugTab( TQWidget * parent, const char * name )
04502   : ConfigModuleTab( parent, name )
04503 {
04504   TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
04505 
04506   mBackendConfig = Kleo::CryptoBackendFactory::instance()->configWidget( this, "mBackendConfig" );
04507   connect( mBackendConfig, TQT_SIGNAL( changed( bool ) ), this, TQT_SIGNAL( changed( bool ) ) );
04508 
04509   vlay->addWidget( mBackendConfig );
04510 }
04511 
04512 SecurityPageCryptPlugTab::~SecurityPageCryptPlugTab()
04513 {
04514 
04515 }
04516 
04517 void SecurityPage::CryptPlugTab::doLoadOther() {
04518   mBackendConfig->load();
04519 }
04520 
04521 void SecurityPage::CryptPlugTab::save() {
04522   mBackendConfig->save();
04523 }
04524 
04525 // *************************************************************
04526 // *                                                           *
04527 // *                        MiscPage                           *
04528 // *                                                           *
04529 // *************************************************************
04530 TQString MiscPage::helpAnchor() const {
04531   return TQString::fromLatin1("configure-misc");
04532 }
04533 
04534 MiscPage::MiscPage( TQWidget * parent, const char * name )
04535   : ConfigModuleWithTabs( parent, name )
04536 {
04537   mFolderTab = new FolderTab();
04538   addTab( mFolderTab, i18n("&Folders") );
04539 
04540   mGroupwareTab = new GroupwareTab();
04541   addTab( mGroupwareTab, i18n("&Groupware") );
04542   load();
04543 }
04544 
04545 TQString MiscPage::FolderTab::helpAnchor() const {
04546   return TQString::fromLatin1("configure-misc-folders");
04547 }
04548 
04549 MiscPageFolderTab::MiscPageFolderTab( TQWidget * parent, const char * name )
04550   : ConfigModuleTab( parent, name )
04551 {
04552   // temp. vars:
04553   TQVBoxLayout *vlay;
04554   TQHBoxLayout *hlay;
04555   TQLabel      *label;
04556 
04557   vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
04558 
04559   // "confirm before emptying folder" check box: stretch 0
04560   mEmptyFolderConfirmCheck =
04561     new TQCheckBox( i18n("Corresponds to Folder->Move All Messages to Trash",
04562                         "Ask for co&nfirmation before moving all messages to "
04563                         "trash"),
04564                    this );
04565   vlay->addWidget( mEmptyFolderConfirmCheck );
04566   connect( mEmptyFolderConfirmCheck, TQT_SIGNAL( stateChanged( int ) ),
04567            this, TQT_SLOT( slotEmitChanged( void ) ) );
04568   mExcludeImportantFromExpiry =
04569     new TQCheckBox( i18n("E&xclude important messages from expiry"), this );
04570   vlay->addWidget( mExcludeImportantFromExpiry );
04571   connect( mExcludeImportantFromExpiry, TQT_SIGNAL( stateChanged( int ) ),
04572            this, TQT_SLOT( slotEmitChanged( void ) ) );
04573 
04574   // "when trying to find unread messages" combo + label: stretch 0
04575   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04576   mLoopOnGotoUnread = new TQComboBox( false, this );
04577   label = new TQLabel( mLoopOnGotoUnread,
04578            i18n("to be continued with \"do not loop\", \"loop in current folder\", "
04579                 "and \"loop in all folders\".",
04580                 "When trying to find unread messages:"), this );
04581   mLoopOnGotoUnread->insertStringList( TQStringList()
04582       << i18n("continuation of \"When trying to find unread messages:\"",
04583               "Do not Loop")
04584       << i18n("continuation of \"When trying to find unread messages:\"",
04585               "Loop in Current Folder")
04586       << i18n("continuation of \"When trying to find unread messages:\"",
04587               "Loop in All Folders"));
04588   hlay->addWidget( label );
04589   hlay->addWidget( mLoopOnGotoUnread, 1 );
04590   connect( mLoopOnGotoUnread, TQT_SIGNAL( activated( int ) ),
04591            this, TQT_SLOT( slotEmitChanged( void ) ) );
04592 
04593   // when entering a folder
04594   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04595   mActionEnterFolder = new TQComboBox( false, this );
04596   label = new TQLabel( mActionEnterFolder,
04597            i18n("to be continued with \"jump to first new message\", "
04598                 "\"jump to first unread or new message\","
04599                 "and \"jump to last selected message\".",
04600                 "When entering a folder:"), this );
04601   mActionEnterFolder->insertStringList( TQStringList()
04602       << i18n("continuation of \"When entering a folder:\"",
04603               "Jump to First New Message")
04604       << i18n("continuation of \"When entering a folder:\"",
04605               "Jump to First Unread or New Message")
04606       << i18n("continuation of \"When entering a folder:\"",
04607               "Jump to Last Selected Message")
04608       << i18n("continuation of \"When entering a folder:\"",
04609               "Jump to Newest Message")
04610       << i18n("continuation of \"When entering a folder:\"",
04611               "Jump to Oldest Message") );
04612   hlay->addWidget( label );
04613   hlay->addWidget( mActionEnterFolder, 1 );
04614   connect( mActionEnterFolder, TQT_SIGNAL( activated( int ) ),
04615            this, TQT_SLOT( slotEmitChanged( void ) ) );
04616 
04617   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04618   mDelayedMarkAsRead = new TQCheckBox( i18n("Mar&k selected message as read after"), this );
04619   hlay->addWidget( mDelayedMarkAsRead );
04620   mDelayedMarkTime = new KIntSpinBox( 0 /*min*/, 60 /*max*/, 1/*step*/,
04621                                       0 /*init*/, 10 /*base*/, this);
04622   mDelayedMarkTime->setSuffix( i18n(" sec") );
04623   mDelayedMarkTime->setEnabled( false ); // since mDelayedMarkAsREad is off
04624   hlay->addWidget( mDelayedMarkTime );
04625   hlay->addStretch( 1 );
04626   connect( mDelayedMarkTime, TQT_SIGNAL( valueChanged( int ) ),
04627            this, TQT_SLOT( slotEmitChanged( void ) ) );
04628   connect( mDelayedMarkAsRead, TQT_SIGNAL(toggled(bool)),
04629            mDelayedMarkTime, TQT_SLOT(setEnabled(bool)));
04630   connect( mDelayedMarkAsRead, TQT_SIGNAL(toggled(bool)),
04631            this , TQT_SLOT(slotEmitChanged( void )));
04632 
04633   // "show popup after Drag'n'Drop" checkbox: stretch 0
04634   mShowPopupAfterDnD =
04635     new TQCheckBox( i18n("Ask for action after &dragging messages to another folder"), this );
04636   vlay->addWidget( mShowPopupAfterDnD );
04637   connect( mShowPopupAfterDnD, TQT_SIGNAL( stateChanged( int ) ),
04638            this, TQT_SLOT( slotEmitChanged( void ) ) );
04639 
04640   // "default mailbox format" combo + label: stretch 0
04641   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04642   mMailboxPrefCombo = new TQComboBox( false, this );
04643   label = new TQLabel( mMailboxPrefCombo,
04644                       i18n("to be continued with \"flat files\" and "
04645                            "\"directories\", resp.",
04646                            "By default, &message folders on disk are:"), this );
04647   mMailboxPrefCombo->insertStringList( TQStringList()
04648           << i18n("continuation of \"By default, &message folders on disk are\"",
04649                   "Flat Files (\"mbox\" format)")
04650           << i18n("continuation of \"By default, &message folders on disk are\"",
04651                   "Directories (\"maildir\" format)") );
04652   // and now: add TQWhatsThis:
04653   TQString msg = i18n( "what's this help",
04654                       "<qt><p>This selects which mailbox format will be "
04655                       "the default for local folders:</p>"
04656                       "<p><b>mbox:</b> KMail's mail "
04657                       "folders are represented by a single file each. "
04658                       "Individual messages are separated from each other by a "
04659                       "line starting with \"From \". This saves space on "
04660                       "disk, but may be less robust, e.g. when moving messages "
04661                       "between folders.</p>"
04662                       "<p><b>maildir:</b> KMail's mail folders are "
04663                       "represented by real folders on disk. Individual messages "
04664                       "are separate files. This may waste a bit of space on "
04665                       "disk, but should be more robust, e.g. when moving "
04666                       "messages between folders.</p></qt>");
04667   TQWhatsThis::add( mMailboxPrefCombo, msg );
04668   TQWhatsThis::add( label, msg );
04669   hlay->addWidget( label );
04670   hlay->addWidget( mMailboxPrefCombo, 1 );
04671   connect( mMailboxPrefCombo, TQT_SIGNAL( activated( int ) ),
04672            this, TQT_SLOT( slotEmitChanged( void ) ) );
04673 
04674   // "On startup..." option:
04675   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04676   mOnStartupOpenFolder = new FolderRequester( this,
04677       kmkernel->getKMMainWidget()->folderTree() );
04678   label = new TQLabel( mOnStartupOpenFolder,
04679                       i18n("Open this folder on startup:"), this );
04680   hlay->addWidget( label );
04681   hlay->addWidget( mOnStartupOpenFolder, 1 );
04682   connect( mOnStartupOpenFolder, TQT_SIGNAL( folderChanged( KMFolder* ) ),
04683            this, TQT_SLOT( slotEmitChanged( void ) ) );
04684 
04685   // "Empty &trash on program exit" option:
04686   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04687   mEmptyTrashCheck = new TQCheckBox( i18n("Empty local &trash folder on program exit"),
04688                                     this );
04689   hlay->addWidget( mEmptyTrashCheck );
04690   connect( mEmptyTrashCheck, TQT_SIGNAL( stateChanged( int ) ),
04691            this, TQT_SLOT( slotEmitChanged( void ) ) );
04692 
04693 #ifdef HAVE_INDEXLIB
04694   // indexing enabled option:
04695   mIndexingEnabled = new TQCheckBox( i18n("Enable full text &indexing"), this );
04696   vlay->addWidget( mIndexingEnabled );
04697   connect( mIndexingEnabled, TQT_SIGNAL( stateChanged( int ) ),
04698            this, TQT_SLOT( slotEmitChanged( void ) ) );
04699 #endif
04700 
04701   // "Quota Units"
04702   hlay = new TQHBoxLayout( vlay ); // inherits spacing
04703   mQuotaCmbBox = new TQComboBox( false, this );
04704   label = new TQLabel( mQuotaCmbBox,
04705                       i18n("Quota units: "), this );
04706   mQuotaCmbBox->insertStringList( TQStringList()
04707                    << i18n("KB")
04708                    << i18n("MB")
04709                    << i18n("GB") );
04710   hlay->addWidget( label );
04711   hlay->addWidget( mQuotaCmbBox, 1 );
04712   connect( mQuotaCmbBox, TQT_SIGNAL( activated( int )  ), this, TQT_SLOT( slotEmitChanged( void ) ) );
04713 
04714   vlay->addStretch( 1 );
04715 
04716   // @TODO: Till, move into .kcgc file
04717   msg = i18n( "what's this help",
04718             "<qt><p>When jumping to the next unread message, it may occur "
04719             "that no more unread messages are below the current message.</p>"
04720             "<p><b>Do not loop:</b> The search will stop at the last message in "
04721             "the current folder.</p>"
04722             "<p><b>Loop in current folder:</b> The search will continue at the "
04723             "top of the message list, but not go to another folder.</p>"
04724             "<p><b>Loop in all folders:</b> The search will continue at the top of "
04725             "the message list. If no unread messages are found it will then continue "
04726             "to the next folder.</p>"
04727             "<p>Similarly, when searching for the previous unread message, "
04728             "the search will start from the bottom of the message list and continue to "
04729             "the previous folder depending on which option is selected.</p></qt>" );
04730   TQWhatsThis::add( mLoopOnGotoUnread, msg );
04731 
04732 #ifdef HAVE_INDEXLIB
04733  // this is probably overly pessimistic
04734   msg = i18n( "what's this help",
04735           "<qt><p>Full text indexing allows very fast searches on the content "
04736           "of your messages. When enabled, the search dialog will work very fast. "
04737           "Also, the search tool bar will select messages based on content.</p>"
04738           "<p>It takes up a certain amount of disk space "
04739           "(about half the disk space for the messages).</p>"
04740           "<p>After enabling, the index will need to be built, but you can continue to use KMail "
04741           "while this operation is running.</p>"
04742           "</qt>"
04743         );
04744 
04745   TQWhatsThis::add( mIndexingEnabled, msg );
04746 #endif
04747 }
04748 
04749 void MiscPage::FolderTab::doLoadFromGlobalSettings() {
04750   mExcludeImportantFromExpiry->setChecked( GlobalSettings::self()->excludeImportantMailFromExpiry() );
04751   // default = "Loop in current folder"
04752   mLoopOnGotoUnread->setCurrentItem( GlobalSettings::self()->loopOnGotoUnread() );
04753   mActionEnterFolder->setCurrentItem( GlobalSettings::self()->actionEnterFolder() );
04754   mDelayedMarkAsRead->setChecked( GlobalSettings::self()->delayedMarkAsRead() );
04755   mDelayedMarkTime->setValue( GlobalSettings::self()->delayedMarkTime() );
04756   mShowPopupAfterDnD->setChecked( GlobalSettings::self()->showPopupAfterDnD() );
04757   mQuotaCmbBox->setCurrentItem( GlobalSettings::self()->quotaUnit() );
04758 }
04759 
04760 void MiscPage::FolderTab::doLoadOther() {
04761   KConfigGroup general( KMKernel::config(), "General" );
04762 
04763   mEmptyTrashCheck->setChecked( general.readBoolEntry( "empty-trash-on-exit", true ) );
04764   mOnStartupOpenFolder->setFolder( general.readEntry( "startupFolder",
04765                                                   kmkernel->inboxFolder()->idString() ) );
04766   mEmptyFolderConfirmCheck->setChecked( general.readBoolEntry( "confirm-before-empty", true ) );
04767 
04768   int num = general.readNumEntry("default-mailbox-format", 1 );
04769   if ( num < 0 || num > 1 ) num = 1;
04770   mMailboxPrefCombo->setCurrentItem( num );
04771 
04772 #ifdef HAVE_INDEXLIB
04773   mIndexingEnabled->setChecked( kmkernel->msgIndex() && kmkernel->msgIndex()->isEnabled() );
04774 #endif
04775 }
04776 
04777 void MiscPage::FolderTab::save() {
04778   KConfigGroup general( KMKernel::config(), "General" );
04779 
04780   general.writeEntry( "empty-trash-on-exit", mEmptyTrashCheck->isChecked() );
04781   general.writeEntry( "confirm-before-empty", mEmptyFolderConfirmCheck->isChecked() );
04782   general.writeEntry( "default-mailbox-format", mMailboxPrefCombo->currentItem() );
04783   general.writeEntry( "startupFolder", mOnStartupOpenFolder->folder() ?
04784                                   mOnStartupOpenFolder->folder()->idString() : TQString::null );
04785 
04786   GlobalSettings::self()->setDelayedMarkAsRead( mDelayedMarkAsRead->isChecked() );
04787   GlobalSettings::self()->setDelayedMarkTime( mDelayedMarkTime->value() );
04788   GlobalSettings::self()->setActionEnterFolder( mActionEnterFolder->currentItem() );
04789   GlobalSettings::self()->setLoopOnGotoUnread( mLoopOnGotoUnread->currentItem() );
04790   GlobalSettings::self()->setShowPopupAfterDnD( mShowPopupAfterDnD->isChecked() );
04791   GlobalSettings::self()->setExcludeImportantMailFromExpiry(
04792         mExcludeImportantFromExpiry->isChecked() );
04793   GlobalSettings::self()->setQuotaUnit( mQuotaCmbBox->currentItem() );
04794 #ifdef HAVE_INDEXLIB
04795   if ( kmkernel->msgIndex() ) kmkernel->msgIndex()->setEnabled( mIndexingEnabled->isChecked() );
04796 #endif
04797 }
04798 
04799 TQString MiscPage::GroupwareTab::helpAnchor() const {
04800   return TQString::fromLatin1("configure-misc-groupware");
04801 }
04802 
04803 MiscPageGroupwareTab::MiscPageGroupwareTab( TQWidget* parent, const char* name )
04804   : ConfigModuleTab( parent, name )
04805 {
04806   TQBoxLayout* vlay = new TQVBoxLayout( this, KDialog::marginHint(),
04807                                       KDialog::spacingHint() );
04808   vlay->setAutoAdd( true );
04809 
04810   // IMAP resource setup
04811   TQVGroupBox* b1 = new TQVGroupBox( i18n("&IMAP Resource Folder Options"),
04812                                    this );
04813 
04814   mEnableImapResCB =
04815     new TQCheckBox( i18n("&Enable IMAP resource functionality"), b1 );
04816   TQToolTip::add( mEnableImapResCB,  i18n( "This enables the IMAP storage for "
04817                                           "the Kontact applications" ) );
04818   TQWhatsThis::add( mEnableImapResCB,
04819         i18n( GlobalSettings::self()->theIMAPResourceEnabledItem()->whatsThis().utf8() ) );
04820   connect( mEnableImapResCB, TQT_SIGNAL( stateChanged( int ) ),
04821            this, TQT_SLOT( slotEmitChanged( void ) ) );
04822 
04823   mBox = new TQWidget( b1 );
04824   TQGridLayout* grid = new TQGridLayout( mBox, 5, 2, 0, KDialog::spacingHint() );
04825   grid->setColStretch( 1, 1 );
04826   connect( mEnableImapResCB, TQT_SIGNAL( toggled(bool) ),
04827            mBox, TQT_SLOT( setEnabled(bool) ) );
04828 
04829   TQLabel* storageFormatLA = new TQLabel( i18n("&Format used for the groupware folders:"),
04830                                         mBox );
04831   TQString toolTip = i18n( "Choose the format to use to store the contents of the groupware folders." );
04832   TQString whatsThis = i18n( GlobalSettings::self()
04833         ->theIMAPResourceStorageFormatItem()->whatsThis().utf8() );
04834   grid->addWidget( storageFormatLA, 0, 0 );
04835   TQToolTip::add( storageFormatLA, toolTip );
04836   TQWhatsThis::add( storageFormatLA, whatsThis );
04837   mStorageFormatCombo = new TQComboBox( false, mBox );
04838   storageFormatLA->setBuddy( mStorageFormatCombo );
04839   TQStringList formatLst;
04840   formatLst << i18n("Deprecated Kolab1 (iCal/vCard)") << i18n("Kolab2 (XML)");
04841   mStorageFormatCombo->insertStringList( formatLst );
04842   grid->addWidget( mStorageFormatCombo, 0, 1 );
04843   TQToolTip::add( mStorageFormatCombo, toolTip );
04844   TQWhatsThis::add( mStorageFormatCombo, whatsThis );
04845   connect( mStorageFormatCombo, TQT_SIGNAL( activated( int ) ),
04846            this, TQT_SLOT( slotStorageFormatChanged( int ) ) );
04847 
04848   TQLabel* languageLA = new TQLabel( i18n("&Language of the groupware folders:"),
04849                                    mBox );
04850 
04851   toolTip = i18n( "Set the language of the folder names" );
04852   whatsThis = i18n( GlobalSettings::self()
04853         ->theIMAPResourceFolderLanguageItem()->whatsThis().utf8() );
04854   grid->addWidget( languageLA, 1, 0 );
04855   TQToolTip::add( languageLA, toolTip );
04856   TQWhatsThis::add( languageLA, whatsThis );
04857   mLanguageCombo = new TQComboBox( false, mBox );
04858   languageLA->setBuddy( mLanguageCombo );
04859   TQStringList lst;
04860   lst << i18n("English") << i18n("German") << i18n("French") << i18n("Dutch");
04861   mLanguageCombo->insertStringList( lst );
04862   grid->addWidget( mLanguageCombo, 1, 1 );
04863   TQToolTip::add( mLanguageCombo, toolTip );
04864   TQWhatsThis::add( mLanguageCombo, whatsThis );
04865   connect( mLanguageCombo, TQT_SIGNAL( activated( int ) ),
04866            this, TQT_SLOT( slotEmitChanged( void ) ) );
04867 
04868   mFolderComboLabel = new TQLabel( mBox ); // text depends on storage format
04869   toolTip = i18n( "Set the parent of the resource folders" );
04870   whatsThis = i18n( GlobalSettings::self()->theIMAPResourceFolderParentItem()->whatsThis().utf8() );
04871   TQToolTip::add( mFolderComboLabel, toolTip );
04872   TQWhatsThis::add( mFolderComboLabel, whatsThis );
04873   grid->addWidget( mFolderComboLabel, 2, 0 );
04874 
04875   mFolderComboStack = new TQWidgetStack( mBox );
04876   grid->addWidget( mFolderComboStack, 2, 1 );
04877 
04878   // First possibility in the widgetstack: a combo showing the list of all folders
04879   // This is used with the ical/vcard storage
04880   mFolderCombo = new FolderRequester( mBox,
04881       kmkernel->getKMMainWidget()->folderTree() );
04882   mFolderComboStack->addWidget( mFolderCombo, 0 );
04883   TQToolTip::add( mFolderCombo, toolTip );
04884   TQWhatsThis::add( mFolderCombo, whatsThis );
04885   connect( mFolderCombo, TQT_SIGNAL( folderChanged( KMFolder* ) ),
04886            this, TQT_SLOT( slotEmitChanged() ) );
04887 
04888   // Second possibility in the widgetstack: a combo showing the list of accounts
04889   // This is used with the kolab xml storage since the groupware folders
04890   // are always under the inbox.
04891   mAccountCombo = new KMail::AccountComboBox( mBox );
04892   mFolderComboStack->addWidget( mAccountCombo, 1 );
04893   TQToolTip::add( mAccountCombo, toolTip );
04894   TQWhatsThis::add( mAccountCombo, whatsThis );
04895   connect( mAccountCombo, TQT_SIGNAL( activated( int ) ),
04896            this, TQT_SLOT( slotEmitChanged() ) );
04897 
04898   mHideGroupwareFolders = new TQCheckBox( i18n( "&Hide groupware folders" ),
04899                                          mBox, "HideGroupwareFoldersBox" );
04900   grid->addMultiCellWidget( mHideGroupwareFolders, 3, 3, 0, 0 );
04901   TQToolTip::add( mHideGroupwareFolders,
04902                  i18n( "When this is checked, you will not see the IMAP "
04903                        "resource folders in the folder tree." ) );
04904   TQWhatsThis::add( mHideGroupwareFolders, i18n( GlobalSettings::self()
04905            ->hideGroupwareFoldersItem()->whatsThis().utf8() ) );
04906   connect( mHideGroupwareFolders, TQT_SIGNAL( toggled( bool ) ),
04907            this, TQT_SLOT( slotEmitChanged() ) );
04908 
04909   mOnlyShowGroupwareFolders = new TQCheckBox( i18n( "&Only show groupware folders for this account" ),
04910                                          mBox, "OnlyGroupwareFoldersBox" );
04911   grid->addMultiCellWidget( mOnlyShowGroupwareFolders, 3, 3, 1, 1 );
04912   TQToolTip::add( mOnlyShowGroupwareFolders,
04913                  i18n( "When this is checked, you will not see normal  "
04914                        "mail folders in the folder tree for the account "
04915                        "configured for groupware." ) );
04916   TQWhatsThis::add( mOnlyShowGroupwareFolders, i18n( GlobalSettings::self()
04917            ->showOnlyGroupwareFoldersForGroupwareAccountItem()->whatsThis().utf8() ) );
04918   connect( mOnlyShowGroupwareFolders, TQT_SIGNAL( toggled( bool ) ),
04919            this, TQT_SLOT( slotEmitChanged() ) );
04920 
04921   mSyncImmediately = new TQCheckBox( i18n( "Synchronize groupware changes immediately" ), mBox );
04922   TQToolTip::add( mSyncImmediately,
04923                  i18n( "Synchronize groupware changes in disconnected IMAP folders immediately when being online." ) );
04924   connect( mSyncImmediately, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04925   grid->addMultiCellWidget( mSyncImmediately, 4, 4, 0, 1 );
04926 
04927   mDeleteInvitations = new TQCheckBox(
04928              i18n( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReplyItem()->label().utf8() ), mBox );
04929   TQWhatsThis::add( mDeleteInvitations, i18n( GlobalSettings::self()
04930              ->deleteInvitationEmailsAfterSendingReplyItem()->whatsThis().utf8() ) );
04931     connect( mDeleteInvitations, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotEmitChanged()) );
04932     grid->addMultiCellWidget( mDeleteInvitations, 5, 5, 0, 1 );
04933 
04934   // Groupware functionality compatibility setup
04935   b1 = new TQVGroupBox( i18n("Groupware Compatibility && Legacy Options"), this );
04936 
04937   gBox = new TQVBox( b1 );
04938 #if 0
04939   // Currently believed to be disused.
04940   mEnableGwCB = new TQCheckBox( i18n("&Enable groupware functionality"), b1 );
04941   gBox->setSpacing( KDialog::spacingHint() );
04942   connect( mEnableGwCB, TQT_SIGNAL( toggled(bool) ),
04943            gBox, TQT_SLOT( setEnabled(bool) ) );
04944   connect( mEnableGwCB, TQT_SIGNAL( stateChanged( int ) ),
04945            this, TQT_SLOT( slotEmitChanged( void ) ) );
04946 #endif
04947   mEnableGwCB = 0;
04948   mLegacyMangleFromTo = new TQCheckBox( i18n( "Mangle From:/To: headers in replies to invitations" ), gBox );
04949   TQToolTip::add( mLegacyMangleFromTo, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitation replies" ) );
04950   TQWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
04951            legacyMangleFromToHeadersItem()->whatsThis().utf8() ) );
04952   connect( mLegacyMangleFromTo, TQT_SIGNAL( stateChanged( int ) ),
04953            this, TQT_SLOT( slotEmitChanged( void ) ) );
04954   mLegacyBodyInvites = new TQCheckBox( i18n( "Send invitations in the mail body" ), gBox );
04955   TQToolTip::add( mLegacyBodyInvites, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitations" ) );
04956   TQWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
04957            legacyBodyInvitesItem()->whatsThis().utf8() ) );
04958   connect( mLegacyBodyInvites, TQT_SIGNAL( toggled( bool ) ),
04959            this, TQT_SLOT( slotLegacyBodyInvitesToggled( bool ) ) );
04960   connect( mLegacyBodyInvites, TQT_SIGNAL( stateChanged( int ) ),
04961            this, TQT_SLOT( slotEmitChanged( void ) ) );
04962 
04963   mExchangeCompatibleInvitations = new TQCheckBox( i18n( "Exchange compatible invitation naming" ), gBox );
04964   TQToolTip::add( mExchangeCompatibleInvitations, i18n( "Outlook(tm), when used in combination with a Microsoft Exchange server,\nhas a problem understanding standards-compliant groupware e-mail.\nTurn this option on to send groupware invitations and replies in an Exchange compatible way." ) );
04965   TQWhatsThis::add( mExchangeCompatibleInvitations, i18n( GlobalSettings::self()->
04966            exchangeCompatibleInvitationsItem()->whatsThis().utf8() ) );
04967   connect( mExchangeCompatibleInvitations, TQT_SIGNAL( stateChanged( int ) ),
04968            this, TQT_SLOT( slotEmitChanged( void ) ) );
04969 
04970   mOutlookCompatibleInvitationComments = new TQCheckBox( i18n( "Outlook compatible invitation reply comments" ), gBox );
04971   TQToolTip::add( mOutlookCompatibleInvitationComments, i18n( "Send invitation reply comments in a way that Microsoft Outlook(tm) understands." ) );
04972   TQWhatsThis::add( mOutlookCompatibleInvitationComments, i18n( GlobalSettings::self()->
04973            outlookCompatibleInvitationReplyCommentsItem()->whatsThis().utf8() ) );
04974   connect( mOutlookCompatibleInvitationComments, TQT_SIGNAL( stateChanged( int ) ),
04975            this, TQT_SLOT( slotEmitChanged( void ) ) );
04976 
04977   mAutomaticSending = new TQCheckBox( i18n( "Automatic invitation sending" ), gBox );
04978   TQToolTip::add( mAutomaticSending, i18n( "When this is on, the user will not see the mail composer window. Invitation mails are sent automatically" ) );
04979   TQWhatsThis::add( mAutomaticSending, i18n( GlobalSettings::self()->
04980            automaticSendingItem()->whatsThis().utf8() ) );
04981   connect( mAutomaticSending, TQT_SIGNAL( stateChanged( int ) ),
04982            this, TQT_SLOT( slotEmitChanged( void ) ) );
04983 
04984   // Open space padding at the end
04985   new TQLabel( this );
04986 }
04987 
04988 void MiscPageGroupwareTab::slotLegacyBodyInvitesToggled( bool on )
04989 {
04990   if ( on ) {
04991     TQString txt = i18n( "<qt>Invitations are normally sent as attachments to "
04992                         "a mail. This switch changes the invitation mails to "
04993                         "be sent in the text of the mail instead; this is "
04994                         "necessary to send invitations and replies to "
04995                         "Microsoft Outlook.<br>But, when you do this, you no "
04996                         "longer get descriptive text that mail programs "
04997                         "can read; so, to people who have email programs "
04998                         "that do not understand the invitations, the "
04999                         "resulting messages look very odd.<br>People that have email "
05000                         "programs that do understand invitations will still "
05001                         "be able to work with this.</qt>" );
05002     KMessageBox::information( this, txt, TQString::null,
05003                               "LegacyBodyInvitesWarning" );
05004   }
05005   // Invitations in the body are autosent in any case (no point in editing raw ICAL)
05006   // So the autosend option is only available if invitations are sent as attachment.
05007   mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
05008 }
05009 
05010 void MiscPage::GroupwareTab::doLoadFromGlobalSettings() {
05011   if ( mEnableGwCB ) {
05012     mEnableGwCB->setChecked( GlobalSettings::self()->groupwareEnabled() );
05013     gBox->setEnabled( mEnableGwCB->isChecked() );
05014   }
05015 
05016   mLegacyMangleFromTo->setChecked( GlobalSettings::self()->legacyMangleFromToHeaders() );
05017   mLegacyBodyInvites->blockSignals( true );
05018 
05019   mLegacyBodyInvites->setChecked( GlobalSettings::self()->legacyBodyInvites() );
05020   mLegacyBodyInvites->blockSignals( false );
05021 
05022   mExchangeCompatibleInvitations->setChecked( GlobalSettings::self()->exchangeCompatibleInvitations() );
05023 
05024   mOutlookCompatibleInvitationComments->setChecked( GlobalSettings::self()->outlookCompatibleInvitationReplyComments() );
05025 
05026   mAutomaticSending->setChecked( GlobalSettings::self()->automaticSending() );
05027   mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
05028 
05029   // Read the IMAP resource config
05030   mEnableImapResCB->setChecked( GlobalSettings::self()->theIMAPResourceEnabled() );
05031   mBox->setEnabled( mEnableImapResCB->isChecked() );
05032 
05033   mHideGroupwareFolders->setChecked( GlobalSettings::self()->hideGroupwareFolders() );
05034   int i = GlobalSettings::self()->theIMAPResourceFolderLanguage();
05035   mLanguageCombo->setCurrentItem(i);
05036   i = GlobalSettings::self()->theIMAPResourceStorageFormat();
05037   mStorageFormatCombo->setCurrentItem(i);
05038   slotStorageFormatChanged( i );
05039   mOnlyShowGroupwareFolders->setChecked( GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount() );
05040   mSyncImmediately->setChecked( GlobalSettings::self()->immediatlySyncDIMAPOnGroupwareChanges() );
05041   mDeleteInvitations->setChecked( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReply() );
05042 
05043   TQString folderId( GlobalSettings::self()->theIMAPResourceFolderParent() );
05044   if( !folderId.isNull() && kmkernel->findFolderById( folderId ) ) {
05045     mFolderCombo->setFolder( folderId );
05046   } else {
05047     // Folder was deleted, we have to choose a new one
05048     mFolderCombo->setFolder( i18n( "<Choose a Folder>" ) );
05049   }
05050 
05051   KMAccount* selectedAccount = 0;
05052   int accountId = GlobalSettings::self()->theIMAPResourceAccount();
05053   if ( accountId )
05054     selectedAccount = kmkernel->acctMgr()->find( accountId );
05055   else {
05056     // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
05057       for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
05058          a = kmkernel->acctMgr()->next() ) {
05059       if( a->folder() && a->folder()->child() ) {
05060         // Look inside that folder for an INBOX
05061         KMFolderNode *node;
05062         for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next())
05063           if (!node->isDir() && node->name() == "INBOX") break;
05064 
05065         if ( node && static_cast<KMFolder*>(node)->idString() == folderId ) {
05066           selectedAccount = a;
05067           break;
05068         }
05069       }
05070     }
05071   }
05072   if ( selectedAccount )
05073     mAccountCombo->setCurrentAccount( selectedAccount );
05074   else if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == 1 )
05075     kdDebug(5006) << "Folder " << folderId << " not found as an account's inbox" << endl;
05076 }
05077 
05078 void MiscPage::GroupwareTab::save() {
05079   KConfigGroup groupware( KMKernel::config(), "Groupware" );
05080 
05081   // Write the groupware config
05082   if ( mEnableGwCB ) {
05083     groupware.writeEntry( "GroupwareEnabled", mEnableGwCB->isChecked() );
05084   }
05085   groupware.writeEntry( "LegacyMangleFromToHeaders", mLegacyMangleFromTo->isChecked() );
05086   groupware.writeEntry( "LegacyBodyInvites", mLegacyBodyInvites->isChecked() );
05087   groupware.writeEntry( "ExchangeCompatibleInvitations", mExchangeCompatibleInvitations->isChecked() );
05088   groupware.writeEntry( "OutlookCompatibleInvitationReplyComments", mOutlookCompatibleInvitationComments->isChecked() );
05089   groupware.writeEntry( "AutomaticSending", mAutomaticSending->isChecked() );
05090 
05091   if ( mEnableGwCB ) {
05092     GlobalSettings::self()->setGroupwareEnabled( mEnableGwCB->isChecked() );
05093   }
05094   GlobalSettings::self()->setLegacyMangleFromToHeaders( mLegacyMangleFromTo->isChecked() );
05095   GlobalSettings::self()->setLegacyBodyInvites( mLegacyBodyInvites->isChecked() );
05096   GlobalSettings::self()->setExchangeCompatibleInvitations( mExchangeCompatibleInvitations->isChecked() );
05097   GlobalSettings::self()->setOutlookCompatibleInvitationReplyComments( mOutlookCompatibleInvitationComments->isChecked() );
05098   GlobalSettings::self()->setAutomaticSending( mAutomaticSending->isChecked() );
05099 
05100   int format = mStorageFormatCombo->currentItem();
05101   GlobalSettings::self()->setTheIMAPResourceStorageFormat( format );
05102 
05103   // Write the IMAP resource config
05104   GlobalSettings::self()->setHideGroupwareFolders( mHideGroupwareFolders->isChecked() );
05105   GlobalSettings::self()->setShowOnlyGroupwareFoldersForGroupwareAccount( mOnlyShowGroupwareFolders->isChecked() );
05106   GlobalSettings::self()->setImmediatlySyncDIMAPOnGroupwareChanges( mSyncImmediately->isChecked() );
05107   GlobalSettings::self()->setDeleteInvitationEmailsAfterSendingReply( mDeleteInvitations->isChecked() );
05108 
05109   // If there is a leftover folder in the foldercombo, getFolder can
05110   // return 0. In that case we really don't have it enabled
05111   TQString folderId;
05112   if (  format == 0 ) {
05113     KMFolder* folder = mFolderCombo->folder();
05114     if (  folder )
05115       folderId = folder->idString();
05116     KMAccount* account = 0;
05117     // Didn't find an easy way to find the account for a given folder...
05118     // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
05119     for( KMAccount *a = kmkernel->acctMgr()->first();
05120         a && !account; // stop when found
05121         a = kmkernel->acctMgr()->next() ) {
05122       if( a->folder() && a->folder()->child() ) {
05123         KMFolderNode *node;
05124         for ( node = a->folder()->child()->first(); node; node = a->folder()->child()->next() )
05125         {
05126           if ( static_cast<KMFolder*>(node) == folder ) {
05127             account = a;
05128             break;
05129           }
05130         }
05131       }
05132     }
05133     GlobalSettings::self()->setTheIMAPResourceAccount( account ? account->id() : 0 );
05134   } else {
05135     // Inbox folder of the selected account
05136     KMAccount* acct = mAccountCombo->currentAccount();
05137     if (  acct ) {
05138       folderId = TQString( ".%1.directory/INBOX" ).arg( acct->id() );
05139       GlobalSettings::self()->setTheIMAPResourceAccount( acct->id() );
05140     }
05141   }
05142 
05143   bool enabled = mEnableImapResCB->isChecked() && !folderId.isEmpty();
05144   GlobalSettings::self()->setTheIMAPResourceEnabled( enabled );
05145   GlobalSettings::self()->setTheIMAPResourceFolderLanguage( mLanguageCombo->currentItem() );
05146   GlobalSettings::self()->setTheIMAPResourceFolderParent( folderId );
05147 }
05148 
05149 void MiscPage::GroupwareTab::slotStorageFormatChanged( int format )
05150 {
05151   mLanguageCombo->setEnabled( format == 0 ); // only ical/vcard needs the language hack
05152   mFolderComboStack->raiseWidget( format );
05153   if ( format == 0 ) {
05154     mFolderComboLabel->setText( i18n("&Resource folders are subfolders of:") );
05155     mFolderComboLabel->setBuddy( mFolderCombo );
05156   } else {
05157     mFolderComboLabel->setText( i18n("&Resource folders are in account:") );
05158     mFolderComboLabel->setBuddy( mAccountCombo );
05159   }
05160   slotEmitChanged();
05161 }
05162 
05163 
05164 // *************************************************************
05165 // *                                                           *
05166 // *                     AccountUpdater                        *
05167 // *                                                           *
05168 // *************************************************************
05169 AccountUpdater::AccountUpdater(ImapAccountBase *account)
05170     : TQObject()
05171 {
05172   mAccount = account;
05173 }
05174 
05175 void AccountUpdater::update()
05176 {
05177   connect( mAccount, TQT_SIGNAL( connectionResult(int, const TQString&) ),
05178           this, TQT_SLOT( namespacesFetched() ) );
05179   mAccount->makeConnection();
05180 }
05181 
05182 void AccountUpdater::namespacesFetched()
05183 {
05184   mAccount->setCheckingMail( true );
05185   mAccount->processNewMail( false );
05186   deleteLater();
05187 }
05188 
05189 #undef DIM
05190 
05191 //----------------------------
05192 #include "configuredialog.moc"