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