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