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