kmail

configuredialog.cpp
1 /*
2  * kmail: KDE mail client
3  * This file: Copyright (C) 2000 Espen Sand, espen@kde.org
4  * Copyright (C) 2001-2003 Marc Mutz, mutz@kde.org
5  * Contains code segments and ideas from earlier kmail dialog code.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 // This must be first
24 #include <config.h>
25 
26 // my headers:
27 #include "configuredialog.h"
28 #include "configuredialog_p.h"
29 
30 #include "globalsettings.h"
31 #include "replyphrases.h"
32 #include "templatesconfiguration_kfg.h"
33 
34 // other KMail headers:
35 #include "kmkernel.h"
36 #include "simplestringlisteditor.h"
37 #include "accountdialog.h"
38 using KMail::AccountDialog;
39 #include "colorlistbox.h"
40 #include "kmacctseldlg.h"
41 #include "messagesender.h"
42 #include "kmtransport.h"
43 #include "kmfoldermgr.h"
44 #include <libkpimidentities/identitymanager.h>
45 #include "identitylistview.h"
48 #include "kcursorsaver.h"
49 #include "accountmanager.h"
50 #include <composercryptoconfiguration.h>
51 #include <warningconfiguration.h>
52 #include <smimeconfiguration.h>
53 #include "templatesconfiguration.h"
54 #include "customtemplates.h"
55 #include "folderrequester.h"
57 #include "accountcombobox.h"
58 #include "imapaccountbase.h"
59 using KMail::ImapAccountBase;
60 #include "folderstorage.h"
61 #include "kmfolder.h"
62 #include "kmmainwidget.h"
63 #include "recentaddresses.h"
64 using TDERecentAddress::RecentAddresses;
65 #include "completionordereditor.h"
66 #include "ldapclient.h"
67 #include "index.h"
68 
71 #include "identitydialog.h"
72 using KMail::IdentityDialog;
73 
74 // other tdenetwork headers:
75 #include <libkpimidentities/identity.h>
76 #include <kmime_util.h>
77 using KMime::DateFormatter;
78 #include <kleo/cryptoconfig.h>
79 #include <kleo/cryptobackendfactory.h>
80 #include <ui/backendconfigwidget.h>
81 #include <ui/keyrequester.h>
82 #include <ui/keyselectiondialog.h>
83 
84 // other KDE headers:
85 #include <tdelocale.h>
86 #include <tdeapplication.h>
87 #include <kcharsets.h>
88 #include <kdebug.h>
89 #include <knuminput.h>
90 #include <tdefontdialog.h>
91 #include <tdemessagebox.h>
92 #include <kurlrequester.h>
93 #include <kseparator.h>
94 #include <kiconloader.h>
95 #include <kstandarddirs.h>
96 #include <twin.h>
97 #include <knotifydialog.h>
98 #include <tdeconfig.h>
99 #include <kactivelabel.h>
100 #include <kcmultidialog.h>
101 #include <kcombobox.h>
102 
103 // TQt headers:
104 #include <tqvalidator.h>
105 #include <tqwhatsthis.h>
106 #include <tqvgroupbox.h>
107 #include <tqvbox.h>
108 #include <tqvbuttongroup.h>
109 #include <tqhbuttongroup.h>
110 #include <tqtooltip.h>
111 #include <tqlabel.h>
112 #include <tqtextcodec.h>
113 #include <tqheader.h>
114 #include <tqpopupmenu.h>
115 #include <tqradiobutton.h>
116 #include <tqlayout.h>
117 #include <tqcheckbox.h>
118 #include <tqwidgetstack.h>
119 #include <tqglobal.h>
120 
121 // other headers:
122 #include <assert.h>
123 #include <stdlib.h>
124 
125 #ifndef _PATH_SENDMAIL
126 #define _PATH_SENDMAIL "/usr/sbin/sendmail"
127 #endif
128 
129 #ifdef DIM
130 #undef DIM
131 #endif
132 #define DIM(x) sizeof(x) / sizeof(*x)
133 
134 namespace {
135 
136  struct EnumConfigEntryItem {
137  const char * key; // config key value, as appears in config file
138  const char * desc; // description, to be i18n()ized
139  };
140  struct EnumConfigEntry {
141  const char * group;
142  const char * key;
143  const char * desc;
144  const EnumConfigEntryItem * items;
145  int numItems;
146  int defaultItem;
147  };
148  struct BoolConfigEntry {
149  const char * group;
150  const char * key;
151  const char * desc;
152  bool defaultValue;
153  };
154 
155  static const char * lockedDownWarning =
156  I18N_NOOP("<qt><p>This setting has been fixed by your administrator.</p>"
157  "<p>If you think this is an error, please contact him.</p></qt>");
158 
159  void checkLockDown( TQWidget * w, const TDEConfigBase & c, const char * key ) {
160  if ( c.entryIsImmutable( key ) ) {
161  w->setEnabled( false );
162  TQToolTip::add( w, i18n( lockedDownWarning ) );
163  } else {
164  TQToolTip::remove( w );
165  }
166  }
167 
168  void populateButtonGroup( TQButtonGroup * g, const EnumConfigEntry & e ) {
169  g->setTitle( i18n( e.desc ) );
170  g->layout()->setSpacing( KDialog::spacingHint() );
171  for ( int i = 0 ; i < e.numItems ; ++i )
172  g->insert( new TQRadioButton( i18n( e.items[i].desc ), g ), i );
173  }
174 
175  void populateCheckBox( TQCheckBox * b, const BoolConfigEntry & e ) {
176  b->setText( i18n( e.desc ) );
177  }
178 
179  void loadWidget( TQCheckBox * b, const TDEConfigBase & c, const BoolConfigEntry & e ) {
180  Q_ASSERT( c.group() == e.group );
181  checkLockDown( b, c, e.key );
182  b->setChecked( c.readBoolEntry( e.key, e.defaultValue ) );
183  }
184 
185  void loadWidget( TQButtonGroup * g, const TDEConfigBase & c, const EnumConfigEntry & e ) {
186  Q_ASSERT( c.group() == e.group );
187  Q_ASSERT( g->count() == e.numItems );
188  checkLockDown( g, c, e.key );
189  const TQString s = c.readEntry( e.key, e.items[e.defaultItem].key );
190  for ( int i = 0 ; i < e.numItems ; ++i )
191  if ( s == e.items[i].key ) {
192  g->setButton( i );
193  return;
194  }
195  g->setButton( e.defaultItem );
196  }
197 
198  void saveCheckBox( TQCheckBox * b, TDEConfigBase & c, const BoolConfigEntry & e ) {
199  Q_ASSERT( c.group() == e.group );
200  c.writeEntry( e.key, b->isChecked() );
201  }
202 
203  void saveButtonGroup( TQButtonGroup * g, TDEConfigBase & c, const EnumConfigEntry & e ) {
204  Q_ASSERT( c.group() == e.group );
205  Q_ASSERT( g->count() == e.numItems );
206  c.writeEntry( e.key, e.items[ g->id( g->selected() ) ].key );
207  }
208 
209  template <typename T_Widget, typename T_Entry>
210  inline void loadProfile( T_Widget * g, const TDEConfigBase & c, const T_Entry & e ) {
211  if ( c.hasKey( e.key ) )
212  loadWidget( g, c, e );
213  }
214 }
215 
216 
217 ConfigureDialog::ConfigureDialog( TQWidget *parent, const char *name, bool modal )
218  : KCMultiDialog( KDialogBase::IconList, KGuiItem( i18n( "&Load Profile..." ) ),
219  KGuiItem(), User2, i18n( "Configure" ), parent, name, modal )
220  , mProfileDialog( 0 )
221 {
222  KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
223  showButton( User1, true );
224 
225  addModule ( "kmail_config_identity", false );
226  addModule ( "kmail_config_accounts", false );
227  addModule ( "kmail_config_appearance", false );
228  addModule ( "kmail_config_composer", false );
229  addModule ( "kmail_config_security", false );
230  addModule ( "kmail_config_misc", false );
231 
232  // We store the size of the dialog on hide, because otherwise
233  // the KCMultiDialog starts with the size of the first kcm, not
234  // the largest one. This way at least after the first showing of
235  // the largest kcm the size is kept.
236  TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
237  int width = geometry.readNumEntry( "ConfigureDialogWidth" );
238  int height = geometry.readNumEntry( "ConfigureDialogHeight" );
239  if ( width != 0 && height != 0 ) {
240  setMinimumSize( width, height );
241  }
242 
243 }
244 
245 void ConfigureDialog::hideEvent( TQHideEvent *ev ) {
246  TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
247  geometry.writeEntry( "ConfigureDialogWidth", width() );
248  geometry.writeEntry( "ConfigureDialogHeight",height() );
249  KDialogBase::hideEvent( ev );
250 }
251 
252 ConfigureDialog::~ConfigureDialog() {
253 }
254 
255 void ConfigureDialog::slotApply() {
256  KCMultiDialog::slotApply();
257  GlobalSettings::self()->writeConfig();
258  emit configChanged();
259 }
260 
261 void ConfigureDialog::slotOk() {
262  KCMultiDialog::slotOk();
263  GlobalSettings::self()->writeConfig();
264  emit configChanged();
265 }
266 
267 void ConfigureDialog::slotUser2() {
268  if ( mProfileDialog ) {
269  mProfileDialog->raise();
270  return;
271  }
272  mProfileDialog = new ProfileDialog( this, "mProfileDialog" );
273  connect( mProfileDialog, TQ_SIGNAL(profileSelected(TDEConfig*)),
274  this, TQ_SIGNAL(installProfile(TDEConfig*)) );
275  mProfileDialog->show();
276 }
277 
278 // *************************************************************
279 // * *
280 // * IdentityPage *
281 // * *
282 // *************************************************************
283 TQString IdentityPage::helpAnchor() const {
284  return TQString::fromLatin1("configure-identity");
285 }
286 
287 IdentityPage::IdentityPage( TQWidget * parent, const char * name )
288  : ConfigModule( parent, name ),
289  mIdentityDialog( 0 )
290 {
291  TQHBoxLayout * hlay = new TQHBoxLayout( this, 0, KDialog::spacingHint() );
292 
293  mIdentityList = new IdentityListView( this );
294  connect( mIdentityList, TQ_SIGNAL(selectionChanged()),
295  TQ_SLOT(slotIdentitySelectionChanged()) );
296  connect( mIdentityList, TQ_SIGNAL(itemRenamed(TQListViewItem*,const TQString&,int)),
297  TQ_SLOT(slotRenameIdentity(TQListViewItem*,const TQString&,int)) );
298  connect( mIdentityList, TQ_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&,int)),
299  TQ_SLOT(slotModifyIdentity()) );
300  connect( mIdentityList, TQ_SIGNAL(contextMenu(TDEListView*,TQListViewItem*,const TQPoint&)),
301  TQ_SLOT(slotContextMenu(TDEListView*,TQListViewItem*,const TQPoint&)) );
302  // ### connect dragged(...), ...
303 
304  hlay->addWidget( mIdentityList, 1 );
305 
306  TQVBoxLayout * vlay = new TQVBoxLayout( hlay ); // inherits spacing
307 
308  TQPushButton * button = new TQPushButton( i18n("&Add..."), this );
309  mModifyButton = new TQPushButton( i18n("&Modify..."), this );
310  mRenameButton = new TQPushButton( i18n("&Rename"), this );
311  mRemoveButton = new TQPushButton( i18n("Remo&ve"), this );
312  mSetAsDefaultButton = new TQPushButton( i18n("Set as &Default"), this );
313  button->setAutoDefault( false );
314  mModifyButton->setAutoDefault( false );
315  mModifyButton->setEnabled( false );
316  mRenameButton->setAutoDefault( false );
317  mRenameButton->setEnabled( false );
318  mRemoveButton->setAutoDefault( false );
319  mRemoveButton->setEnabled( false );
320  mSetAsDefaultButton->setAutoDefault( false );
321  mSetAsDefaultButton->setEnabled( false );
322  connect( button, TQ_SIGNAL(clicked()),
323  this, TQ_SLOT(slotNewIdentity()) );
324  connect( mModifyButton, TQ_SIGNAL(clicked()),
325  this, TQ_SLOT(slotModifyIdentity()) );
326  connect( mRenameButton, TQ_SIGNAL(clicked()),
327  this, TQ_SLOT(slotRenameIdentity()) );
328  connect( mRemoveButton, TQ_SIGNAL(clicked()),
329  this, TQ_SLOT(slotRemoveIdentity()) );
330  connect( mSetAsDefaultButton, TQ_SIGNAL(clicked()),
331  this, TQ_SLOT(slotSetAsDefault()) );
332  vlay->addWidget( button );
333  vlay->addWidget( mModifyButton );
334  vlay->addWidget( mRenameButton );
335  vlay->addWidget( mRemoveButton );
336  vlay->addWidget( mSetAsDefaultButton );
337  vlay->addStretch( 1 );
338  load();
339 }
340 
341 void IdentityPage::load()
342 {
343  KPIM::IdentityManager * im = kmkernel->identityManager();
344  mOldNumberOfIdentities = im->shadowIdentities().count();
345  // Fill the list:
346  mIdentityList->clear();
347  TQListViewItem * item = 0;
348  for ( KPIM::IdentityManager::Iterator it = im->modifyBegin() ; it != im->modifyEnd() ; ++it )
349  item = new IdentityListViewItem( mIdentityList, item, *it );
350  mIdentityList->setSelected( mIdentityList->currentItem(), true );
351 }
352 
353 void IdentityPage::save() {
354  assert( !mIdentityDialog );
355 
356  kmkernel->identityManager()->sort();
357  kmkernel->identityManager()->commit();
358 
359  if( mOldNumberOfIdentities < 2 && mIdentityList->childCount() > 1 ) {
360  // have more than one identity, so better show the combo in the
361  // composer now:
362  TDEConfigGroup composer( KMKernel::config(), "Composer" );
363  int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
364  showHeaders |= HDR_IDENTITY;
365  composer.writeEntry( "headers", showHeaders );
366  }
367  // and now the reverse
368  if( mOldNumberOfIdentities > 1 && mIdentityList->childCount() < 2 ) {
369  // have only one identity, so remove the combo in the composer:
370  TDEConfigGroup composer( KMKernel::config(), "Composer" );
371  int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
372  showHeaders &= ~HDR_IDENTITY;
373  composer.writeEntry( "headers", showHeaders );
374  }
375 }
376 
377 void IdentityPage::slotNewIdentity()
378 {
379  assert( !mIdentityDialog );
380 
381  KPIM::IdentityManager * im = kmkernel->identityManager();
382  NewIdentityDialog dialog( im->shadowIdentities(), this, "new", true );
383 
384  if( dialog.exec() == TQDialog::Accepted ) {
385  TQString identityName = dialog.identityName().stripWhiteSpace();
386  assert( !identityName.isEmpty() );
387 
388  //
389  // Construct a new Identity:
390  //
391  switch ( dialog.duplicateMode() ) {
392  case NewIdentityDialog::ExistingEntry:
393  {
394  KPIM::Identity & dupThis = im->modifyIdentityForName( dialog.duplicateIdentity() );
395  im->newFromExisting( dupThis, identityName );
396  break;
397  }
398  case NewIdentityDialog::ControlCenter:
399  im->newFromControlCenter( identityName );
400  break;
401  case NewIdentityDialog::Empty:
402  im->newFromScratch( identityName );
403  default: ;
404  }
405 
406  //
407  // Insert into listview:
408  //
409  KPIM::Identity & newIdent = im->modifyIdentityForName( identityName );
410  TQListViewItem * item = mIdentityList->selectedItem();
411  if ( item )
412  item = item->itemAbove();
413  mIdentityList->setSelected( new IdentityListViewItem( mIdentityList,
414  /*after*/ item,
415  newIdent ), true );
416  slotModifyIdentity();
417  }
418 }
419 
420 void IdentityPage::slotModifyIdentity() {
421  assert( !mIdentityDialog );
422 
423  IdentityListViewItem * item =
424  dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
425  if ( !item ) return;
426 
427  mIdentityDialog = new IdentityDialog( this );
428  mIdentityDialog->setIdentity( item->identity() );
429 
430  // Hmm, an unmodal dialog would be nicer, but a modal one is easier ;-)
431  if ( mIdentityDialog->exec() == TQDialog::Accepted ) {
432  mIdentityDialog->updateIdentity( item->identity() );
433  item->redisplay();
434  emit changed(true);
435  }
436 
437  delete mIdentityDialog;
438  mIdentityDialog = 0;
439 }
440 
441 void IdentityPage::slotRemoveIdentity()
442 {
443  assert( !mIdentityDialog );
444 
445  KPIM::IdentityManager * im = kmkernel->identityManager();
446  kdFatal( im->shadowIdentities().count() < 2 )
447  << "Attempted to remove the last identity!" << endl;
448 
449  IdentityListViewItem * item =
450  dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
451  if ( !item ) return;
452 
453  TQString msg = i18n("<qt>Do you really want to remove the identity named "
454  "<b>%1</b>?</qt>").arg( item->identity().identityName() );
455  if( KMessageBox::warningContinueCancel( this, msg, i18n("Remove Identity"),
456  KGuiItem(i18n("&Remove"),"edit-delete") ) == KMessageBox::Continue )
457  if ( im->removeIdentity( item->identity().identityName() ) ) {
458  delete item;
459  mIdentityList->setSelected( mIdentityList->currentItem(), true );
460  refreshList();
461  }
462 }
463 
464 void IdentityPage::slotRenameIdentity() {
465  assert( !mIdentityDialog );
466 
467  TQListViewItem * item = mIdentityList->selectedItem();
468  if ( !item ) return;
469 
470  mIdentityList->rename( item, 0 );
471 }
472 
473 void IdentityPage::slotRenameIdentity( TQListViewItem * i,
474  const TQString & s, int col ) {
475  assert( col == 0 );
476  Q_UNUSED( col );
477 
478  IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
479  if ( !item ) return;
480 
481  TQString newName = s.stripWhiteSpace();
482  if ( !newName.isEmpty() &&
483  !kmkernel->identityManager()->shadowIdentities().contains( newName ) ) {
484  KPIM::Identity & ident = item->identity();
485  ident.setIdentityName( newName );
486  emit changed(true);
487  }
488  item->redisplay();
489 }
490 
491 void IdentityPage::slotContextMenu( TDEListView *, TQListViewItem * i,
492  const TQPoint & pos ) {
493  IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
494 
495  TQPopupMenu * menu = new TQPopupMenu( this );
496  menu->insertItem( i18n("Add..."), this, TQ_SLOT(slotNewIdentity()) );
497  if ( item ) {
498  menu->insertItem( i18n("Modify..."), this, TQ_SLOT(slotModifyIdentity()) );
499  if ( mIdentityList->childCount() > 1 )
500  menu->insertItem( i18n("Remove"), this, TQ_SLOT(slotRemoveIdentity()) );
501  if ( !item->identity().isDefault() )
502  menu->insertItem( i18n("Set as Default"), this, TQ_SLOT(slotSetAsDefault()) );
503  }
504  menu->exec( pos );
505  delete menu;
506 }
507 
508 
509 void IdentityPage::slotSetAsDefault() {
510  assert( !mIdentityDialog );
511 
512  IdentityListViewItem * item =
513  dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
514  if ( !item ) return;
515 
516  KPIM::IdentityManager * im = kmkernel->identityManager();
517  im->setAsDefault( item->identity().identityName() );
518  refreshList();
519 }
520 
521 void IdentityPage::refreshList() {
522  for ( TQListViewItemIterator it( mIdentityList ) ; it.current() ; ++it ) {
523  IdentityListViewItem * item =
524  dynamic_cast<IdentityListViewItem*>(it.current());
525  if ( item )
526  item->redisplay();
527  }
528  emit changed(true);
529 }
530 
531 void IdentityPage::slotIdentitySelectionChanged()
532 {
533  IdentityListViewItem *item =
534  dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
535 
536  mRemoveButton->setEnabled( item && mIdentityList->childCount() > 1 );
537  mModifyButton->setEnabled( item );
538  mRenameButton->setEnabled( item );
539  mSetAsDefaultButton->setEnabled( item && !item->identity().isDefault() );
540 }
541 
542 void IdentityPage::slotUpdateTransportCombo( const TQStringList & sl )
543 {
544  if ( mIdentityDialog ) mIdentityDialog->slotUpdateTransportCombo( sl );
545 }
546 
547 
548 
549 // *************************************************************
550 // * *
551 // * AccountsPage *
552 // * *
553 // *************************************************************
554 TQString AccountsPage::helpAnchor() const {
555  return TQString::fromLatin1("configure-accounts");
556 }
557 
558 AccountsPage::AccountsPage( TQWidget * parent, const char * name )
559  : ConfigModuleWithTabs( parent, name )
560 {
561  //
562  // "Receiving" tab:
563  //
564  mReceivingTab = new ReceivingTab();
565  addTab( mReceivingTab, i18n( "&Receiving" ) );
566  connect( mReceivingTab, TQ_SIGNAL(accountListChanged(const TQStringList &)),
567  this, TQ_SIGNAL(accountListChanged(const TQStringList &)) );
568 
569  //
570  // "Sending" tab:
571  //
572  mSendingTab = new SendingTab();
573  addTab( mSendingTab, i18n( "&Sending" ) );
574  connect( mSendingTab, TQ_SIGNAL(transportListChanged(const TQStringList&)),
575  this, TQ_SIGNAL(transportListChanged(const TQStringList&)) );
576 
577  load();
578 }
579 
580 TQString AccountsPage::SendingTab::helpAnchor() const {
581  return TQString::fromLatin1("configure-accounts-sending");
582 }
583 
584 AccountsPageSendingTab::AccountsPageSendingTab( TQWidget * parent, const char * name )
585  : ConfigModuleTab( parent, name )
586 {
587  mTransportInfoList.setAutoDelete( true );
588  // temp. vars:
589  TQVBoxLayout *vlay;
590  TQVBoxLayout *btn_vlay;
591  TQHBoxLayout *hlay;
592  TQGridLayout *glay;
593  TQPushButton *button;
594  TQGroupBox *group;
595 
596  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
597  // label: zero stretch ### FIXME more
598  vlay->addWidget( new TQLabel( i18n("Outgoing accounts (add at least one):"), this ) );
599 
600  // hbox layout: stretch 10, spacing inherited from vlay
601  hlay = new TQHBoxLayout();
602  vlay->addLayout( hlay, 10 ); // high stretch b/c of the groupbox's sizeHint
603 
604  // transport list: left widget in hlay; stretch 1
605  // ### FIXME: allow inline renaming of the account:
606  mTransportList = new ListView( this, "transportList", 5 );
607  mTransportList->addColumn( i18n("Name") );
608  mTransportList->addColumn( i18n("Type") );
609  mTransportList->setAllColumnsShowFocus( true );
610  mTransportList->setSorting( -1 );
611  connect( mTransportList, TQ_SIGNAL(selectionChanged()),
612  this, TQ_SLOT(slotTransportSelected()) );
613  connect( mTransportList, TQ_SIGNAL(doubleClicked( TQListViewItem *)),
614  this, TQ_SLOT(slotModifySelectedTransport()) );
615  hlay->addWidget( mTransportList, 1 );
616 
617  // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
618  btn_vlay = new TQVBoxLayout( hlay );
619 
620  // "add..." button: stretch 0
621  button = new TQPushButton( i18n("A&dd..."), this );
622  button->setAutoDefault( false );
623  connect( button, TQ_SIGNAL(clicked()),
624  this, TQ_SLOT(slotAddTransport()) );
625  btn_vlay->addWidget( button );
626 
627  // "modify..." button: stretch 0
628  mModifyTransportButton = new TQPushButton( i18n("&Modify..."), this );
629  mModifyTransportButton->setAutoDefault( false );
630  mModifyTransportButton->setEnabled( false ); // b/c no item is selected yet
631  connect( mModifyTransportButton, TQ_SIGNAL(clicked()),
632  this, TQ_SLOT(slotModifySelectedTransport()) );
633  btn_vlay->addWidget( mModifyTransportButton );
634 
635  // "remove" button: stretch 0
636  mRemoveTransportButton = new TQPushButton( i18n("R&emove"), this );
637  mRemoveTransportButton->setAutoDefault( false );
638  mRemoveTransportButton->setEnabled( false ); // b/c no item is selected yet
639  connect( mRemoveTransportButton, TQ_SIGNAL(clicked()),
640  this, TQ_SLOT(slotRemoveSelectedTransport()) );
641  btn_vlay->addWidget( mRemoveTransportButton );
642 
643  mSetDefaultTransportButton = new TQPushButton( i18n("Set Default"), this );
644  mSetDefaultTransportButton->setAutoDefault( false );
645  mSetDefaultTransportButton->setEnabled( false );
646  connect ( mSetDefaultTransportButton, TQ_SIGNAL(clicked()),
647  this, TQ_SLOT(slotSetDefaultTransport()) );
648  btn_vlay->addWidget( mSetDefaultTransportButton );
649  btn_vlay->addStretch( 1 ); // spacer
650 
651  // "Common options" groupbox:
652  group = new TQGroupBox( 0, TQt::Vertical,
653  i18n("Common Options"), this );
654  vlay->addWidget(group);
655 
656  // a grid layout for the contents of the "common options" group box
657  glay = new TQGridLayout( group->layout(), 5, 3, KDialog::spacingHint() );
658  glay->setColStretch( 2, 10 );
659 
660  // "confirm before send" check box:
661  mConfirmSendCheck = new TQCheckBox( i18n("Confirm &before send"), group );
662  glay->addMultiCellWidget( mConfirmSendCheck, 0, 0, 0, 1 );
663  connect( mConfirmSendCheck, TQ_SIGNAL( stateChanged( int ) ),
664  this, TQ_SLOT( slotEmitChanged( void ) ) );
665 
666  // "send on check" combo:
667  mSendOnCheckCombo = new TQComboBox( false, group );
668  mSendOnCheckCombo->insertStringList( TQStringList()
669  << i18n("Never Automatically")
670  << i18n("On Manual Mail Checks")
671  << i18n("On All Mail Checks") );
672  glay->addWidget( mSendOnCheckCombo, 1, 1 );
673  connect( mSendOnCheckCombo, TQ_SIGNAL( activated( int ) ),
674  this, TQ_SLOT( slotEmitChanged( void ) ) );
675 
676  // "default send method" combo:
677  mSendMethodCombo = new TQComboBox( false, group );
678  mSendMethodCombo->insertStringList( TQStringList()
679  << i18n("Send Now")
680  << i18n("Send Later") );
681  glay->addWidget( mSendMethodCombo, 2, 1 );
682  connect( mSendMethodCombo, TQ_SIGNAL( activated( int ) ),
683  this, TQ_SLOT( slotEmitChanged( void ) ) );
684 
685 
686  // "message property" combo:
687  // ### FIXME: remove completely?
688  mMessagePropertyCombo = new TQComboBox( false, group );
689  mMessagePropertyCombo->insertStringList( TQStringList()
690  << i18n("Allow 8-bit")
691  << i18n("MIME Compliant (Quoted Printable)") );
692  glay->addWidget( mMessagePropertyCombo, 3, 1 );
693  connect( mMessagePropertyCombo, TQ_SIGNAL( activated( int ) ),
694  this, TQ_SLOT( slotEmitChanged( void ) ) );
695 
696  // "default domain" input field:
697  mDefaultDomainEdit = new KLineEdit( group );
698  glay->addMultiCellWidget( mDefaultDomainEdit, 4, 4, 1, 2 );
699  connect( mDefaultDomainEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
700  this, TQ_SLOT( slotEmitChanged( void ) ) );
701 
702  // labels:
703  TQLabel *l = new TQLabel( mSendOnCheckCombo, /*buddy*/
704  i18n("Send &messages in outbox folder:"), group );
705  glay->addWidget( l, 1, 0 );
706 
707  TQString msg = i18n( GlobalSettings::self()->sendOnCheckItem()->whatsThis().utf8() );
708  TQWhatsThis::add( l, msg );
709  TQWhatsThis::add( mSendOnCheckCombo, msg );
710 
711  glay->addWidget( new TQLabel( mSendMethodCombo, /*buddy*/
712  i18n("Defa&ult send method:"), group ), 2, 0 );
713  glay->addWidget( new TQLabel( mMessagePropertyCombo, /*buddy*/
714  i18n("Message &property:"), group ), 3, 0 );
715  l = new TQLabel( mDefaultDomainEdit, /*buddy*/
716  i18n("Defaul&t domain:"), group );
717  glay->addWidget( l, 4, 0 );
718 
719  // and now: add TQWhatsThis:
720  msg = i18n( "<qt><p>The default domain is used to complete email "
721  "addresses that only consist of the user's name."
722  "</p></qt>" );
723  TQWhatsThis::add( l, msg );
724  TQWhatsThis::add( mDefaultDomainEdit, msg );
725 }
726 
727 
728 void AccountsPage::SendingTab::slotTransportSelected()
729 {
730  TQListViewItem *cur = mTransportList->selectedItem();
731  mModifyTransportButton->setEnabled( cur );
732  mRemoveTransportButton->setEnabled( cur );
733  mSetDefaultTransportButton->setEnabled( cur );
734 }
735 
736 // adds a number to @p name to make the name unique
737 static inline TQString uniqueName( const TQStringList & list,
738  const TQString & name )
739 {
740  int suffix = 1;
741  TQString result = name;
742  while ( list.find( result ) != list.end() ) {
743  result = i18n("%1: name; %2: number appended to it to make it unique "
744  "among a list of names", "%1 %2")
745  .arg( name ).arg( suffix );
746  suffix++;
747  }
748  return result;
749 }
750 
751 void AccountsPage::SendingTab::slotSetDefaultTransport()
752 {
753  TQListViewItem *item = mTransportList->selectedItem();
754  if ( !item ) return;
755 
756  KMTransportInfo ti;
757 
758  TQListViewItemIterator it( mTransportList );
759  for ( ; it.current(); ++it ) {
760  ti.readConfig( KMTransportInfo::findTransport( it.current()->text(0) ));
761  if ( ti.type != "sendmail" ) {
762  it.current()->setText( 1, "smtp" );
763  } else {
764  it.current()->setText( 1, "sendmail" );
765  }
766  }
767 
768  if ( item->text(1) != "sendmail" ) {
769  item->setText( 1, i18n( "smtp (Default)" ));
770  } else {
771  item->setText( 1, i18n( "sendmail (Default)" ));
772  }
773  GlobalSettings::self()->setDefaultTransport( item->text(0) );
774 
775 }
776 
777 void AccountsPage::SendingTab::slotAddTransport()
778 {
779  int transportType;
780 
781  { // limit scope of selDialog
782  KMTransportSelDlg selDialog( this );
783  if ( selDialog.exec() != TQDialog::Accepted ) return;
784  transportType = selDialog.selected();
785  }
786 
787  KMTransportInfo *transportInfo = new KMTransportInfo();
788  switch ( transportType ) {
789  case 0: // smtp
790  transportInfo->type = TQString::fromLatin1("smtp");
791  break;
792  case 1: // sendmail
793  transportInfo->type = TQString::fromLatin1("sendmail");
794  transportInfo->name = i18n("Sendmail");
795  transportInfo->host = _PATH_SENDMAIL; // ### FIXME: use const, not #define
796  break;
797  default:
798  assert( 0 );
799  }
800 
801  KMTransportDialog dialog( i18n("Add Transport"), transportInfo, this );
802 
803  // create list of names:
804  // ### move behind dialog.exec()?
805  TQStringList transportNames;
806  TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
807  for ( it.toFirst() ; it.current() ; ++it )
808  transportNames << (*it)->name;
809 
810  if( dialog.exec() != TQDialog::Accepted ) {
811  delete transportInfo;
812  return;
813  }
814 
815  // disambiguate the name by appending a number:
816  // ### FIXME: don't allow this error to happen in the first place!
817  transportInfo->name = uniqueName( transportNames, transportInfo->name );
818  // append to names and transportinfo lists:
819  transportNames << transportInfo->name;
820  mTransportInfoList.append( transportInfo );
821 
822  // append to listview:
823  // ### FIXME: insert before the selected item, append on empty selection
824  TQListViewItem *lastItem = mTransportList->firstChild();
825  TQString typeDisplayName;
826  if ( lastItem ) {
827  typeDisplayName = transportInfo->type;
828  } else {
829  typeDisplayName = i18n("%1: type of transport. Result used in "
830  "Configure->Accounts->Sending listview, \"type\" "
831  "column, first row, to indicate that this is the "
832  "default transport", "%1 (Default)")
833  .arg( transportInfo->type );
834  GlobalSettings::self()->setDefaultTransport( transportInfo->name );
835  }
836  (void) new TQListViewItem( mTransportList, lastItem, transportInfo->name,
837  typeDisplayName );
838 
839  // notify anyone who cares:
840  emit transportListChanged( transportNames );
841  emit changed( true );
842 }
843 
844 void AccountsPage::SendingTab::slotModifySelectedTransport()
845 {
846  TQListViewItem *item = mTransportList->selectedItem();
847  if ( !item ) return;
848 
849  const TQString& originalTransport = item->text(0);
850 
851  TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
852  for ( it.toFirst() ; it.current() ; ++it )
853  if ( (*it)->name == item->text(0) ) break;
854  if ( !it.current() ) return;
855 
856  KMTransportDialog dialog( i18n("Modify Transport"), (*it), this );
857 
858  if ( dialog.exec() != TQDialog::Accepted ) return;
859 
860  // create the list of names of transports, but leave out the current
861  // item:
862  TQStringList transportNames;
863  TQPtrListIterator<KMTransportInfo> jt( mTransportInfoList );
864  int entryLocation = -1;
865  for ( jt.toFirst() ; jt.current() ; ++jt )
866  if ( jt != it )
867  transportNames << (*jt)->name;
868  else
869  entryLocation = transportNames.count();
870  assert( entryLocation >= 0 );
871 
872  // make the new name unique by appending a high enough number:
873  (*it)->name = uniqueName( transportNames, (*it)->name );
874  // change the list item to the new name
875  item->setText( 0, (*it)->name );
876  // and insert the new name at the position of the old in the list of
877  // strings; then broadcast the new list:
878  transportNames.insert( transportNames.at( entryLocation ), (*it)->name );
879  const TQString& newTransportName = (*it)->name;
880 
881  TQStringList changedIdents;
882  KPIM::IdentityManager * im = kmkernel->identityManager();
883  for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
884  if ( originalTransport == (*it).transport() ) {
885  (*it).setTransport( newTransportName );
886  changedIdents += (*it).identityName();
887  }
888  }
889 
890  if ( !changedIdents.isEmpty() ) {
891  TQString information = i18n( "This identity has been changed to use the modified transport:",
892  "These %n identities have been changed to use the modified transport:",
893  changedIdents.count() );
894  KMessageBox::informationList( this, information, changedIdents );
895  }
896 
897  emit transportListChanged( transportNames );
898  emit changed( true );
899 }
900 
901 void AccountsPage::SendingTab::slotRemoveSelectedTransport()
902 {
903  TQListViewItem *item = mTransportList->selectedItem();
904  if ( !item ) return;
905 
906  bool selectedTransportWasDefault = false;
907  if ( item->text( 0 ) == GlobalSettings::self()->defaultTransport() ) {
908  selectedTransportWasDefault = true;
909  }
910  TQStringList changedIdents;
911  KPIM::IdentityManager * im = kmkernel->identityManager();
912  for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
913  if ( item->text( 0 ) == (*it).transport() ) {
914  (*it).setTransport( TQString() );
915  changedIdents += (*it).identityName();
916  }
917  }
918 
919  // if the deleted transport is the currently used transport reset it to default
920  const TQString& currentTransport = GlobalSettings::self()->currentTransport();
921  if ( item->text( 0 ) == currentTransport ) {
922  GlobalSettings::self()->setCurrentTransport( TQString() );
923  }
924 
925  if ( !changedIdents.isEmpty() ) {
926  TQString information = i18n( "This identity has been changed to use the default transport:",
927  "These %n identities have been changed to use the default transport:",
928  changedIdents.count() );
929  KMessageBox::informationList( this, information, changedIdents );
930  }
931 
932  TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
933  for ( it.toFirst() ; it.current() ; ++it )
934  if ( (*it)->name == item->text(0) ) break;
935  if ( !it.current() ) return;
936 
937  KMTransportInfo ti;
938 
939  if( selectedTransportWasDefault )
940  {
941  TQListViewItem *newCurrent = item->itemBelow();
942  if ( !newCurrent ) newCurrent = item->itemAbove();
943  //mTransportList->removeItem( item );
944  if ( newCurrent ) {
945  mTransportList->setCurrentItem( newCurrent );
946  mTransportList->setSelected( newCurrent, true );
947  GlobalSettings::self()->setDefaultTransport( newCurrent->text(0) );
948  ti.readConfig( KMTransportInfo::findTransport( newCurrent->text(0) ));
949  if ( ti.type != "sendmail" ) {
950  newCurrent->setText( 1, i18n("smtp (Default)") );
951  } else {
952  newCurrent->setText( 1, i18n("sendmail (Default)" ));
953  }
954  } else {
955  GlobalSettings::self()->setDefaultTransport( TQString() );
956  }
957  }
958  delete item;
959  mTransportInfoList.remove( it );
960 
961  TQStringList transportNames;
962  for ( it.toFirst() ; it.current() ; ++it )
963  transportNames << (*it)->name;
964  emit transportListChanged( transportNames );
965  emit changed( true );
966 }
967 
968 void AccountsPage::SendingTab::doLoadFromGlobalSettings() {
969  mSendOnCheckCombo->setCurrentItem( GlobalSettings::self()->sendOnCheck() );
970 }
971 
972 void AccountsPage::SendingTab::doLoadOther() {
973  TDEConfigGroup general( KMKernel::config(), "General");
974  TDEConfigGroup composer( KMKernel::config(), "Composer");
975 
976  int numTransports = general.readNumEntry("transports", 0);
977 
978  TQListViewItem *top = 0;
979  mTransportInfoList.clear();
980  mTransportList->clear();
981  TQStringList transportNames;
982  for ( int i = 1 ; i <= numTransports ; i++ ) {
983  KMTransportInfo *ti = new KMTransportInfo();
984  ti->readConfig(i);
985  mTransportInfoList.append( ti );
986  transportNames << ti->name;
987  top = new TQListViewItem( mTransportList, top, ti->name, ti->type );
988  }
989  emit transportListChanged( transportNames );
990 
991  const TQString &defaultTransport = GlobalSettings::self()->defaultTransport();
992 
993  TQListViewItemIterator it( mTransportList );
994  for ( ; it.current(); ++it ) {
995  if ( it.current()->text(0) == defaultTransport ) {
996  if ( it.current()->text(1) != "sendmail" ) {
997  it.current()->setText( 1, i18n( "smtp (Default)" ));
998  } else {
999  it.current()->setText( 1, i18n( "sendmail (Default)" ));
1000  }
1001  } else {
1002  if ( it.current()->text(1) != "sendmail" ) {
1003  it.current()->setText( 1, "smtp" );
1004  } else {
1005  it.current()->setText( 1, "sendmail" );
1006  }
1007  }
1008  }
1009 
1010  mSendMethodCombo->setCurrentItem(
1011  kmkernel->msgSender()->sendImmediate() ? 0 : 1 );
1012  mMessagePropertyCombo->setCurrentItem(
1013  kmkernel->msgSender()->sendQuotedPrintable() ? 1 : 0 );
1014 
1015  mConfirmSendCheck->setChecked( composer.readBoolEntry( "confirm-before-send",
1016  false ) );
1017  TQString str = general.readEntry( "Default domain" );
1018  if( str.isEmpty() )
1019  {
1020  //### FIXME: Use the global convenience function instead of the homebrewed
1021  // solution once we can rely on HEAD tdelibs.
1022  //str = TDEGlobal::hostname(); ???????
1023  char buffer[256];
1024  if ( !gethostname( buffer, 255 ) )
1025  // buffer need not be NUL-terminated if it has full length
1026  buffer[255] = 0;
1027  else
1028  buffer[0] = 0;
1029  str = TQString::fromLatin1( *buffer ? buffer : "localhost" );
1030  }
1031  mDefaultDomainEdit->setText( str );
1032 }
1033 
1034 void AccountsPage::SendingTab::save() {
1035  TDEConfigGroup general( KMKernel::config(), "General" );
1036  TDEConfigGroup composer( KMKernel::config(), "Composer" );
1037 
1038  // Save transports:
1039  general.writeEntry( "transports", mTransportInfoList.count() );
1040  TQPtrListIterator<KMTransportInfo> it( mTransportInfoList );
1041  for ( int i = 1 ; it.current() ; ++it, ++i )
1042  (*it)->writeConfig(i);
1043 
1044  // Save common options:
1045  GlobalSettings::self()->setSendOnCheck( mSendOnCheckCombo->currentItem() );
1046  kmkernel->msgSender()->setSendImmediate(
1047  mSendMethodCombo->currentItem() == 0 );
1048  kmkernel->msgSender()->setSendQuotedPrintable(
1049  mMessagePropertyCombo->currentItem() == 1 );
1050  kmkernel->msgSender()->writeConfig( false ); // don't sync
1051  composer.writeEntry("confirm-before-send", mConfirmSendCheck->isChecked() );
1052  general.writeEntry( "Default domain", mDefaultDomainEdit->text() );
1053 }
1054 
1055 TQString AccountsPage::ReceivingTab::helpAnchor() const {
1056  return TQString::fromLatin1("configure-accounts-receiving");
1057 }
1058 
1059 AccountsPageReceivingTab::AccountsPageReceivingTab( TQWidget * parent, const char * name )
1060  : ConfigModuleTab ( parent, name )
1061 {
1062  // temp. vars:
1063  TQVBoxLayout *vlay;
1064  TQVBoxLayout *btn_vlay;
1065  TQHBoxLayout *hlay;
1066  TQPushButton *button;
1067  TQGroupBox *group;
1068 
1069  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
1070 
1071  // label: zero stretch
1072  vlay->addWidget( new TQLabel( i18n("Incoming accounts (add at least one):"), this ) );
1073 
1074  // hbox layout: stretch 10, spacing inherited from vlay
1075  hlay = new TQHBoxLayout();
1076  vlay->addLayout( hlay, 10 ); // high stretch to suppress groupbox's growing
1077 
1078  // account list: left widget in hlay; stretch 1
1079  mAccountList = new ListView( this, "accountList", 5 );
1080  mAccountList->addColumn( i18n("Name") );
1081  mAccountList->addColumn( i18n("Type") );
1082  mAccountList->addColumn( i18n("Folder") );
1083  mAccountList->setAllColumnsShowFocus( true );
1084  mAccountList->setSorting( -1 );
1085  connect( mAccountList, TQ_SIGNAL(selectionChanged()),
1086  this, TQ_SLOT(slotAccountSelected()) );
1087  connect( mAccountList, TQ_SIGNAL(doubleClicked( TQListViewItem *)),
1088  this, TQ_SLOT(slotModifySelectedAccount()) );
1089  hlay->addWidget( mAccountList, 1 );
1090 
1091  // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
1092  btn_vlay = new TQVBoxLayout( hlay );
1093 
1094  // "add..." button: stretch 0
1095  button = new TQPushButton( i18n("A&dd..."), this );
1096  button->setAutoDefault( false );
1097  connect( button, TQ_SIGNAL(clicked()),
1098  this, TQ_SLOT(slotAddAccount()) );
1099  btn_vlay->addWidget( button );
1100 
1101  // "modify..." button: stretch 0
1102  mModifyAccountButton = new TQPushButton( i18n("&Modify..."), this );
1103  mModifyAccountButton->setAutoDefault( false );
1104  mModifyAccountButton->setEnabled( false ); // b/c no item is selected yet
1105  connect( mModifyAccountButton, TQ_SIGNAL(clicked()),
1106  this, TQ_SLOT(slotModifySelectedAccount()) );
1107  btn_vlay->addWidget( mModifyAccountButton );
1108 
1109  // "remove..." button: stretch 0
1110  mRemoveAccountButton = new TQPushButton( i18n("R&emove"), this );
1111  mRemoveAccountButton->setAutoDefault( false );
1112  mRemoveAccountButton->setEnabled( false ); // b/c no item is selected yet
1113  connect( mRemoveAccountButton, TQ_SIGNAL(clicked()),
1114  this, TQ_SLOT(slotRemoveSelectedAccount()) );
1115  btn_vlay->addWidget( mRemoveAccountButton );
1116  btn_vlay->addStretch( 1 ); // spacer
1117 
1118  mCheckmailStartupCheck = new TQCheckBox( i18n("Chec&k mail on startup"), this );
1119  vlay->addWidget( mCheckmailStartupCheck );
1120  connect( mCheckmailStartupCheck, TQ_SIGNAL( stateChanged( int ) ),
1121  this, TQ_SLOT( slotEmitChanged( void ) ) );
1122 
1123  // "New Mail Notification" group box: stretch 0
1124  group = new TQVGroupBox( i18n("New Mail Notification"), this );
1125  vlay->addWidget( group );
1126  group->layout()->setSpacing( KDialog::spacingHint() );
1127 
1128  // "beep on new mail" check box:
1129  mBeepNewMailCheck = new TQCheckBox(i18n("&Beep"), group );
1130  mBeepNewMailCheck->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
1131  TQSizePolicy::Fixed ) );
1132  connect( mBeepNewMailCheck, TQ_SIGNAL( stateChanged( int ) ),
1133  this, TQ_SLOT( slotEmitChanged( void ) ) );
1134 
1135  // "Detailed new mail notification" check box
1136  mVerboseNotificationCheck =
1137  new TQCheckBox( i18n( "Deta&iled new mail notification" ), group );
1138  mVerboseNotificationCheck->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
1139  TQSizePolicy::Fixed ) );
1140  TQToolTip::add( mVerboseNotificationCheck,
1141  i18n( "Show for each folder the number of newly arrived "
1142  "messages" ) );
1143  TQWhatsThis::add( mVerboseNotificationCheck,
1144  GlobalSettings::self()->verboseNewMailNotificationItem()->whatsThis() );
1145  connect( mVerboseNotificationCheck, TQ_SIGNAL( stateChanged( int ) ),
1146  this, TQ_SLOT( slotEmitChanged() ) );
1147 
1148  // "Other Actions" button:
1149  mOtherNewMailActionsButton = new TQPushButton( i18n("Other Actio&ns"), group );
1150  mOtherNewMailActionsButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed,
1151  TQSizePolicy::Fixed ) );
1152  connect( mOtherNewMailActionsButton, TQ_SIGNAL(clicked()),
1153  this, TQ_SLOT(slotEditNotifications()) );
1154 }
1155 
1156 AccountsPageReceivingTab::~AccountsPageReceivingTab()
1157 {
1158  // When hitting Cancel or closing the dialog with the window-manager-button,
1159  // we have a number of things to clean up:
1160 
1161  // The newly created accounts
1162  TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
1163  for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
1164  delete (*it);
1165  }
1166  mNewAccounts.clear();
1167 
1168  // The modified accounts
1169  TQValueList<ModifiedAccountsType*>::Iterator j;
1170  for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
1171  delete (*j)->newAccount;
1172  delete (*j);
1173  }
1174  mModifiedAccounts.clear();
1175 
1176 
1177 }
1178 
1179 void AccountsPage::ReceivingTab::slotAccountSelected()
1180 {
1181  TQListViewItem * item = mAccountList->selectedItem();
1182  mModifyAccountButton->setEnabled( item );
1183  mRemoveAccountButton->setEnabled( item );
1184 }
1185 
1186 TQStringList AccountsPage::ReceivingTab::occupiedNames()
1187 {
1188  TQStringList accountNames = kmkernel->acctMgr()->getAccounts();
1189 
1190  TQValueList<ModifiedAccountsType*>::Iterator k;
1191  for (k = mModifiedAccounts.begin(); k != mModifiedAccounts.end(); ++k )
1192  if ((*k)->oldAccount)
1193  accountNames.remove( (*k)->oldAccount->name() );
1194 
1195  TQValueList< TQGuardedPtr<KMAccount> >::Iterator l;
1196  for (l = mAccountsToDelete.begin(); l != mAccountsToDelete.end(); ++l )
1197  if (*l)
1198  accountNames.remove( (*l)->name() );
1199 
1200  TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
1201  for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it )
1202  if (*it)
1203  accountNames += (*it)->name();
1204 
1205  TQValueList<ModifiedAccountsType*>::Iterator j;
1206  for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
1207  accountNames += (*j)->newAccount->name();
1208 
1209  return accountNames;
1210 }
1211 
1212 void AccountsPage::ReceivingTab::slotAddAccount() {
1213  KMAcctSelDlg accountSelectorDialog( this );
1214  if( accountSelectorDialog.exec() != TQDialog::Accepted ) return;
1215 
1216  const char *accountType = 0;
1217  switch ( accountSelectorDialog.selected() ) {
1218  case 0: accountType = "local"; break;
1219  case 1: accountType = "pop"; break;
1220  case 2: accountType = "imap"; break;
1221  case 3: accountType = "cachedimap"; break;
1222  case 4: accountType = "maildir"; break;
1223 
1224  default:
1225  // ### FIXME: How should this happen???
1226  // replace with assert.
1227  KMessageBox::sorry( this, i18n("Unknown account type selected") );
1228  return;
1229  }
1230 
1231  KMAccount *account
1232  = kmkernel->acctMgr()->create( TQString::fromLatin1( accountType ) );
1233  if ( !account ) {
1234  // ### FIXME: Give the user more information. Is this error
1235  // recoverable?
1236  KMessageBox::sorry( this, i18n("Unable to create account") );
1237  return;
1238  }
1239 
1240  account->init(); // fill the account fields with good default values
1241 
1242  AccountDialog dialog( i18n("Add Account"), account, this );
1243 
1244  TQStringList accountNames = occupiedNames();
1245 
1246  if( dialog.exec() != TQDialog::Accepted ) {
1247  delete account;
1248  return;
1249  }
1250 
1251  account->deinstallTimer();
1252  account->setName( uniqueName( accountNames, account->name() ) );
1253 
1254  TQListViewItem *after = mAccountList->firstChild();
1255  while ( after && after->nextSibling() )
1256  after = after->nextSibling();
1257 
1258  TQListViewItem *listItem =
1259  new TQListViewItem( mAccountList, after, account->name(), account->type() );
1260  if( account->folder() )
1261  listItem->setText( 2, account->folder()->label() );
1262 
1263  mNewAccounts.append( account );
1264  emit changed( true );
1265 }
1266 
1267 
1268 
1269 void AccountsPage::ReceivingTab::slotModifySelectedAccount()
1270 {
1271  TQListViewItem *listItem = mAccountList->selectedItem();
1272  if( !listItem ) return;
1273 
1274  KMAccount *account = 0;
1275  TQValueList<ModifiedAccountsType*>::Iterator j;
1276  for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
1277  if ( (*j)->newAccount->name() == listItem->text(0) ) {
1278  account = (*j)->newAccount;
1279  break;
1280  }
1281 
1282  if ( !account ) {
1283  TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
1284  for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
1285  if ( (*it)->name() == listItem->text(0) ) {
1286  account = *it;
1287  break;
1288  }
1289 
1290  if ( !account ) {
1291  account = kmkernel->acctMgr()->findByName( listItem->text(0) );
1292  if( !account ) {
1293  // ### FIXME: How should this happen? See above.
1294  KMessageBox::sorry( this, i18n("Unable to locate account") );
1295  return;
1296  }
1297  if ( account->type() == "imap" || account->type() == "cachedimap" )
1298  {
1299  ImapAccountBase* ai = static_cast<ImapAccountBase*>( account );
1300  if ( ai->namespaces().isEmpty() || ai->namespaceToDelimiter().isEmpty() )
1301  {
1302  // connect to server - the namespaces are fetched automatically
1303  kdDebug(5006) << "slotModifySelectedAccount - connect" << endl;
1304  ai->makeConnection();
1305  }
1306  }
1307 
1308  ModifiedAccountsType *mod = new ModifiedAccountsType;
1309  mod->oldAccount = account;
1310  mod->newAccount = kmkernel->acctMgr()->create( account->type(),
1311  account->name() );
1312  mod->newAccount->pseudoAssign( account );
1313  mModifiedAccounts.append( mod );
1314  account = mod->newAccount;
1315  }
1316  }
1317 
1318  TQStringList accountNames = occupiedNames();
1319  accountNames.remove( account->name() );
1320 
1321  AccountDialog dialog( i18n("Modify Account"), account, this );
1322 
1323  if( dialog.exec() != TQDialog::Accepted ) return;
1324 
1325  account->setName( uniqueName( accountNames, account->name() ) );
1326 
1327  listItem->setText( 0, account->name() );
1328  listItem->setText( 1, account->type() );
1329  if( account->folder() )
1330  listItem->setText( 2, account->folder()->label() );
1331 
1332  emit changed( true );
1333 }
1334 
1335 
1336 
1337 void AccountsPage::ReceivingTab::slotRemoveSelectedAccount() {
1338  TQListViewItem *listItem = mAccountList->selectedItem();
1339  if( !listItem ) return;
1340 
1341  KMAccount *acct = 0;
1342  TQValueList<ModifiedAccountsType*>::Iterator j;
1343  for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j )
1344  if ( (*j)->newAccount->name() == listItem->text(0) ) {
1345  acct = (*j)->oldAccount;
1346  mAccountsToDelete.append( acct );
1347  mModifiedAccounts.remove( j );
1348  break;
1349  }
1350  if ( !acct ) {
1351  TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
1352  for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
1353  if ( (*it)->name() == listItem->text(0) ) {
1354  acct = *it;
1355  mNewAccounts.remove( it );
1356  break;
1357  }
1358  }
1359  if ( !acct ) {
1360  acct = kmkernel->acctMgr()->findByName( listItem->text(0) );
1361  if ( acct )
1362  mAccountsToDelete.append( acct );
1363  }
1364  if ( !acct ) {
1365  // ### FIXME: see above
1366  KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
1367  .arg(listItem->text(0)) );
1368  return;
1369  }
1370 
1371  TQListViewItem * item = listItem->itemBelow();
1372  if ( !item ) item = listItem->itemAbove();
1373  delete listItem;
1374 
1375  if ( item )
1376  mAccountList->setSelected( item, true );
1377 
1378  emit changed( true );
1379 }
1380 
1381 void AccountsPage::ReceivingTab::slotEditNotifications()
1382 {
1383  if(kmkernel->xmlGuiInstance())
1384  KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
1385  else
1386  KNotifyDialog::configure(this);
1387 }
1388 
1389 void AccountsPage::ReceivingTab::doLoadFromGlobalSettings() {
1390  mVerboseNotificationCheck->setChecked( GlobalSettings::self()->verboseNewMailNotification() );
1391 }
1392 
1393 void AccountsPage::ReceivingTab::doLoadOther() {
1394  TDEConfigGroup general( KMKernel::config(), "General" );
1395 
1396  mAccountList->clear();
1397  TQListViewItem *top = 0;
1398 
1399  for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
1400  a = kmkernel->acctMgr()->next() ) {
1401  TQListViewItem *listItem =
1402  new TQListViewItem( mAccountList, top, a->name(), a->type() );
1403  if( a->folder() )
1404  listItem->setText( 2, a->folder()->label() );
1405  top = listItem;
1406  }
1407  TQListViewItem *listItem = mAccountList->firstChild();
1408  if ( listItem ) {
1409  mAccountList->setCurrentItem( listItem );
1410  mAccountList->setSelected( listItem, true );
1411  }
1412 
1413  mBeepNewMailCheck->setChecked( general.readBoolEntry("beep-on-mail", false ) );
1414  mCheckmailStartupCheck->setChecked( general.readBoolEntry("checkmail-startup", false) );
1415  TQTimer::singleShot( 0, this, TQ_SLOT( slotTweakAccountList() ) );
1416 }
1417 
1418 void AccountsPage::ReceivingTab::slotTweakAccountList()
1419 {
1420  // Force the contentsWidth of mAccountList to be recalculated so that items can be
1421  // selected in the normal way. It would be best if this were not necessary.
1422  mAccountList->resizeContents( mAccountList->visibleWidth(), mAccountList->contentsHeight() );
1423 }
1424 
1425 void AccountsPage::ReceivingTab::save() {
1426  // Add accounts marked as new
1427  TQValueList< TQGuardedPtr<KMAccount> >::Iterator it;
1428  for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
1429  kmkernel->acctMgr()->add( *it ); // calls installTimer too
1430  }
1431 
1432  // Update accounts that have been modified
1433  TQValueList<ModifiedAccountsType*>::Iterator j;
1434  for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
1435  (*j)->oldAccount->pseudoAssign( (*j)->newAccount );
1436  delete (*j)->newAccount;
1437  delete (*j);
1438  }
1439  mModifiedAccounts.clear();
1440 
1441  // Delete accounts marked for deletion
1442  for ( it = mAccountsToDelete.begin() ;
1443  it != mAccountsToDelete.end() ; ++it ) {
1444  kmkernel->acctMgr()->writeConfig( true );
1445  if ( (*it) && !kmkernel->acctMgr()->remove(*it) )
1446  KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
1447  .arg( (*it)->name() ) );
1448  }
1449  mAccountsToDelete.clear();
1450 
1451  // Incoming mail
1452  kmkernel->acctMgr()->writeConfig( false );
1453  kmkernel->cleanupImapFolders();
1454 
1455  // Save Mail notification settings
1456  TDEConfigGroup general( KMKernel::config(), "General" );
1457  general.writeEntry( "beep-on-mail", mBeepNewMailCheck->isChecked() );
1458  GlobalSettings::self()->setVerboseNewMailNotification( mVerboseNotificationCheck->isChecked() );
1459 
1460  general.writeEntry( "checkmail-startup", mCheckmailStartupCheck->isChecked() );
1461 
1462  // Sync new IMAP accounts ASAP:
1463  for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
1464  KMAccount *macc = (*it);
1465  ImapAccountBase *acc = dynamic_cast<ImapAccountBase*> (macc);
1466  if ( acc ) {
1467  AccountUpdater *au = new AccountUpdater( acc );
1468  au->update();
1469  }
1470  }
1471  mNewAccounts.clear();
1472 
1473 }
1474 
1475 // *************************************************************
1476 // * *
1477 // * AppearancePage *
1478 // * *
1479 // *************************************************************
1480 TQString AppearancePage::helpAnchor() const {
1481  return TQString::fromLatin1("configure-appearance");
1482 }
1483 
1484 AppearancePage::AppearancePage( TQWidget * parent, const char * name )
1485  : ConfigModuleWithTabs( parent, name )
1486 {
1487  //
1488  // "Fonts" tab:
1489  //
1490  mFontsTab = new FontsTab();
1491  addTab( mFontsTab, i18n("&Fonts") );
1492 
1493  //
1494  // "Colors" tab:
1495  //
1496  mColorsTab = new ColorsTab();
1497  addTab( mColorsTab, i18n("Color&s") );
1498 
1499  //
1500  // "Layout" tab:
1501  //
1502  mLayoutTab = new LayoutTab();
1503  addTab( mLayoutTab, i18n("La&yout") );
1504 
1505  //
1506  // "Headers" tab:
1507  //
1508  mHeadersTab = new HeadersTab();
1509  addTab( mHeadersTab, i18n("M&essage List") );
1510 
1511  //
1512  // "Reader window" tab:
1513  //
1514  mReaderTab = new ReaderTab();
1515  addTab( mReaderTab, i18n("Message W&indow") );
1516 
1517  //
1518  // "System Tray" tab:
1519  //
1520  mSystemTrayTab = new SystemTrayTab();
1521  addTab( mSystemTrayTab, i18n("System &Tray") );
1522 
1523  load();
1524 }
1525 
1526 
1527 TQString AppearancePage::FontsTab::helpAnchor() const {
1528  return TQString::fromLatin1("configure-appearance-fonts");
1529 }
1530 
1531 static const struct {
1532  const char * configName;
1533  const char * displayName;
1534  bool enableFamilyAndSize;
1535  bool onlyFixed;
1536 } fontNames[] = {
1537  { "body-font", I18N_NOOP("Message Body"), true, false },
1538  { "list-font", I18N_NOOP("Message List"), true, false },
1539  { "list-new-font", I18N_NOOP("Message List - New Messages"), true, false },
1540  { "list-unread-font", I18N_NOOP("Message List - Unread Messages"), true, false },
1541  { "list-important-font", I18N_NOOP("Message List - Important Messages"), true, false },
1542  { "list-todo-font", I18N_NOOP("Message List - Todo Messages"), true, false },
1543  { "list-date-font", I18N_NOOP("Message List - Date Field"), true, false },
1544  { "folder-font", I18N_NOOP("Folder List"), true, false },
1545  { "quote1-font", I18N_NOOP("Quoted Text - First Level"), false, false },
1546  { "quote2-font", I18N_NOOP("Quoted Text - Second Level"), false, false },
1547  { "quote3-font", I18N_NOOP("Quoted Text - Third Level"), false, false },
1548  { "fixed-font", I18N_NOOP("Fixed Width Font"), true, true },
1549  { "composer-font", I18N_NOOP("Composer"), true, false },
1550  { "print-font", I18N_NOOP("Printing Output"), true, false },
1551 };
1552 static const int numFontNames = sizeof fontNames / sizeof *fontNames;
1553 
1554 AppearancePageFontsTab::AppearancePageFontsTab( TQWidget * parent, const char * name )
1555  : ConfigModuleTab( parent, name ), mActiveFontIndex( -1 )
1556 {
1557  assert( numFontNames == sizeof mFont / sizeof *mFont );
1558  // tmp. vars:
1559  TQVBoxLayout *vlay;
1560  TQHBoxLayout *hlay;
1561  TQLabel *label;
1562 
1563  // "Use custom fonts" checkbox, followed by <hr>
1564  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
1565  mCustomFontCheck = new TQCheckBox( i18n("&Use custom fonts"), this );
1566  vlay->addWidget( mCustomFontCheck );
1567  vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
1568  connect ( mCustomFontCheck, TQ_SIGNAL( stateChanged( int ) ),
1569  this, TQ_SLOT( slotEmitChanged( void ) ) );
1570 
1571  // "font location" combo box and label:
1572  hlay = new TQHBoxLayout( vlay ); // inherites spacing
1573  mFontLocationCombo = new TQComboBox( false, this );
1574  mFontLocationCombo->setEnabled( false ); // !mCustomFontCheck->isChecked()
1575 
1576  TQStringList fontDescriptions;
1577  for ( int i = 0 ; i < numFontNames ; i++ )
1578  fontDescriptions << i18n( fontNames[i].displayName );
1579  mFontLocationCombo->insertStringList( fontDescriptions );
1580 
1581  label = new TQLabel( mFontLocationCombo, i18n("Apply &to:"), this );
1582  label->setEnabled( false ); // since !mCustomFontCheck->isChecked()
1583  hlay->addWidget( label );
1584 
1585  hlay->addWidget( mFontLocationCombo );
1586  hlay->addStretch( 10 );
1587  vlay->addSpacing( KDialog::spacingHint() );
1588  mFontChooser = new TDEFontChooser( this, "font", false, TQStringList(),
1589  false, 4 );
1590  mFontChooser->setEnabled( false ); // since !mCustomFontCheck->isChecked()
1591  vlay->addWidget( mFontChooser );
1592  connect ( mFontChooser, TQ_SIGNAL( fontSelected( const TQFont& ) ),
1593  this, TQ_SLOT( slotEmitChanged( void ) ) );
1594 
1595 
1596  // {en,dis}able widgets depending on the state of mCustomFontCheck:
1597  connect( mCustomFontCheck, TQ_SIGNAL(toggled(bool)),
1598  label, TQ_SLOT(setEnabled(bool)) );
1599  connect( mCustomFontCheck, TQ_SIGNAL(toggled(bool)),
1600  mFontLocationCombo, TQ_SLOT(setEnabled(bool)) );
1601  connect( mCustomFontCheck, TQ_SIGNAL(toggled(bool)),
1602  mFontChooser, TQ_SLOT(setEnabled(bool)) );
1603  // load the right font settings into mFontChooser:
1604  connect( mFontLocationCombo, TQ_SIGNAL(activated(int) ),
1605  this, TQ_SLOT(slotFontSelectorChanged(int)) );
1606 }
1607 
1608 
1609 void AppearancePage::FontsTab::slotFontSelectorChanged( int index )
1610 {
1611  kdDebug(5006) << "slotFontSelectorChanged() called" << endl;
1612  if( index < 0 || index >= mFontLocationCombo->count() )
1613  return; // Should never happen, but it is better to check.
1614 
1615  // Save current fontselector setting before we install the new:
1616  if( mActiveFontIndex == 0 ) {
1617  mFont[0] = mFontChooser->font();
1618  // hardcode the family and size of "message body" dependant fonts:
1619  for ( int i = 0 ; i < numFontNames ; i++ )
1620  if ( !fontNames[i].enableFamilyAndSize ) {
1621  // ### shall we copy the font and set the save and re-set
1622  // {regular,italic,bold,bold italic} property or should we
1623  // copy only family and pointSize?
1624  mFont[i].setFamily( mFont[0].family() );
1625  mFont[i].setPointSize/*Float?*/( mFont[0].pointSize/*Float?*/() );
1626  }
1627  } else if ( mActiveFontIndex > 0 )
1628  mFont[ mActiveFontIndex ] = mFontChooser->font();
1629  mActiveFontIndex = index;
1630 
1631  // Disonnect so the "Apply" button is not activated by the change
1632  disconnect ( mFontChooser, TQ_SIGNAL( fontSelected( const TQFont& ) ),
1633  this, TQ_SLOT( slotEmitChanged( void ) ) );
1634 
1635  // Display the new setting:
1636  mFontChooser->setFont( mFont[index], fontNames[index].onlyFixed );
1637 
1638  connect ( mFontChooser, TQ_SIGNAL( fontSelected( const TQFont& ) ),
1639  this, TQ_SLOT( slotEmitChanged( void ) ) );
1640 
1641  // Disable Family and Size list if we have selected a quote font:
1642  mFontChooser->enableColumn( TDEFontChooser::FamilyList|TDEFontChooser::SizeList,
1643  fontNames[ index ].enableFamilyAndSize );
1644 }
1645 
1646 void AppearancePage::FontsTab::doLoadOther() {
1647  TDEConfigGroup fonts( KMKernel::config(), "Fonts" );
1648 
1649  mFont[0] = TDEGlobalSettings::generalFont();
1650  TQFont fixedFont = TDEGlobalSettings::fixedFont();
1651  for ( int i = 0 ; i < numFontNames ; i++ )
1652  mFont[i] = fonts.readFontEntry( fontNames[i].configName,
1653  (fontNames[i].onlyFixed) ? &fixedFont : &mFont[0] );
1654 
1655  mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts", true ) );
1656  mFontLocationCombo->setCurrentItem( 0 );
1657  slotFontSelectorChanged( 0 );
1658 }
1659 
1660 void AppearancePage::FontsTab::installProfile( TDEConfig * profile ) {
1661  TDEConfigGroup fonts( profile, "Fonts" );
1662 
1663  // read fonts that are defined in the profile:
1664  bool needChange = false;
1665  for ( int i = 0 ; i < numFontNames ; i++ )
1666  if ( fonts.hasKey( fontNames[i].configName ) ) {
1667  needChange = true;
1668  mFont[i] = fonts.readFontEntry( fontNames[i].configName );
1669  kdDebug(5006) << "got font \"" << fontNames[i].configName
1670  << "\" thusly: \"" << TQString(mFont[i].toString()) << "\"" << endl;
1671  }
1672  if ( needChange && mFontLocationCombo->currentItem() > 0 )
1673  mFontChooser->setFont( mFont[ mFontLocationCombo->currentItem() ],
1674  fontNames[ mFontLocationCombo->currentItem() ].onlyFixed );
1675 
1676  if ( fonts.hasKey( "defaultFonts" ) )
1677  mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts" ) );
1678 }
1679 
1680 void AppearancePage::FontsTab::save() {
1681  TDEConfigGroup fonts( KMKernel::config(), "Fonts" );
1682 
1683  // read the current font (might have been modified)
1684  if ( mActiveFontIndex >= 0 )
1685  mFont[ mActiveFontIndex ] = mFontChooser->font();
1686 
1687  bool customFonts = mCustomFontCheck->isChecked();
1688  fonts.writeEntry( "defaultFonts", !customFonts );
1689  for ( int i = 0 ; i < numFontNames ; i++ )
1690  if ( customFonts || fonts.hasKey( fontNames[i].configName ) )
1691  // Don't write font info when we use default fonts, but write
1692  // if it's already there:
1693  fonts.writeEntry( fontNames[i].configName, mFont[i] );
1694 }
1695 
1696 TQString AppearancePage::ColorsTab::helpAnchor() const {
1697  return TQString::fromLatin1("configure-appearance-colors");
1698 }
1699 
1700 
1701 static const struct {
1702  const char * configName;
1703  const char * displayName;
1704 } colorNames[] = { // adjust setup() if you change this:
1705  { "BackgroundColor", I18N_NOOP("Composer Background") },
1706  { "AltBackgroundColor", I18N_NOOP("Alternative Background Color") },
1707  { "ForegroundColor", I18N_NOOP("Normal Text") },
1708  { "QuotedText1", I18N_NOOP("Quoted Text - First Level") },
1709  { "QuotedText2", I18N_NOOP("Quoted Text - Second Level") },
1710  { "QuotedText3", I18N_NOOP("Quoted Text - Third Level") },
1711  { "LinkColor", I18N_NOOP("Link") },
1712  { "FollowedColor", I18N_NOOP("Followed Link") },
1713  { "MisspelledColor", I18N_NOOP("Misspelled Words") },
1714  { "NewMessage", I18N_NOOP("New Message") },
1715  { "UnreadMessage", I18N_NOOP("Unread Message") },
1716  { "FlagMessage", I18N_NOOP("Important Message") },
1717  { "TodoMessage", I18N_NOOP("Todo Message") },
1718  { "PGPMessageEncr", I18N_NOOP("OpenPGP Message - Encrypted") },
1719  { "PGPMessageOkKeyOk", I18N_NOOP("OpenPGP Message - Valid Signature with Trusted Key") },
1720  { "PGPMessageOkKeyBad", I18N_NOOP("OpenPGP Message - Valid Signature with Untrusted Key") },
1721  { "PGPMessageWarn", I18N_NOOP("OpenPGP Message - Unchecked Signature") },
1722  { "PGPMessageErr", I18N_NOOP("OpenPGP Message - Bad Signature") },
1723  { "HTMLWarningColor", I18N_NOOP("Border Around Warning Prepending HTML Messages") },
1724  { "CloseToQuotaColor", I18N_NOOP("Folder Name and Size When Close to Quota") },
1725  { "ColorbarBackgroundPlain", I18N_NOOP("HTML Status Bar Background - No HTML Message") },
1726  { "ColorbarForegroundPlain", I18N_NOOP("HTML Status Bar Foreground - No HTML Message") },
1727  { "ColorbarBackgroundHTML", I18N_NOOP("HTML Status Bar Background - HTML Message") },
1728  { "ColorbarForegroundHTML", I18N_NOOP("HTML Status Bar Foreground - HTML Message") },
1729 };
1730 static const int numColorNames = sizeof colorNames / sizeof *colorNames;
1731 
1732 AppearancePageColorsTab::AppearancePageColorsTab( TQWidget * parent, const char * name )
1733  : ConfigModuleTab( parent, name )
1734 {
1735  // tmp. vars:
1736  TQVBoxLayout *vlay;
1737 
1738  // "use custom colors" check box
1739  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
1740  mCustomColorCheck = new TQCheckBox( i18n("&Use custom colors"), this );
1741  vlay->addWidget( mCustomColorCheck );
1742  connect( mCustomColorCheck, TQ_SIGNAL( stateChanged( int ) ),
1743  this, TQ_SLOT( slotEmitChanged( void ) ) );
1744 
1745  // color list box:
1746  mColorList = new ColorListBox( this );
1747  mColorList->setEnabled( false ); // since !mCustomColorCheck->isChecked()
1748  TQStringList modeList;
1749  for ( int i = 0 ; i < numColorNames ; i++ )
1750  mColorList->insertItem( new ColorListItem( i18n( colorNames[i].displayName ) ) );
1751  vlay->addWidget( mColorList, 1 );
1752 
1753  // "recycle colors" check box:
1754  mRecycleColorCheck =
1755  new TQCheckBox( i18n("Recycle colors on deep &quoting"), this );
1756  mRecycleColorCheck->setEnabled( false );
1757  vlay->addWidget( mRecycleColorCheck );
1758  connect( mRecycleColorCheck, TQ_SIGNAL( stateChanged( int ) ),
1759  this, TQ_SLOT( slotEmitChanged( void ) ) );
1760 
1761  // close to quota threshold
1762  TQHBoxLayout *hbox = new TQHBoxLayout(vlay);
1763  TQLabel *l = new TQLabel( i18n("Close to quota threshold"), this );
1764  hbox->addWidget( l );
1765  l->setEnabled( false );
1766  mCloseToQuotaThreshold = new TQSpinBox( 0, 100, 1, this );
1767  connect( mCloseToQuotaThreshold, TQ_SIGNAL( valueChanged( int ) ),
1768  this, TQ_SLOT( slotEmitChanged( void ) ) );
1769  mCloseToQuotaThreshold->setEnabled( false );
1770  mCloseToQuotaThreshold->setSuffix( i18n("%"));
1771  hbox->addWidget( mCloseToQuotaThreshold );
1772  hbox->addWidget( new TQWidget(this), 2 );
1773 
1774  // {en,dir}able widgets depending on the state of mCustomColorCheck:
1775  connect( mCustomColorCheck, TQ_SIGNAL(toggled(bool)),
1776  mColorList, TQ_SLOT(setEnabled(bool)) );
1777  connect( mCustomColorCheck, TQ_SIGNAL(toggled(bool)),
1778  mRecycleColorCheck, TQ_SLOT(setEnabled(bool)) );
1779  connect( mCustomColorCheck, TQ_SIGNAL(toggled(bool)),
1780  l, TQ_SLOT(setEnabled(bool)) );
1781  connect( mCustomColorCheck, TQ_SIGNAL(toggled(bool)),
1782  mCloseToQuotaThreshold, TQ_SLOT(setEnabled(bool)) );
1783 
1784  connect( mCustomColorCheck, TQ_SIGNAL( stateChanged( int ) ),
1785  this, TQ_SLOT( slotEmitChanged( void ) ) );
1786 }
1787 
1788 void AppearancePage::ColorsTab::doLoadOther() {
1789  TDEConfigGroup reader( KMKernel::config(), "Reader" );
1790 
1791  mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors", true ) );
1792  mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors", false ) );
1793  mCloseToQuotaThreshold->setValue( GlobalSettings::closeToQuotaThreshold() );
1794 
1795  static const TQColor defaultColor[ numColorNames ] = {
1796  kapp->palette().active().base(), // bg
1797  TDEGlobalSettings::alternateBackgroundColor(), // alt bg
1798  kapp->palette().active().text(), // fg
1799  TQColor( 0x00, 0x80, 0x00 ), // quoted l1
1800  TQColor( 0x00, 0x70, 0x00 ), // quoted l2
1801  TQColor( 0x00, 0x60, 0x00 ), // quoted l3
1802  TDEGlobalSettings::linkColor(), // link
1803  TDEGlobalSettings::visitedLinkColor(), // visited link
1804  TQt::red, // misspelled words
1805  TQt::red, // new msg
1806  TQt::blue, // unread mgs
1807  TQColor( 0x00, 0x7F, 0x00 ), // important msg
1808  TQt::blue, // todo mgs
1809  TQColor( 0x00, 0x80, 0xFF ), // light blue // pgp encrypted
1810  TQColor( 0x40, 0xFF, 0x40 ), // light green // pgp ok, trusted key
1811  TQColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp ok, untrusted key
1812  TQColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp unchk
1813  TQt::red, // pgp bad
1814  TQColor( 0xFF, 0x40, 0x40 ), // warning text color: light red
1815  TQt::red, // close to quota
1816  TQt::lightGray, // colorbar plain bg
1817  TQt::black, // colorbar plain fg
1818  TQt::black, // colorbar html bg
1819  TQt::white, // colorbar html fg
1820  };
1821 
1822  for ( int i = 0 ; i < numColorNames ; i++ ) {
1823  mColorList->setColor( i,
1824  reader.readColorEntry( colorNames[i].configName, &defaultColor[i] ) );
1825  }
1826  connect( mColorList, TQ_SIGNAL( changed( ) ),
1827  this, TQ_SLOT( slotEmitChanged( void ) ) );
1828 }
1829 
1830 void AppearancePage::ColorsTab::installProfile( TDEConfig * profile ) {
1831  TDEConfigGroup reader( profile, "Reader" );
1832 
1833  if ( reader.hasKey( "defaultColors" ) )
1834  mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors" ) );
1835  if ( reader.hasKey( "RecycleQuoteColors" ) )
1836  mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors" ) );
1837 
1838  for ( int i = 0 ; i < numColorNames ; i++ )
1839  if ( reader.hasKey( colorNames[i].configName ) )
1840  mColorList->setColor( i, reader.readColorEntry( colorNames[i].configName ) );
1841 }
1842 
1843 void AppearancePage::ColorsTab::save() {
1844  TDEConfigGroup reader( KMKernel::config(), "Reader" );
1845 
1846  bool customColors = mCustomColorCheck->isChecked();
1847  reader.writeEntry( "defaultColors", !customColors );
1848 
1849  for ( int i = 0 ; i < numColorNames ; i++ )
1850  // Don't write color info when we use default colors, but write
1851  // if it's already there:
1852  if ( customColors || reader.hasKey( colorNames[i].configName ) )
1853  reader.writeEntry( colorNames[i].configName, mColorList->color(i) );
1854 
1855  reader.writeEntry( "RecycleQuoteColors", mRecycleColorCheck->isChecked() );
1856  GlobalSettings::setCloseToQuotaThreshold( mCloseToQuotaThreshold->value() );
1857 }
1858 
1859 TQString AppearancePage::LayoutTab::helpAnchor() const {
1860  return TQString::fromLatin1("configure-appearance-layout");
1861 }
1862 
1863 static const EnumConfigEntryItem folderListModes[] = {
1864  { "long", I18N_NOOP("Lon&g folder list") },
1865  { "short", I18N_NOOP("Shor&t folder list" ) }
1866 };
1867 static const EnumConfigEntry folderListMode = {
1868  "Geometry", "FolderList", I18N_NOOP("Folder List"),
1869  folderListModes, DIM(folderListModes), 0
1870 };
1871 
1872 
1873 static const EnumConfigEntryItem mimeTreeLocations[] = {
1874  { "top", I18N_NOOP("Abo&ve the message pane") },
1875  { "bottom", I18N_NOOP("&Below the message pane") }
1876 };
1877 static const EnumConfigEntry mimeTreeLocation = {
1878  "Reader", "MimeTreeLocation", I18N_NOOP("Message Structure Viewer Placement"),
1879  mimeTreeLocations, DIM(mimeTreeLocations), 1
1880 };
1881 
1882 static const EnumConfigEntryItem mimeTreeModes[] = {
1883  { "never", I18N_NOOP("Show &never") },
1884  { "smart", I18N_NOOP("Show only for non-plaintext &messages") },
1885  { "always", I18N_NOOP("Show alway&s") }
1886 };
1887 static const EnumConfigEntry mimeTreeMode = {
1888  "Reader", "MimeTreeMode", I18N_NOOP("Message Structure Viewer"),
1889  mimeTreeModes, DIM(mimeTreeModes), 1
1890 };
1891 
1892 
1893 static const EnumConfigEntryItem readerWindowModes[] = {
1894  { "hide", I18N_NOOP("&Do not show a message preview pane") },
1895  { "below", I18N_NOOP("Show the message preview pane belo&w the message list") },
1896  { "right", I18N_NOOP("Show the message preview pane ne&xt to the message list") }
1897 };
1898 static const EnumConfigEntry readerWindowMode = {
1899  "Geometry", "readerWindowMode", I18N_NOOP("Message Preview Pane"),
1900  readerWindowModes, DIM(readerWindowModes), 1
1901 };
1902 
1903 AppearancePageLayoutTab::AppearancePageLayoutTab( TQWidget * parent, const char * name )
1904  : ConfigModuleTab( parent, name )
1905 {
1906  // tmp. vars:
1907  TQVBoxLayout * vlay;
1908 
1909  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
1910 
1911  // "folder list" radio buttons:
1912  populateButtonGroup( mFolderListGroup = new TQHButtonGroup( this ), folderListMode );
1913  vlay->addWidget( mFolderListGroup );
1914  connect( mFolderListGroup, TQ_SIGNAL ( clicked( int ) ),
1915  this, TQ_SLOT( slotEmitChanged() ) );
1916 
1917  mFavoriteFolderViewCB = new TQCheckBox( i18n("Show favorite folder view"), this );
1918  connect( mFavoriteFolderViewCB, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
1919  vlay->addWidget( mFavoriteFolderViewCB );
1920 
1921  // "show reader window" radio buttons:
1922  populateButtonGroup( mReaderWindowModeGroup = new TQVButtonGroup( this ), readerWindowMode );
1923  vlay->addWidget( mReaderWindowModeGroup );
1924  connect( mReaderWindowModeGroup, TQ_SIGNAL ( clicked( int ) ),
1925  this, TQ_SLOT( slotEmitChanged() ) );
1926 
1927  // "Show MIME Tree" radio buttons:
1928  populateButtonGroup( mMIMETreeModeGroup = new TQVButtonGroup( this ), mimeTreeMode );
1929  vlay->addWidget( mMIMETreeModeGroup );
1930  connect( mMIMETreeModeGroup, TQ_SIGNAL ( clicked( int ) ),
1931  this, TQ_SLOT( slotEmitChanged() ) );
1932 
1933  // "MIME Tree Location" radio buttons:
1934  populateButtonGroup( mMIMETreeLocationGroup = new TQHButtonGroup( this ), mimeTreeLocation );
1935  vlay->addWidget( mMIMETreeLocationGroup );
1936  connect( mMIMETreeLocationGroup, TQ_SIGNAL ( clicked( int ) ),
1937  this, TQ_SLOT( slotEmitChanged() ) );
1938 
1939  vlay->addStretch( 10 ); // spacer
1940 }
1941 
1942 void AppearancePage::LayoutTab::doLoadOther() {
1943  const TDEConfigGroup reader( KMKernel::config(), "Reader" );
1944  const TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
1945 
1946  loadWidget( mFolderListGroup, geometry, folderListMode );
1947  loadWidget( mMIMETreeLocationGroup, reader, mimeTreeLocation );
1948  loadWidget( mMIMETreeModeGroup, reader, mimeTreeMode );
1949  loadWidget( mReaderWindowModeGroup, geometry, readerWindowMode );
1950  mFavoriteFolderViewCB->setChecked( GlobalSettings::self()->enableFavoriteFolderView() );
1951 }
1952 
1953 void AppearancePage::LayoutTab::installProfile( TDEConfig * profile ) {
1954  const TDEConfigGroup reader( profile, "Reader" );
1955  const TDEConfigGroup geometry( profile, "Geometry" );
1956 
1957  loadProfile( mFolderListGroup, geometry, folderListMode );
1958  loadProfile( mMIMETreeLocationGroup, reader, mimeTreeLocation );
1959  loadProfile( mMIMETreeModeGroup, reader, mimeTreeMode );
1960  loadProfile( mReaderWindowModeGroup, geometry, readerWindowMode );
1961 }
1962 
1963 void AppearancePage::LayoutTab::save() {
1964  TDEConfigGroup reader( KMKernel::config(), "Reader" );
1965  TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
1966 
1967  saveButtonGroup( mFolderListGroup, geometry, folderListMode );
1968  saveButtonGroup( mMIMETreeLocationGroup, reader, mimeTreeLocation );
1969  saveButtonGroup( mMIMETreeModeGroup, reader, mimeTreeMode );
1970  saveButtonGroup( mReaderWindowModeGroup, geometry, readerWindowMode );
1971  GlobalSettings::self()->setEnableFavoriteFolderView( mFavoriteFolderViewCB->isChecked() );
1972 }
1973 
1974 //
1975 // Appearance Message List
1976 //
1977 
1978 TQString AppearancePage::HeadersTab::helpAnchor() const {
1979  return TQString::fromLatin1("configure-appearance-headers");
1980 }
1981 
1982 static const struct {
1983  const char * displayName;
1984  DateFormatter::FormatType dateDisplay;
1985 } dateDisplayConfig[] = {
1986  { I18N_NOOP("Sta&ndard format (%1)"), KMime::DateFormatter::CTime },
1987  { I18N_NOOP("Locali&zed format (%1)"), KMime::DateFormatter::Localized },
1988  { I18N_NOOP("Fancy for&mat (%1)"), KMime::DateFormatter::Fancy },
1989  { I18N_NOOP("C&ustom format (Shift+F1 for help):"),
1990  KMime::DateFormatter::Custom }
1991 };
1992 static const int numDateDisplayConfig =
1993  sizeof dateDisplayConfig / sizeof *dateDisplayConfig;
1994 
1995 AppearancePageHeadersTab::AppearancePageHeadersTab( TQWidget * parent, const char * name )
1996  : ConfigModuleTab( parent, name ),
1997  mCustomDateFormatEdit( 0 )
1998 {
1999  // tmp. vars:
2000  TQButtonGroup * group;
2001  TQRadioButton * radio;
2002 
2003  TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
2004 
2005  // "General Options" group:
2006  group = new TQVButtonGroup( i18n( "General Options" ), this );
2007  group->layout()->setSpacing( KDialog::spacingHint() );
2008 
2009  mMessageSizeCheck = new TQCheckBox( i18n("Display messa&ge sizes"), group );
2010 
2011  mCryptoIconsCheck = new TQCheckBox( i18n( "Show crypto &icons" ), group );
2012 
2013  mAttachmentCheck = new TQCheckBox( i18n("Show attachment icon"), group );
2014 
2015  mNestedMessagesCheck =
2016  new TQCheckBox( i18n("&Threaded message list"), group );
2017 
2018  connect( mMessageSizeCheck, TQ_SIGNAL( stateChanged( int ) ),
2019  this, TQ_SLOT( slotEmitChanged( void ) ) );
2020  connect( mAttachmentCheck, TQ_SIGNAL( stateChanged( int ) ),
2021  this, TQ_SLOT( slotEmitChanged( void ) ) );
2022  connect( mCryptoIconsCheck, TQ_SIGNAL( stateChanged( int ) ),
2023  this, TQ_SLOT( slotEmitChanged( void ) ) );
2024  connect( mNestedMessagesCheck, TQ_SIGNAL( stateChanged( int ) ),
2025  this, TQ_SLOT( slotEmitChanged( void ) ) );
2026 
2027 
2028  vlay->addWidget( group );
2029 
2030  // "Message Header Threading Options" group:
2031  mNestingPolicy =
2032  new TQVButtonGroup( i18n("Threaded Message List Options"), this );
2033  mNestingPolicy->layout()->setSpacing( KDialog::spacingHint() );
2034 
2035  mNestingPolicy->insert(
2036  new TQRadioButton( i18n("Always &keep threads open"),
2037  mNestingPolicy ), 0 );
2038  mNestingPolicy->insert(
2039  new TQRadioButton( i18n("Threads default to o&pen"),
2040  mNestingPolicy ), 1 );
2041  mNestingPolicy->insert(
2042  new TQRadioButton( i18n("Threads default to closed"),
2043  mNestingPolicy ), 2 );
2044  mNestingPolicy->insert(
2045  new TQRadioButton( i18n("Open threads that contain ne&w, unread "
2046  "or important messages and open watched threads."),
2047  mNestingPolicy ), 3 );
2048 
2049  vlay->addWidget( mNestingPolicy );
2050 
2051  connect( mNestingPolicy, TQ_SIGNAL( clicked( int ) ),
2052  this, TQ_SLOT( slotEmitChanged( void ) ) );
2053 
2054  // "Date Display" group:
2055  mDateDisplay = new TQVButtonGroup( i18n("Date Display"), this );
2056  mDateDisplay->layout()->setSpacing( KDialog::spacingHint() );
2057 
2058  for ( int i = 0 ; i < numDateDisplayConfig ; i++ ) {
2059  TQString buttonLabel = i18n(dateDisplayConfig[i].displayName);
2060  if ( buttonLabel.contains("%1") )
2061  buttonLabel = buttonLabel.arg( DateFormatter::formatCurrentDate( dateDisplayConfig[i].dateDisplay ) );
2062  radio = new TQRadioButton( buttonLabel, mDateDisplay );
2063  mDateDisplay->insert( radio, i );
2064  if ( dateDisplayConfig[i].dateDisplay == DateFormatter::Custom ) {
2065  mCustomDateFormatEdit = new KLineEdit( mDateDisplay );
2066  mCustomDateFormatEdit->setEnabled( false );
2067  connect( radio, TQ_SIGNAL(toggled(bool)),
2068  mCustomDateFormatEdit, TQ_SLOT(setEnabled(bool)) );
2069  connect( mCustomDateFormatEdit, TQ_SIGNAL(textChanged(const TQString&)),
2070  this, TQ_SLOT(slotEmitChanged(void)) );
2071  TQString customDateWhatsThis =
2072  i18n("<qt><p><strong>These expressions may be used for the date:"
2073  "</strong></p>"
2074  "<ul>"
2075  "<li>d - the day as a number without a leading zero (1-31)</li>"
2076  "<li>dd - the day as a number with a leading zero (01-31)</li>"
2077  "<li>ddd - the abbreviated day name (Mon - Sun)</li>"
2078  "<li>dddd - the long day name (Monday - Sunday)</li>"
2079  "<li>M - the month as a number without a leading zero (1-12)</li>"
2080  "<li>MM - the month as a number with a leading zero (01-12)</li>"
2081  "<li>MMM - the abbreviated month name (Jan - Dec)</li>"
2082  "<li>MMMM - the long month name (January - December)</li>"
2083  "<li>yy - the year as a two digit number (00-99)</li>"
2084  "<li>yyyy - the year as a four digit number (0000-9999)</li>"
2085  "</ul>"
2086  "<p><strong>These expressions may be used for the time:"
2087  "</string></p> "
2088  "<ul>"
2089  "<li>h - the hour without a leading zero (0-23 or 1-12 if AM/PM display)</li>"
2090  "<li>hh - the hour with a leading zero (00-23 or 01-12 if AM/PM display)</li>"
2091  "<li>m - the minutes without a leading zero (0-59)</li>"
2092  "<li>mm - the minutes with a leading zero (00-59)</li>"
2093  "<li>s - the seconds without a leading zero (0-59)</li>"
2094  "<li>ss - the seconds with a leading zero (00-59)</li>"
2095  "<li>z - the milliseconds without leading zeroes (0-999)</li>"
2096  "<li>zzz - the milliseconds with leading zeroes (000-999)</li>"
2097  "<li>AP - switch to AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</li>"
2098  "<li>ap - switch to AM/PM display. ap will be replaced by either \"am\" or \"pm\".</li>"
2099  "<li>Z - time zone in numeric form (-0500)</li>"
2100  "</ul>"
2101  "<p><strong>All other input characters will be ignored."
2102  "</strong></p></qt>");
2103  TQWhatsThis::add( mCustomDateFormatEdit, customDateWhatsThis );
2104  TQWhatsThis::add( radio, customDateWhatsThis );
2105  }
2106  } // end for loop populating mDateDisplay
2107 
2108  vlay->addWidget( mDateDisplay );
2109  connect( mDateDisplay, TQ_SIGNAL( clicked( int ) ),
2110  this, TQ_SLOT( slotEmitChanged( void ) ) );
2111 
2112 
2113  vlay->addStretch( 10 ); // spacer
2114 }
2115 
2116 void AppearancePage::HeadersTab::doLoadOther() {
2117  TDEConfigGroup general( KMKernel::config(), "General" );
2118  TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
2119 
2120  // "General Options":
2121  mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages", false ) );
2122  mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize", false ) );
2123  mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons", false ) );
2124  mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon", true ) );
2125 
2126  // "Message Header Threading Options":
2127  int num = geometry.readNumEntry( "nestingPolicy", 3 );
2128  if ( num < 0 || num > 3 ) num = 3;
2129  mNestingPolicy->setButton( num );
2130 
2131  // "Date Display":
2132  setDateDisplay( general.readNumEntry( "dateFormat", DateFormatter::Fancy ),
2133  general.readEntry( "customDateFormat" ) );
2134 }
2135 
2136 void AppearancePage::HeadersTab::setDateDisplay( int num, const TQString & format ) {
2137  DateFormatter::FormatType dateDisplay =
2138  static_cast<DateFormatter::FormatType>( num );
2139 
2140  // special case: needs text for the line edit:
2141  if ( dateDisplay == DateFormatter::Custom )
2142  mCustomDateFormatEdit->setText( format );
2143 
2144  for ( int i = 0 ; i < numDateDisplayConfig ; i++ )
2145  if ( dateDisplay == dateDisplayConfig[i].dateDisplay ) {
2146  mDateDisplay->setButton( i );
2147  return;
2148  }
2149  // fell through since none found:
2150  mDateDisplay->setButton( numDateDisplayConfig - 2 ); // default
2151 }
2152 
2153 void AppearancePage::HeadersTab::installProfile( TDEConfig * profile ) {
2154  TDEConfigGroup general( profile, "General" );
2155  TDEConfigGroup geometry( profile, "Geometry" );
2156 
2157  if ( geometry.hasKey( "nestedMessages" ) )
2158  mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages" ) );
2159  if ( general.hasKey( "showMessageSize" ) )
2160  mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize" ) );
2161 
2162  if( general.hasKey( "showCryptoIcons" ) )
2163  mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons" ) );
2164  if ( general.hasKey( "showAttachmentIcon" ) )
2165  mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon" ) );
2166 
2167  if ( geometry.hasKey( "nestingPolicy" ) ) {
2168  int num = geometry.readNumEntry( "nestingPolicy" );
2169  if ( num < 0 || num > 3 ) num = 3;
2170  mNestingPolicy->setButton( num );
2171  }
2172 
2173  if ( general.hasKey( "dateFormat" ) )
2174  setDateDisplay( general.readNumEntry( "dateFormat" ),
2175  general.readEntry( "customDateFormat" ) );
2176 }
2177 
2178 void AppearancePage::HeadersTab::save() {
2179  TDEConfigGroup general( KMKernel::config(), "General" );
2180  TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
2181 
2182  if ( geometry.readBoolEntry( "nestedMessages", false )
2183  != mNestedMessagesCheck->isChecked() ) {
2184  int result = KMessageBox::warningContinueCancel( this,
2185  i18n("Changing the global threading setting will override "
2186  "all folder specific values."),
2187  TQString(), KStdGuiItem::cont(), "threadOverride" );
2188  if ( result == KMessageBox::Continue ) {
2189  geometry.writeEntry( "nestedMessages", mNestedMessagesCheck->isChecked() );
2190  // remove all threadMessagesOverride keys from all [Folder-*] groups:
2191  TQStringList groups = KMKernel::config()->groupList().grep( TQRegExp("^Folder-") );
2192  kdDebug(5006) << "groups.count() == " << groups.count() << endl;
2193  for ( TQStringList::const_iterator it = groups.begin() ; it != groups.end() ; ++it ) {
2194  TDEConfigGroup group( KMKernel::config(), *it );
2195  group.deleteEntry( "threadMessagesOverride" );
2196  }
2197  }
2198  }
2199 
2200  geometry.writeEntry( "nestingPolicy",
2201  mNestingPolicy->id( mNestingPolicy->selected() ) );
2202  general.writeEntry( "showMessageSize", mMessageSizeCheck->isChecked() );
2203  general.writeEntry( "showCryptoIcons", mCryptoIconsCheck->isChecked() );
2204  general.writeEntry( "showAttachmentIcon", mAttachmentCheck->isChecked() );
2205 
2206  int dateDisplayID = mDateDisplay->id( mDateDisplay->selected() );
2207  // check bounds:
2208  assert( dateDisplayID >= 0 ); assert( dateDisplayID < numDateDisplayConfig );
2209  general.writeEntry( "dateFormat",
2210  dateDisplayConfig[ dateDisplayID ].dateDisplay );
2211  general.writeEntry( "customDateFormat", mCustomDateFormatEdit->text() );
2212 }
2213 
2214 
2215 //
2216 // Message Window
2217 //
2218 
2219 
2220 static const BoolConfigEntry closeAfterReplyOrForward = {
2221  "Reader", "CloseAfterReplyOrForward", I18N_NOOP("Close message window after replying or forwarding"), false
2222 };
2223 
2224 static const BoolConfigEntry showColorbarMode = {
2225  "Reader", "showColorbar", I18N_NOOP("Show HTML stat&us bar"), false
2226 };
2227 
2228 static const BoolConfigEntry showSpamStatusMode = {
2229  "Reader", "showSpamStatus", I18N_NOOP("Show s&pam status in fancy headers"), true
2230 };
2231 
2232 static const BoolConfigEntry showEmoticons = {
2233  "Reader", "ShowEmoticons", I18N_NOOP("Replace smileys by emoticons"), true
2234 };
2235 
2236 static const BoolConfigEntry shrinkQuotes = {
2237  "Reader", "ShrinkQuotes", I18N_NOOP("Use smaller font for quoted text"), false
2238 };
2239 
2240 static const BoolConfigEntry showExpandQuotesMark= {
2241  "Reader", "ShowExpandQuotesMark", I18N_NOOP("Show expand/collapse quote marks"), false
2242 };
2243 
2244 static const BoolConfigEntry showCurrentTime = {
2245  "Reader", "ShowCurrentTime", I18N_NOOP("Show current sender time"), true
2246 };
2247 
2248 TQString AppearancePage::ReaderTab::helpAnchor() const {
2249  return TQString::fromLatin1("configure-appearance-reader");
2250 }
2251 
2252 AppearancePageReaderTab::AppearancePageReaderTab( TQWidget * parent,
2253  const char * name )
2254  : ConfigModuleTab( parent, name )
2255 {
2256  TQVBoxLayout *vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
2257 
2258  // "close message window after replying or forwarding" checkbox
2259  populateCheckBox( mCloseAfterReplyOrForwardCheck = new TQCheckBox( this ),
2260  closeAfterReplyOrForward );
2261  TQToolTip::add( mCloseAfterReplyOrForwardCheck,
2262  i18n( "Close the standalone message window after replying or forwarding the message" ) );
2263  vlay->addWidget( mCloseAfterReplyOrForwardCheck );
2264  connect( mCloseAfterReplyOrForwardCheck, TQ_SIGNAL ( stateChanged( int ) ),
2265  this, TQ_SLOT( slotEmitChanged() ) );
2266 
2267  // "show colorbar" check box:
2268  populateCheckBox( mShowColorbarCheck = new TQCheckBox( this ), showColorbarMode );
2269  vlay->addWidget( mShowColorbarCheck );
2270  connect( mShowColorbarCheck, TQ_SIGNAL ( stateChanged( int ) ),
2271  this, TQ_SLOT( slotEmitChanged() ) );
2272 
2273  // "show spam status" check box;
2274  populateCheckBox( mShowSpamStatusCheck = new TQCheckBox( this ), showSpamStatusMode );
2275  vlay->addWidget( mShowSpamStatusCheck );
2276  connect( mShowSpamStatusCheck, TQ_SIGNAL ( stateChanged( int ) ),
2277  this, TQ_SLOT( slotEmitChanged() ) );
2278 
2279  // "replace smileys by emoticons" check box;
2280  populateCheckBox( mShowEmoticonsCheck = new TQCheckBox( this ), showEmoticons );
2281  vlay->addWidget( mShowEmoticonsCheck );
2282  connect( mShowEmoticonsCheck, TQ_SIGNAL ( stateChanged( int ) ),
2283  this, TQ_SLOT( slotEmitChanged() ) );
2284 
2285  // "Use smaller font for quoted text" check box
2286  mShrinkQuotesCheck = new TQCheckBox( i18n( shrinkQuotes.desc ), this,
2287  "kcfg_ShrinkQuotes" );
2288  vlay->addWidget( mShrinkQuotesCheck );
2289  connect( mShrinkQuotesCheck, TQ_SIGNAL( stateChanged( int ) ),
2290  this, TQ_SLOT( slotEmitChanged() ) );
2291 
2292  // "Show expand/collaps quote marks" check box;
2293  TQHBoxLayout *hlay= new TQHBoxLayout( vlay ); // inherits spacing
2294  populateCheckBox( mShowExpandQuotesMark= new TQCheckBox( this ), showExpandQuotesMark);
2295  hlay->addWidget( mShowExpandQuotesMark);
2296  connect( mShowExpandQuotesMark, TQ_SIGNAL ( stateChanged( int ) ),
2297  this, TQ_SLOT( slotEmitChanged() ) );
2298 
2299  hlay->addStretch( 1 );
2300  mCollapseQuoteLevelSpin = new KIntSpinBox( 0/*min*/,10/*max*/,1/*step*/,
2301  3/*init*/,10/*base*/,this );
2302 
2303  TQLabel *label = new TQLabel( mCollapseQuoteLevelSpin,
2304  GlobalSettings::self()->collapseQuoteLevelSpinItem()->label(), this );
2305 
2306  hlay->addWidget( label );
2307 
2308  mCollapseQuoteLevelSpin->setEnabled( false ); //since !mShowExpandQuotesMark->isCheckec()
2309  connect( mCollapseQuoteLevelSpin, TQ_SIGNAL( valueChanged( int ) ),
2310  this, TQ_SLOT( slotEmitChanged( void ) ) );
2311  hlay->addWidget( mCollapseQuoteLevelSpin);
2312 
2313  connect( mShowExpandQuotesMark, TQ_SIGNAL( toggled( bool ) ),
2314  mCollapseQuoteLevelSpin, TQ_SLOT( setEnabled( bool ) ) );
2315 
2316  // Fallback Character Encoding
2317  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2318  mCharsetCombo = new TQComboBox( this );
2319  mCharsetCombo->insertStringList( KMMsgBase::supportedEncodings( false ) );
2320 
2321  connect( mCharsetCombo, TQ_SIGNAL( activated( int ) ),
2322  this, TQ_SLOT( slotEmitChanged( void ) ) );
2323 
2324  TQString fallbackCharsetWhatsThis =
2325  i18n( GlobalSettings::self()->fallbackCharacterEncodingItem()->whatsThis().utf8() );
2326  TQWhatsThis::add( mCharsetCombo, fallbackCharsetWhatsThis );
2327 
2328  label = new TQLabel( i18n("Fallback ch&aracter encoding:"), this );
2329  label->setBuddy( mCharsetCombo );
2330 
2331  hlay->addWidget( label );
2332  hlay->addWidget( mCharsetCombo );
2333 
2334  // Override Character Encoding
2335  TQHBoxLayout *hlay2 = new TQHBoxLayout( vlay ); // inherits spacing
2336  mOverrideCharsetCombo = new TQComboBox( this );
2337  TQStringList encodings = KMMsgBase::supportedEncodings( false );
2338  encodings.prepend( i18n( "Auto" ) );
2339  mOverrideCharsetCombo->insertStringList( encodings );
2340  mOverrideCharsetCombo->setCurrentItem(0);
2341 
2342  connect( mOverrideCharsetCombo, TQ_SIGNAL( activated( int ) ),
2343  this, TQ_SLOT( slotEmitChanged( void ) ) );
2344 
2345  TQString overrideCharsetWhatsThis =
2346  i18n( GlobalSettings::self()->overrideCharacterEncodingItem()->whatsThis().utf8() );
2347  TQWhatsThis::add( mOverrideCharsetCombo, overrideCharsetWhatsThis );
2348 
2349  label = new TQLabel( i18n("&Override character encoding:"), this );
2350  label->setBuddy( mOverrideCharsetCombo );
2351 
2352  hlay2->addWidget( label );
2353  hlay2->addWidget( mOverrideCharsetCombo );
2354 
2355  populateCheckBox( mShowCurrentTimeCheck = new TQCheckBox( this ), showCurrentTime );
2356  vlay->addWidget( mShowCurrentTimeCheck );
2357  connect( mShowCurrentTimeCheck, TQ_SIGNAL ( stateChanged( int ) ),
2358  this, TQ_SLOT( slotEmitChanged() ) );
2359 
2360  vlay->addStretch( 100 ); // spacer
2361 }
2362 
2363 
2364 void AppearancePage::ReaderTab::readCurrentFallbackCodec()
2365 {
2366  TQStringList encodings = KMMsgBase::supportedEncodings( false );
2367  TQStringList::ConstIterator it( encodings.begin() );
2368  TQStringList::ConstIterator end( encodings.end() );
2369  TQString currentEncoding = GlobalSettings::self()->fallbackCharacterEncoding();
2370  currentEncoding = currentEncoding.replace( "iso ", "iso-", false );
2372  int i = 0;
2373  int indexOfLatin9 = 0;
2374  bool found = false;
2375  for( ; it != end; ++it)
2376  {
2377  const TQString encoding = TDEGlobal::charsets()->encodingForName(*it);
2378  if ( encoding == "iso-8859-15" )
2379  indexOfLatin9 = i;
2380  if( encoding == currentEncoding )
2381  {
2382  mCharsetCombo->setCurrentItem( i );
2383  found = true;
2384  break;
2385  }
2386  i++;
2387  }
2388  if ( !found ) // nothing matched, use latin9
2389  mCharsetCombo->setCurrentItem( indexOfLatin9 );
2390 }
2391 
2392 void AppearancePage::ReaderTab::readCurrentOverrideCodec()
2393 {
2394  const TQString &currentOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
2395  if ( currentOverrideEncoding.isEmpty() ) {
2396  mOverrideCharsetCombo->setCurrentItem( 0 );
2397  return;
2398  }
2399  TQStringList encodings = KMMsgBase::supportedEncodings( false );
2400  encodings.prepend( i18n( "Auto" ) );
2401  TQStringList::Iterator it( encodings.begin() );
2402  TQStringList::Iterator end( encodings.end() );
2403  uint i = 0;
2404  for( ; it != end; ++it)
2405  {
2406  if( TDEGlobal::charsets()->encodingForName(*it) == currentOverrideEncoding )
2407  {
2408  mOverrideCharsetCombo->setCurrentItem( i );
2409  break;
2410  }
2411  i++;
2412  }
2413  if ( i == encodings.size() ) {
2414  // the current value of overrideCharacterEncoding is an unknown encoding => reset to Auto
2415  kdWarning(5006) << "Unknown override character encoding \"" << currentOverrideEncoding
2416  << "\". Resetting to Auto." << endl;
2417  mOverrideCharsetCombo->setCurrentItem( 0 );
2418  GlobalSettings::self()->setOverrideCharacterEncoding( TQString() );
2419  }
2420 }
2421 
2422 void AppearancePage::ReaderTab::doLoadFromGlobalSettings()
2423 {
2424  mCloseAfterReplyOrForwardCheck->setChecked( GlobalSettings::self()->closeAfterReplyOrForward() );
2425  mShowEmoticonsCheck->setChecked( GlobalSettings::self()->showEmoticons() );
2426  mShrinkQuotesCheck->setChecked( GlobalSettings::self()->shrinkQuotes() );
2427  mShowExpandQuotesMark->setChecked( GlobalSettings::self()->showExpandQuotesMark() );
2428  mCollapseQuoteLevelSpin->setValue( GlobalSettings::self()->collapseQuoteLevelSpin() );
2429  readCurrentFallbackCodec();
2430  readCurrentOverrideCodec();
2431  mShowCurrentTimeCheck->setChecked( GlobalSettings::self()->showCurrentTime() );
2432 }
2433 
2434 void AppearancePage::ReaderTab::doLoadOther()
2435 {
2436  const TDEConfigGroup reader( KMKernel::config(), "Reader" );
2437  loadWidget( mShowColorbarCheck, reader, showColorbarMode );
2438  loadWidget( mShowSpamStatusCheck, reader, showSpamStatusMode );
2439 }
2440 
2441 
2442 void AppearancePage::ReaderTab::save() {
2443  TDEConfigGroup reader( KMKernel::config(), "Reader" );
2444  saveCheckBox( mShowColorbarCheck, reader, showColorbarMode );
2445  saveCheckBox( mShowSpamStatusCheck, reader, showSpamStatusMode );
2446  GlobalSettings::self()->setCloseAfterReplyOrForward( mCloseAfterReplyOrForwardCheck->isChecked() );
2447  GlobalSettings::self()->setShowEmoticons( mShowEmoticonsCheck->isChecked() );
2448  GlobalSettings::self()->setShrinkQuotes( mShrinkQuotesCheck->isChecked() );
2449  GlobalSettings::self()->setShowExpandQuotesMark( mShowExpandQuotesMark->isChecked() );
2450 
2451  GlobalSettings::self()->setCollapseQuoteLevelSpin( mCollapseQuoteLevelSpin->value() );
2452  GlobalSettings::self()->setFallbackCharacterEncoding(
2453  TDEGlobal::charsets()->encodingForName( mCharsetCombo->currentText() ) );
2454  GlobalSettings::self()->setOverrideCharacterEncoding(
2455  mOverrideCharsetCombo->currentItem() == 0 ?
2456  TQString() :
2457  TDEGlobal::charsets()->encodingForName( mOverrideCharsetCombo->currentText() ) );
2458  GlobalSettings::self()->setShowCurrentTime( mShowCurrentTimeCheck->isChecked() );
2459 }
2460 
2461 
2462 void AppearancePage::ReaderTab::installProfile( TDEConfig * /* profile */ ) {
2463  const TDEConfigGroup reader( KMKernel::config(), "Reader" );
2464  loadProfile( mCloseAfterReplyOrForwardCheck, reader, closeAfterReplyOrForward );
2465  loadProfile( mShowColorbarCheck, reader, showColorbarMode );
2466  loadProfile( mShowSpamStatusCheck, reader, showSpamStatusMode );
2467  loadProfile( mShowEmoticonsCheck, reader, showEmoticons );
2468  loadProfile( mShrinkQuotesCheck, reader, shrinkQuotes );
2469  loadProfile( mShowExpandQuotesMark, reader, showExpandQuotesMark);
2470  loadProfile( mShowCurrentTimeCheck, reader, showCurrentTime );
2471 }
2472 
2473 
2474 TQString AppearancePage::SystemTrayTab::helpAnchor() const {
2475  return TQString::fromLatin1("configure-appearance-systemtray");
2476 }
2477 
2478 AppearancePageSystemTrayTab::AppearancePageSystemTrayTab( TQWidget * parent,
2479  const char * name )
2480  : ConfigModuleTab( parent, name )
2481 {
2482  TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(),
2483  KDialog::spacingHint() );
2484 
2485  // "Enable system tray applet" check box
2486  mSystemTrayCheck = new TQCheckBox( i18n("Enable system tray icon"), this );
2487  vlay->addWidget( mSystemTrayCheck );
2488  connect( mSystemTrayCheck, TQ_SIGNAL( stateChanged( int ) ),
2489  this, TQ_SLOT( slotEmitChanged( void ) ) );
2490 
2491  // System tray modes
2492  mSystemTrayGroup = new TQVButtonGroup( i18n("System Tray Mode"), this );
2493  mSystemTrayGroup->layout()->setSpacing( KDialog::spacingHint() );
2494  vlay->addWidget( mSystemTrayGroup );
2495  connect( mSystemTrayGroup, TQ_SIGNAL( clicked( int ) ),
2496  this, TQ_SLOT( slotEmitChanged( void ) ) );
2497  connect( mSystemTrayCheck, TQ_SIGNAL( toggled( bool ) ),
2498  mSystemTrayGroup, TQ_SLOT( setEnabled( bool ) ) );
2499 
2500  mSystemTrayGroup->insert( new TQRadioButton( i18n("Always show KMail in system tray"), mSystemTrayGroup ),
2501  GlobalSettings::EnumSystemTrayPolicy::ShowAlways );
2502 
2503  mSystemTrayGroup->insert( new TQRadioButton( i18n("Only show KMail in system tray if there are unread messages"), mSystemTrayGroup ),
2504  GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread );
2505 
2506  vlay->addStretch( 10 ); // spacer
2507 }
2508 
2509 void AppearancePage::SystemTrayTab::doLoadFromGlobalSettings() {
2510  mSystemTrayCheck->setChecked( GlobalSettings::self()->systemTrayEnabled() );
2511  mSystemTrayGroup->setButton( GlobalSettings::self()->systemTrayPolicy() );
2512  mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
2513 }
2514 
2515 void AppearancePage::SystemTrayTab::installProfile( TDEConfig * profile ) {
2516  TDEConfigGroup general( profile, "General" );
2517 
2518  if ( general.hasKey( "SystemTrayEnabled" ) ) {
2519  mSystemTrayCheck->setChecked( general.readBoolEntry( "SystemTrayEnabled" ) );
2520  }
2521  if ( general.hasKey( "SystemTrayPolicy" ) ) {
2522  mSystemTrayGroup->setButton( general.readNumEntry( "SystemTrayPolicy" ) );
2523  }
2524  mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
2525 }
2526 
2527 void AppearancePage::SystemTrayTab::save() {
2528  GlobalSettings::self()->setSystemTrayEnabled( mSystemTrayCheck->isChecked() );
2529  GlobalSettings::self()->setSystemTrayPolicy( mSystemTrayGroup->id( mSystemTrayGroup->selected() ) );
2530 }
2531 
2532 
2533 // *************************************************************
2534 // * *
2535 // * ComposerPage *
2536 // * *
2537 // *************************************************************
2538 
2539 TQString ComposerPage::helpAnchor() const {
2540  return TQString::fromLatin1("configure-composer");
2541 }
2542 
2543 ComposerPage::ComposerPage( TQWidget * parent, const char * name )
2544  : ConfigModuleWithTabs( parent, name )
2545 {
2546  //
2547  // "General" tab:
2548  //
2549  mGeneralTab = new GeneralTab();
2550  addTab( mGeneralTab, i18n("&General") );
2551  addConfig( GlobalSettings::self(), mGeneralTab );
2552 
2553  //
2554  // "Phrases" tab:
2555  //
2556  // mPhrasesTab = new PhrasesTab();
2557  // addTab( mPhrasesTab, i18n("&Phrases") );
2558 
2559  //
2560  // "Templates" tab:
2561  //
2562  mTemplatesTab = new TemplatesTab();
2563  addTab( mTemplatesTab, i18n("&Templates") );
2564 
2565  //
2566  // "Custom Templates" tab:
2567  //
2568  mCustomTemplatesTab = new CustomTemplatesTab();
2569  addTab( mCustomTemplatesTab, i18n("&Custom Templates") );
2570 
2571  //
2572  // "Subject" tab:
2573  //
2574  mSubjectTab = new SubjectTab();
2575  addTab( mSubjectTab, i18n("&Subject") );
2576  addConfig( GlobalSettings::self(), mSubjectTab );
2577 
2578  //
2579  // "Charset" tab:
2580  //
2581  mCharsetTab = new CharsetTab();
2582  addTab( mCharsetTab, i18n("Cha&rset") );
2583 
2584  //
2585  // "Headers" tab:
2586  //
2587  mHeadersTab = new HeadersTab();
2588  addTab( mHeadersTab, i18n("H&eaders") );
2589 
2590  //
2591  // "Attachments" tab:
2592  //
2593  mAttachmentsTab = new AttachmentsTab();
2594  addTab( mAttachmentsTab, i18n("Config->Composer->Attachments", "A&ttachments") );
2595  load();
2596 }
2597 
2598 TQString ComposerPage::GeneralTab::helpAnchor() const {
2599  return TQString::fromLatin1("configure-composer-general");
2600 }
2601 
2602 ComposerPageGeneralTab::ComposerPageGeneralTab( TQWidget * parent, const char * name )
2603  : ConfigModuleTab( parent, name )
2604 {
2605  // tmp. vars:
2606  TQVBoxLayout *vlay;
2607  TQHBoxLayout *hlay;
2608  TQGroupBox *group;
2609  TQLabel *label;
2610  TQHBox *hbox;
2611  TQString msg;
2612 
2613  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
2614 
2615  // some check buttons...
2616  mAutoAppSignFileCheck = new TQCheckBox(
2617  GlobalSettings::self()->autoTextSignatureItem()->label(),
2618  this );
2619  vlay->addWidget( mAutoAppSignFileCheck );
2620  connect( mAutoAppSignFileCheck, TQ_SIGNAL( stateChanged(int) ),
2621  this, TQ_SLOT( slotEmitChanged( void ) ) );
2622 
2623  mTopQuoteCheck =
2624  new TQCheckBox( GlobalSettings::self()->prependSignatureItem()->label(), this );
2625  vlay->addWidget( mTopQuoteCheck);
2626  connect( mTopQuoteCheck, TQ_SIGNAL( stateChanged(int) ),
2627  this, TQ_SLOT( slotEmitChanged( void ) ) );
2628 
2629  mSmartQuoteCheck = new TQCheckBox(
2630  GlobalSettings::self()->smartQuoteItem()->label(),
2631  this, "kcfg_SmartQuote" );
2632  TQToolTip::add( mSmartQuoteCheck,
2633  i18n( "When replying, add quote signs in front of all lines of the quoted text,\n"
2634  "even when the line was created by adding an additional linebreak while\n"
2635  "word-wrapping the text." ) );
2636  vlay->addWidget( mSmartQuoteCheck );
2637  connect( mSmartQuoteCheck, TQ_SIGNAL( stateChanged(int) ),
2638  this, TQ_SLOT( slotEmitChanged( void ) ) );
2639 
2640  mQuoteSelectionOnlyCheck = new TQCheckBox( GlobalSettings::self()->quoteSelectionOnlyItem()->label(),
2641  this, "kcfg_QuoteSelectionOnly" );
2642  TQToolTip::add( mQuoteSelectionOnlyCheck,
2643  i18n( "When replying, only quote the selected text instead of the complete message "
2644  "when there is text selected in the message window." ) );
2645  vlay->addWidget( mQuoteSelectionOnlyCheck );
2646  connect( mQuoteSelectionOnlyCheck, TQ_SIGNAL( stateChanged(int) ),
2647  this, TQ_SLOT( slotEmitChanged(void) ) );
2648 
2649  mStripSignatureCheck = new TQCheckBox( GlobalSettings::self()->stripSignatureItem()->label(),
2650  this, "kcfg_StripSignature" );
2651  vlay->addWidget( mStripSignatureCheck );
2652  connect( mStripSignatureCheck, TQ_SIGNAL( stateChanged(int) ),
2653  this, TQ_SLOT( slotEmitChanged( void ) ) );
2654 
2655  mAutoRequestMDNCheck = new TQCheckBox(
2656  GlobalSettings::self()->requestMDNItem()->label(),
2657  this, "kcfg_RequestMDN" );
2658  vlay->addWidget( mAutoRequestMDNCheck );
2659  connect( mAutoRequestMDNCheck, TQ_SIGNAL( stateChanged(int) ),
2660  this, TQ_SLOT( slotEmitChanged( void ) ) );
2661 
2662  mShowRecentAddressesInComposer = new TQCheckBox(
2663  GlobalSettings::self()->showRecentAddressesInComposerItem()->label(),
2664  this, "kcfg_ShowRecentAddressesInComposer" );
2665  vlay->addWidget( mShowRecentAddressesInComposer );
2666  connect( mShowRecentAddressesInComposer, TQ_SIGNAL( stateChanged(int) ),
2667  this, TQ_SLOT( slotEmitChanged( void ) ) );
2668 
2669  // a checkbox for "word wrap" and a spinbox for the column in
2670  // which to wrap:
2671  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2672  mWordWrapCheck = new TQCheckBox(
2673  GlobalSettings::self()->wordWrapItem()->label(),
2674  this, "kcfg_WordWrap" );
2675  hlay->addWidget( mWordWrapCheck );
2676  connect( mWordWrapCheck, TQ_SIGNAL( stateChanged(int) ),
2677  this, TQ_SLOT( slotEmitChanged( void ) ) );
2678 
2679  mWrapColumnSpin = new KIntSpinBox( 30/*min*/, 78/*max*/, 1/*step*/,
2680  78/*init*/, 10 /*base*/, this, "kcfg_LineWrapWidth" );
2681  mWrapColumnSpin->setEnabled( false ); // since !mWordWrapCheck->isChecked()
2682  connect( mWrapColumnSpin, TQ_SIGNAL( valueChanged(int) ),
2683  this, TQ_SLOT( slotEmitChanged( void ) ) );
2684 
2685  hlay->addWidget( mWrapColumnSpin );
2686  hlay->addStretch( 1 );
2687  // only enable the spinbox if the checkbox is checked:
2688  connect( mWordWrapCheck, TQ_SIGNAL(toggled(bool)),
2689  mWrapColumnSpin, TQ_SLOT(setEnabled(bool)) );
2690 
2691  // a checkbox for "too many recipient warning" and a spinbox for the recipient threshold
2692  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2693  mRecipientCheck = new TQCheckBox(
2694  GlobalSettings::self()->tooManyRecipientsItem()->label(),
2695  this, "kcfg_TooManyRecipients" );
2696  hlay->addWidget( mRecipientCheck );
2697  connect( mRecipientCheck, TQ_SIGNAL( stateChanged(int) ),
2698  this, TQ_SLOT( slotEmitChanged( void ) ) );
2699 
2700  TQString recipientCheckWhatsthis =
2701  i18n( GlobalSettings::self()->tooManyRecipientsItem()->whatsThis().utf8() );
2702  TQWhatsThis::add( mRecipientCheck, recipientCheckWhatsthis );
2703  TQToolTip::add( mRecipientCheck,
2704  i18n( "Warn if too many recipients are specified" ) );
2705 
2706  mRecipientSpin = new KIntSpinBox( 1/*min*/, 100/*max*/, 1/*step*/,
2707  5/*init*/, 10 /*base*/, this, "kcfg_RecipientThreshold" );
2708  mRecipientSpin->setEnabled( false );
2709  connect( mRecipientSpin, TQ_SIGNAL( valueChanged(int) ),
2710  this, TQ_SLOT( slotEmitChanged( void ) ) );
2711 
2712  TQString recipientWhatsthis =
2713  i18n( GlobalSettings::self()->recipientThresholdItem()->whatsThis().utf8() );
2714  TQWhatsThis::add( mRecipientSpin, recipientWhatsthis );
2715  TQToolTip::add( mRecipientSpin,
2716  i18n( "Warn if more than this many recipients are specified" ) );
2717 
2718 
2719  hlay->addWidget( mRecipientSpin );
2720  hlay->addStretch( 1 );
2721  // only enable the spinbox if the checkbox is checked:
2722  connect( mRecipientCheck, TQ_SIGNAL(toggled(bool)),
2723  mRecipientSpin, TQ_SLOT(setEnabled(bool)) );
2724 
2725 
2726  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2727  mAutoSave = new KIntSpinBox( 0, 60, 1, 1, 10, this, "kcfg_AutosaveInterval" );
2728  label = new TQLabel( mAutoSave,
2729  GlobalSettings::self()->autosaveIntervalItem()->label(), this );
2730  hlay->addWidget( label );
2731  hlay->addWidget( mAutoSave );
2732  mAutoSave->setSpecialValueText( i18n("No autosave") );
2733  mAutoSave->setSuffix( i18n(" min") );
2734  hlay->addStretch( 1 );
2735  connect( mAutoSave, TQ_SIGNAL( valueChanged(int) ),
2736  this, TQ_SLOT( slotEmitChanged( void ) ) );
2737 
2738  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2739  mForwardTypeCombo = new KComboBox( false, this );
2740  label = new TQLabel( mForwardTypeCombo,
2741  i18n( "Default Forwarding Type:" ),
2742  this );
2743  mForwardTypeCombo->insertStringList( TQStringList()
2744  << i18n( "Inline" )
2745  << i18n( "As Attachment" ) );
2746  hlay->addWidget( label );
2747  hlay->addWidget( mForwardTypeCombo );
2748  hlay->addStretch( 1 );
2749  connect( mForwardTypeCombo, TQ_SIGNAL(activated(int)),
2750  this, TQ_SLOT( slotEmitChanged( void ) ) );
2751 
2752  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2753  TQPushButton *completionOrderBtn = new TQPushButton( i18n( "Configure Completion Order" ), this );
2754  connect( completionOrderBtn, TQ_SIGNAL( clicked() ),
2755  this, TQ_SLOT( slotConfigureCompletionOrder() ) );
2756  hlay->addWidget( completionOrderBtn );
2757  hlay->addItem( new TQSpacerItem(0, 0) );
2758 
2759  // recent addresses
2760  hlay = new TQHBoxLayout( vlay ); // inherits spacing
2761  TQPushButton *recentAddressesBtn = new TQPushButton( i18n( "Edit Recent Addresses..." ), this );
2762  connect( recentAddressesBtn, TQ_SIGNAL( clicked() ),
2763  this, TQ_SLOT( slotConfigureRecentAddresses() ) );
2764  hlay->addWidget( recentAddressesBtn );
2765  hlay->addItem( new TQSpacerItem(0, 0) );
2766 
2767  // The "external editor" group:
2768  group = new TQVGroupBox( i18n("External Editor"), this );
2769  group->layout()->setSpacing( KDialog::spacingHint() );
2770 
2771  mExternalEditorCheck = new TQCheckBox(
2772  GlobalSettings::self()->useExternalEditorItem()->label(),
2773  group, "kcfg_UseExternalEditor" );
2774  connect( mExternalEditorCheck, TQ_SIGNAL( toggled( bool ) ),
2775  this, TQ_SLOT( slotEmitChanged( void ) ) );
2776 
2777  hbox = new TQHBox( group );
2778  label = new TQLabel( GlobalSettings::self()->externalEditorItem()->label(),
2779  hbox );
2780  mEditorRequester = new KURLRequester( hbox, "kcfg_ExternalEditor" );
2781  connect( mEditorRequester, TQ_SIGNAL( urlSelected(const TQString&) ),
2782  this, TQ_SLOT( slotEmitChanged( void ) ) );
2783  connect( mEditorRequester, TQ_SIGNAL( textChanged(const TQString&) ),
2784  this, TQ_SLOT( slotEmitChanged( void ) ) );
2785 
2786  hbox->setStretchFactor( mEditorRequester, 1 );
2787  label->setBuddy( mEditorRequester );
2788  label->setEnabled( false ); // since !mExternalEditorCheck->isChecked()
2789  // ### FIXME: allow only executables (x-bit when available..)
2790  mEditorRequester->setFilter( "application/x-executable "
2791  "application/x-shellscript "
2792  "application/x-desktop" );
2793  mEditorRequester->setEnabled( false ); // !mExternalEditorCheck->isChecked()
2794  connect( mExternalEditorCheck, TQ_SIGNAL(toggled(bool)),
2795  label, TQ_SLOT(setEnabled(bool)) );
2796  connect( mExternalEditorCheck, TQ_SIGNAL(toggled(bool)),
2797  mEditorRequester, TQ_SLOT(setEnabled(bool)) );
2798 
2799  label = new TQLabel( i18n("<b>%f</b> will be replaced with the "
2800  "filename to edit."), group );
2801  label->setEnabled( false ); // see above
2802  connect( mExternalEditorCheck, TQ_SIGNAL(toggled(bool)),
2803  label, TQ_SLOT(setEnabled(bool)) );
2804 
2805  vlay->addWidget( group );
2806  vlay->addStretch( 100 );
2807 }
2808 
2809 void ComposerPage::GeneralTab::doLoadFromGlobalSettings() {
2810  // various check boxes:
2811 
2812  mAutoAppSignFileCheck->setChecked(
2813  GlobalSettings::self()->autoTextSignature()=="auto" );
2814  mTopQuoteCheck->setChecked( GlobalSettings::self()->prependSignature() );
2815  mSmartQuoteCheck->setChecked( GlobalSettings::self()->smartQuote() );
2816  mQuoteSelectionOnlyCheck->setChecked( GlobalSettings::self()->quoteSelectionOnly() );
2817  mStripSignatureCheck->setChecked( GlobalSettings::self()->stripSignature() );
2818  mAutoRequestMDNCheck->setChecked( GlobalSettings::self()->requestMDN() );
2819  mWordWrapCheck->setChecked( GlobalSettings::self()->wordWrap() );
2820 
2821  mWrapColumnSpin->setValue( GlobalSettings::self()->lineWrapWidth() );
2822  mRecipientCheck->setChecked( GlobalSettings::self()->tooManyRecipients() );
2823  mRecipientSpin->setValue( GlobalSettings::self()->recipientThreshold() );
2824  mAutoSave->setValue( GlobalSettings::self()->autosaveInterval() );
2825  if ( GlobalSettings::self()->forwardingInlineByDefault() )
2826  mForwardTypeCombo->setCurrentItem( 0 );
2827  else
2828  mForwardTypeCombo->setCurrentItem( 1 );
2829 
2830  // editor group:
2831  mExternalEditorCheck->setChecked( GlobalSettings::self()->useExternalEditor() );
2832  mEditorRequester->setURL( GlobalSettings::self()->externalEditor() );
2833 }
2834 
2835 void ComposerPage::GeneralTab::installProfile( TDEConfig * profile ) {
2836  TDEConfigGroup composer( profile, "Composer" );
2837  TDEConfigGroup general( profile, "General" );
2838 
2839  if ( composer.hasKey( "signature" ) ) {
2840  bool state = composer.readBoolEntry("signature");
2841  mAutoAppSignFileCheck->setChecked( state );
2842  }
2843  if ( composer.hasKey( "prepend-signature" ) )
2844  mTopQuoteCheck->setChecked( composer.readBoolEntry( "prepend-signature" ) );
2845  if ( composer.hasKey( "smart-quote" ) )
2846  mSmartQuoteCheck->setChecked( composer.readBoolEntry( "smart-quote" ) );
2847  if ( composer.hasKey( "StripSignature" ) )
2848  mStripSignatureCheck->setChecked( composer.readBoolEntry( "StripSignature" ) );
2849  if ( composer.hasKey( "QuoteSelectionOnly" ) )
2850  mQuoteSelectionOnlyCheck->setChecked( composer.readBoolEntry( "QuoteSelectionOnly" ) );
2851  if ( composer.hasKey( "request-mdn" ) )
2852  mAutoRequestMDNCheck->setChecked( composer.readBoolEntry( "request-mdn" ) );
2853  if ( composer.hasKey( "word-wrap" ) )
2854  mWordWrapCheck->setChecked( composer.readBoolEntry( "word-wrap" ) );
2855  if ( composer.hasKey( "break-at" ) )
2856  mWrapColumnSpin->setValue( composer.readNumEntry( "break-at" ) );
2857  if ( composer.hasKey( "too-many-recipients" ) )
2858  mRecipientCheck->setChecked( composer.readBoolEntry( "too-many-recipients" ) );
2859  if ( composer.hasKey( "recipient-threshold" ) )
2860  mRecipientSpin->setValue( composer.readNumEntry( "recipient-threshold" ) );
2861  if ( composer.hasKey( "autosave" ) )
2862  mAutoSave->setValue( composer.readNumEntry( "autosave" ) );
2863 
2864  if ( general.hasKey( "use-external-editor" )
2865  && general.hasKey( "external-editor" ) ) {
2866  mExternalEditorCheck->setChecked( general.readBoolEntry( "use-external-editor" ) );
2867  mEditorRequester->setURL( general.readPathEntry( "external-editor" ) );
2868  }
2869 }
2870 
2871 void ComposerPage::GeneralTab::save() {
2872  GlobalSettings::self()->setAutoTextSignature(
2873  mAutoAppSignFileCheck->isChecked() ? "auto" : "manual" );
2874  GlobalSettings::self()->setPrependSignature( mTopQuoteCheck->isChecked());
2875  GlobalSettings::self()->setSmartQuote( mSmartQuoteCheck->isChecked() );
2876  GlobalSettings::self()->setQuoteSelectionOnly( mQuoteSelectionOnlyCheck->isChecked() );
2877  GlobalSettings::self()->setStripSignature( mStripSignatureCheck->isChecked() );
2878  GlobalSettings::self()->setRequestMDN( mAutoRequestMDNCheck->isChecked() );
2879  GlobalSettings::self()->setWordWrap( mWordWrapCheck->isChecked() );
2880 
2881  GlobalSettings::self()->setLineWrapWidth( mWrapColumnSpin->value() );
2882  GlobalSettings::self()->setTooManyRecipients( mRecipientCheck->isChecked() );
2883  GlobalSettings::self()->setRecipientThreshold( mRecipientSpin->value() );
2884  GlobalSettings::self()->setAutosaveInterval( mAutoSave->value() );
2885  GlobalSettings::self()->setForwardingInlineByDefault( mForwardTypeCombo->currentItem() == 0 );
2886 
2887  // editor group:
2888  GlobalSettings::self()->setUseExternalEditor( mExternalEditorCheck->isChecked() );
2889  GlobalSettings::self()->setExternalEditor( mEditorRequester->url() );
2890 }
2891 
2892 void ComposerPage::GeneralTab::slotConfigureRecentAddresses( )
2893 {
2894  TDERecentAddress::RecentAddressDialog dlg( this );
2895  dlg.setAddresses( RecentAddresses::self( KMKernel::config() )->addresses() );
2896  if ( dlg.exec() ) {
2897  RecentAddresses::self( KMKernel::config() )->clear();
2898  const TQStringList &addrList = dlg.addresses();
2899  TQStringList::ConstIterator it;
2900  for ( it = addrList.constBegin(); it != addrList.constEnd(); ++it )
2901  RecentAddresses::self( KMKernel::config() )->add( *it );
2902  }
2903 }
2904 
2905 void ComposerPage::GeneralTab::slotConfigureCompletionOrder( )
2906 {
2907  KPIM::LdapSearch search;
2908  KPIM::CompletionOrderEditor editor( &search, this );
2909  editor.exec();
2910 }
2911 
2912 TQString ComposerPage::PhrasesTab::helpAnchor() const {
2913  return TQString::fromLatin1("configure-composer-phrases");
2914 }
2915 
2916 ComposerPagePhrasesTab::ComposerPagePhrasesTab( TQWidget * parent, const char * name )
2917  : ConfigModuleTab( parent, name )
2918 {
2919  // tmp. vars:
2920  TQGridLayout *glay;
2921  TQPushButton *button;
2922 
2923  glay = new TQGridLayout( this, 7, 3, KDialog::spacingHint() );
2924  glay->setMargin( KDialog::marginHint() );
2925  glay->setColStretch( 1, 1 );
2926  glay->setColStretch( 2, 1 );
2927  glay->setRowStretch( 7, 1 );
2928 
2929  // row 0: help text
2930  glay->addMultiCellWidget( new TQLabel( i18n("<qt>The following placeholders are "
2931  "supported in the reply phrases:<br>"
2932  "<b>%D</b>: date, <b>%S</b>: subject,<br>"
2933  "<b>%e</b>: sender's address, <b>%F</b>: sender's name, <b>%f</b>: sender's initials,<br>"
2934  "<b>%T</b>: recipient's name, <b>%t</b>: recipient's name and address,<br>"
2935  "<b>%C</b>: carbon copy names, <b>%c</b>: carbon copy names and addresses,<br>"
2936  "<b>%%</b>: percent sign, <b>%_</b>: space, "
2937  "<b>%L</b>: linebreak</qt>"), this ),
2938  0, 0, 0, 2 ); // row 0; cols 0..2
2939 
2940  // row 1: label and language combo box:
2941  mPhraseLanguageCombo = new LanguageComboBox( false, this );
2942  glay->addWidget( new TQLabel( mPhraseLanguageCombo,
2943  i18n("Lang&uage:"), this ), 1, 0 );
2944  glay->addMultiCellWidget( mPhraseLanguageCombo, 1, 1, 1, 2 );
2945  connect( mPhraseLanguageCombo, TQ_SIGNAL(activated(const TQString&)),
2946  this, TQ_SLOT(slotLanguageChanged(const TQString&)) );
2947 
2948  // row 2: "add..." and "remove" push buttons:
2949  button = new TQPushButton( i18n("A&dd..."), this );
2950  button->setAutoDefault( false );
2951  glay->addWidget( button, 2, 1 );
2952  mRemoveButton = new TQPushButton( i18n("Re&move"), this );
2953  mRemoveButton->setAutoDefault( false );
2954  mRemoveButton->setEnabled( false ); // combo doesn't contain anything...
2955  glay->addWidget( mRemoveButton, 2, 2 );
2956  connect( button, TQ_SIGNAL(clicked()),
2957  this, TQ_SLOT(slotNewLanguage()) );
2958  connect( mRemoveButton, TQ_SIGNAL(clicked()),
2959  this, TQ_SLOT(slotRemoveLanguage()) );
2960 
2961  // row 3: "reply to sender" line edit and label:
2962  mPhraseReplyEdit = new KLineEdit( this );
2963  connect( mPhraseReplyEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
2964  this, TQ_SLOT( slotEmitChanged( void ) ) );
2965  glay->addWidget( new TQLabel( mPhraseReplyEdit,
2966  i18n("Reply to se&nder:"), this ), 3, 0 );
2967  glay->addMultiCellWidget( mPhraseReplyEdit, 3, 3, 1, 2 ); // cols 1..2
2968 
2969  // row 4: "reply to all" line edit and label:
2970  mPhraseReplyAllEdit = new KLineEdit( this );
2971  connect( mPhraseReplyAllEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
2972  this, TQ_SLOT( slotEmitChanged( void ) ) );
2973  glay->addWidget( new TQLabel( mPhraseReplyAllEdit,
2974  i18n("Repl&y to all:"), this ), 4, 0 );
2975  glay->addMultiCellWidget( mPhraseReplyAllEdit, 4, 4, 1, 2 ); // cols 1..2
2976 
2977  // row 5: "forward" line edit and label:
2978  mPhraseForwardEdit = new KLineEdit( this );
2979  connect( mPhraseForwardEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
2980  this, TQ_SLOT( slotEmitChanged( void ) ) );
2981  glay->addWidget( new TQLabel( mPhraseForwardEdit,
2982  i18n("&Forward:"), this ), 5, 0 );
2983  glay->addMultiCellWidget( mPhraseForwardEdit, 5, 5, 1, 2 ); // cols 1..2
2984 
2985  // row 6: "quote indicator" line edit and label:
2986  mPhraseIndentPrefixEdit = new KLineEdit( this );
2987  connect( mPhraseIndentPrefixEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
2988  this, TQ_SLOT( slotEmitChanged( void ) ) );
2989  glay->addWidget( new TQLabel( mPhraseIndentPrefixEdit,
2990  i18n("&Quote indicator:"), this ), 6, 0 );
2991  glay->addMultiCellWidget( mPhraseIndentPrefixEdit, 6, 6, 1, 2 );
2992 
2993  // row 7: spacer
2994 }
2995 
2996 
2997 void ComposerPage::PhrasesTab::setLanguageItemInformation( int index ) {
2998  assert( 0 <= index && index < (int)mLanguageList.count() );
2999 
3000  LanguageItem &l = *mLanguageList.at( index );
3001 
3002  mPhraseReplyEdit->setText( l.mReply );
3003  mPhraseReplyAllEdit->setText( l.mReplyAll );
3004  mPhraseForwardEdit->setText( l.mForward );
3005  mPhraseIndentPrefixEdit->setText( l.mIndentPrefix );
3006 }
3007 
3008 void ComposerPage::PhrasesTab::saveActiveLanguageItem() {
3009  int index = mActiveLanguageItem;
3010  if (index == -1) return;
3011  assert( 0 <= index && index < (int)mLanguageList.count() );
3012 
3013  LanguageItem &l = *mLanguageList.at( index );
3014 
3015  l.mReply = mPhraseReplyEdit->text();
3016  l.mReplyAll = mPhraseReplyAllEdit->text();
3017  l.mForward = mPhraseForwardEdit->text();
3018  l.mIndentPrefix = mPhraseIndentPrefixEdit->text();
3019 }
3020 
3021 void ComposerPage::PhrasesTab::slotNewLanguage()
3022 {
3023  NewLanguageDialog dialog( mLanguageList, parentWidget(), "New", true );
3024  if ( dialog.exec() == TQDialog::Accepted ) slotAddNewLanguage( dialog.language() );
3025 }
3026 
3027 void ComposerPage::PhrasesTab::slotAddNewLanguage( const TQString& lang )
3028 {
3029  mPhraseLanguageCombo->setCurrentItem(
3030  mPhraseLanguageCombo->insertLanguage( lang ) );
3031  TDELocale locale("kmail");
3032  locale.setLanguage( lang );
3033  mLanguageList.append(
3034  LanguageItem( lang,
3035  locale.translate("On %D, you wrote:"),
3036  locale.translate("On %D, %F wrote:"),
3037  locale.translate("Forwarded Message"),
3038  locale.translate(">%_") ) );
3039  mRemoveButton->setEnabled( true );
3040  slotLanguageChanged( TQString() );
3041 }
3042 
3043 void ComposerPage::PhrasesTab::slotRemoveLanguage()
3044 {
3045  assert( mPhraseLanguageCombo->count() > 1 );
3046  int index = mPhraseLanguageCombo->currentItem();
3047  assert( 0 <= index && index < (int)mLanguageList.count() );
3048 
3049  // remove current item from internal list and combobox:
3050  mLanguageList.remove( mLanguageList.at( index ) );
3051  mPhraseLanguageCombo->removeItem( index );
3052 
3053  if ( index >= (int)mLanguageList.count() ) index--;
3054 
3055  mActiveLanguageItem = index;
3056  setLanguageItemInformation( index );
3057  mRemoveButton->setEnabled( mLanguageList.count() > 1 );
3058  emit changed( true );
3059 }
3060 
3061 void ComposerPage::PhrasesTab::slotLanguageChanged( const TQString& )
3062 {
3063  int index = mPhraseLanguageCombo->currentItem();
3064  assert( index < (int)mLanguageList.count() );
3065  saveActiveLanguageItem();
3066  mActiveLanguageItem = index;
3067  setLanguageItemInformation( index );
3068  emit changed( true );
3069 }
3070 
3071 
3072 void ComposerPage::PhrasesTab::doLoadFromGlobalSettings() {
3073  mLanguageList.clear();
3074  mPhraseLanguageCombo->clear();
3075  mActiveLanguageItem = -1;
3076 
3077  int numLang = GlobalSettings::self()->replyLanguagesCount();
3078  int currentNr = GlobalSettings::self()->replyCurrentLanguage();
3079 
3080  // build mLanguageList and mPhraseLanguageCombo:
3081  for ( int i = 0 ; i < numLang ; i++ ) {
3082  ReplyPhrases replyPhrases( TQString::number(i) );
3083  replyPhrases.readConfig();
3084  TQString lang = replyPhrases.language();
3085  mLanguageList.append(
3086  LanguageItem( lang,
3087  replyPhrases.phraseReplySender(),
3088  replyPhrases.phraseReplyAll(),
3089  replyPhrases.phraseForward(),
3090  replyPhrases.indentPrefix() ) );
3091  mPhraseLanguageCombo->insertLanguage( lang );
3092  }
3093 
3094  if ( currentNr >= numLang || currentNr < 0 )
3095  currentNr = 0;
3096 
3097  if ( numLang == 0 ) {
3098  slotAddNewLanguage( TDEGlobal::locale()->language() );
3099  }
3100 
3101  mPhraseLanguageCombo->setCurrentItem( currentNr );
3102  mActiveLanguageItem = currentNr;
3103  setLanguageItemInformation( currentNr );
3104  mRemoveButton->setEnabled( mLanguageList.count() > 1 );
3105 }
3106 
3107 void ComposerPage::PhrasesTab::save() {
3108  GlobalSettings::self()->setReplyLanguagesCount( mLanguageList.count() );
3109  GlobalSettings::self()->setReplyCurrentLanguage( mPhraseLanguageCombo->currentItem() );
3110 
3111  saveActiveLanguageItem();
3112  LanguageItemList::Iterator it = mLanguageList.begin();
3113  for ( int i = 0 ; it != mLanguageList.end() ; ++it, ++i ) {
3114  ReplyPhrases replyPhrases( TQString::number(i) );
3115  replyPhrases.setLanguage( (*it).mLanguage );
3116  replyPhrases.setPhraseReplySender( (*it).mReply );
3117  replyPhrases.setPhraseReplyAll( (*it).mReplyAll );
3118  replyPhrases.setPhraseForward( (*it).mForward );
3119  replyPhrases.setIndentPrefix( (*it).mIndentPrefix );
3120  replyPhrases.writeConfig();
3121  }
3122 }
3123 
3124 TQString ComposerPage::TemplatesTab::helpAnchor() const {
3125  return TQString::fromLatin1("configure-composer-templates");
3126 }
3127 
3128 ComposerPageTemplatesTab::ComposerPageTemplatesTab( TQWidget * parent, const char * name )
3129  : ConfigModuleTab ( parent, name )
3130 {
3131  TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
3132 
3133  mWidget = new TemplatesConfiguration( this );
3134  vlay->addWidget( mWidget );
3135 
3136  connect( mWidget, TQ_SIGNAL( changed() ),
3137  this, TQ_SLOT( slotEmitChanged( void ) ) );
3138 }
3139 
3140 void ComposerPage::TemplatesTab::doLoadFromGlobalSettings() {
3141  mWidget->loadFromGlobal();
3142 }
3143 
3144 void ComposerPage::TemplatesTab::save() {
3145  mWidget->saveToGlobal();
3146 }
3147 
3148 TQString ComposerPage::CustomTemplatesTab::helpAnchor() const {
3149  return TQString::fromLatin1("configure-composer-custom-templates");
3150 }
3151 
3152 ComposerPageCustomTemplatesTab::ComposerPageCustomTemplatesTab( TQWidget * parent, const char * name )
3153  : ConfigModuleTab ( parent, name )
3154 {
3155  TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
3156 
3157  mWidget = new CustomTemplates( this );
3158  vlay->addWidget( mWidget );
3159 
3160  connect( mWidget, TQ_SIGNAL( changed() ),
3161  this, TQ_SLOT( slotEmitChanged( void ) ) );
3162 }
3163 
3164 void ComposerPage::CustomTemplatesTab::doLoadFromGlobalSettings() {
3165  mWidget->load();
3166 }
3167 
3168 void ComposerPage::CustomTemplatesTab::save() {
3169  mWidget->save();
3170 }
3171 
3172 TQString ComposerPage::SubjectTab::helpAnchor() const {
3173  return TQString::fromLatin1("configure-composer-subject");
3174 }
3175 
3176 ComposerPageSubjectTab::ComposerPageSubjectTab( TQWidget * parent, const char * name )
3177  : ConfigModuleTab( parent, name )
3178 {
3179  // tmp. vars:
3180  TQVBoxLayout *vlay;
3181  TQGroupBox *group;
3182  TQLabel *label;
3183 
3184 
3185  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
3186 
3187  group = new TQVGroupBox( i18n("Repl&y Subject Prefixes"), this );
3188  group->layout()->setSpacing( KDialog::spacingHint() );
3189 
3190  // row 0: help text:
3191  label = new TQLabel( i18n("Recognize any sequence of the following prefixes\n"
3192  "(entries are case-insensitive regular expressions):"), group );
3193  label->setAlignment( AlignLeft|WordBreak );
3194 
3195  // row 1, string list editor:
3196  SimpleStringListEditor::ButtonCode buttonCode =
3197  static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
3198  mReplyListEditor =
3199  new SimpleStringListEditor( group, 0, buttonCode,
3200  i18n("A&dd..."), i18n("Re&move"),
3201  i18n("Mod&ify..."),
3202  i18n("Enter new reply prefix:") );
3203  connect( mReplyListEditor, TQ_SIGNAL( changed( void ) ),
3204  this, TQ_SLOT( slotEmitChanged( void ) ) );
3205 
3206  // row 2: "replace [...]" check box:
3207  mReplaceReplyPrefixCheck = new TQCheckBox(
3208  GlobalSettings::self()->replaceReplyPrefixItem()->label(),
3209  group, "kcfg_ReplaceReplyPrefix" );
3210  connect( mReplaceReplyPrefixCheck, TQ_SIGNAL( stateChanged( int ) ),
3211  this, TQ_SLOT( slotEmitChanged( void ) ) );
3212 
3213  vlay->addWidget( group );
3214 
3215 
3216  group = new TQVGroupBox( i18n("For&ward Subject Prefixes"), this );
3217  group->layout()->setSpacing( KDialog::marginHint() );
3218 
3219  // row 0: help text:
3220  label= new TQLabel( i18n("Recognize any sequence of the following prefixes\n"
3221  "(entries are case-insensitive regular expressions):"), group );
3222  label->setAlignment( AlignLeft|WordBreak );
3223 
3224  // row 1: string list editor
3225  mForwardListEditor =
3226  new SimpleStringListEditor( group, 0, buttonCode,
3227  i18n("Add..."),
3228  i18n("Remo&ve"),
3229  i18n("Modify..."),
3230  i18n("Enter new forward prefix:") );
3231  connect( mForwardListEditor, TQ_SIGNAL( changed( void ) ),
3232  this, TQ_SLOT( slotEmitChanged( void ) ) );
3233 
3234  // row 3: "replace [...]" check box:
3235  mReplaceForwardPrefixCheck = new TQCheckBox(
3236  GlobalSettings::self()->replaceForwardPrefixItem()->label(),
3237  group, "kcfg_ReplaceForwardPrefix" );
3238  connect( mReplaceForwardPrefixCheck, TQ_SIGNAL( stateChanged( int ) ),
3239  this, TQ_SLOT( slotEmitChanged( void ) ) );
3240 
3241  vlay->addWidget( group );
3242 }
3243 
3244 void ComposerPage::SubjectTab::doLoadFromGlobalSettings() {
3245  mReplyListEditor->setStringList( GlobalSettings::self()->replyPrefixes() );
3246  mReplaceReplyPrefixCheck->setChecked( GlobalSettings::self()->replaceReplyPrefix() );
3247  mForwardListEditor->setStringList( GlobalSettings::self()->forwardPrefixes() );
3248  mReplaceForwardPrefixCheck->setChecked( GlobalSettings::self()->replaceForwardPrefix() );
3249 }
3250 
3251 void ComposerPage::SubjectTab::save() {
3252  GlobalSettings::self()->setReplyPrefixes( mReplyListEditor->stringList() );
3253  GlobalSettings::self()->setForwardPrefixes( mForwardListEditor->stringList() );
3254 }
3255 
3256 TQString ComposerPage::CharsetTab::helpAnchor() const {
3257  return TQString::fromLatin1("configure-composer-charset");
3258 }
3259 
3260 ComposerPageCharsetTab::ComposerPageCharsetTab( TQWidget * parent, const char * name )
3261  : ConfigModuleTab( parent, name )
3262 {
3263  // tmp. vars:
3264  TQVBoxLayout *vlay;
3265  TQLabel *label;
3266 
3267  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
3268 
3269  label = new TQLabel( i18n("This list is checked for every outgoing message "
3270  "from the top to the bottom for a charset that "
3271  "contains all required characters."), this );
3272  label->setAlignment( WordBreak);
3273  vlay->addWidget( label );
3274 
3275  mCharsetListEditor =
3276  new SimpleStringListEditor( this, 0, SimpleStringListEditor::All,
3277  i18n("A&dd..."), i18n("Remo&ve"),
3278  i18n("&Modify..."), i18n("Enter charset:") );
3279  connect( mCharsetListEditor, TQ_SIGNAL( changed( void ) ),
3280  this, TQ_SLOT( slotEmitChanged( void ) ) );
3281 
3282  vlay->addWidget( mCharsetListEditor, 1 );
3283 
3284  mKeepReplyCharsetCheck = new TQCheckBox( i18n("&Keep original charset when "
3285  "replying or forwarding (if "
3286  "possible)"), this );
3287  connect( mKeepReplyCharsetCheck, TQ_SIGNAL ( stateChanged( int ) ),
3288  this, TQ_SLOT( slotEmitChanged( void ) ) );
3289  vlay->addWidget( mKeepReplyCharsetCheck );
3290 
3291  connect( mCharsetListEditor, TQ_SIGNAL(aboutToAdd(TQString&)),
3292  this, TQ_SLOT(slotVerifyCharset(TQString&)) );
3293 }
3294 
3295 void ComposerPage::CharsetTab::slotVerifyCharset( TQString & charset ) {
3296  if ( charset.isEmpty() ) return;
3297 
3298  // KCharsets::codecForName("us-ascii") returns "iso-8859-1" (cf. Bug #49812)
3299  // therefore we have to treat this case specially
3300  if ( charset.lower() == TQString::fromLatin1("us-ascii") ) {
3301  charset = TQString::fromLatin1("us-ascii");
3302  return;
3303  }
3304 
3305  if ( charset.lower() == TQString::fromLatin1("locale") ) {
3306  charset = TQString::fromLatin1("%1 (locale)")
3307  .arg( TQString( kmkernel->networkCodec()->mimeName() ).lower() );
3308  return;
3309  }
3310 
3311  bool ok = false;
3312  TQTextCodec *codec = TDEGlobal::charsets()->codecForName( charset, ok );
3313  if ( ok && codec ) {
3314  charset = TQString::fromLatin1( codec->mimeName() ).lower();
3315  return;
3316  }
3317 
3318  KMessageBox::sorry( this, i18n("This charset is not supported.") );
3319  charset = TQString();
3320 }
3321 
3322 void ComposerPage::CharsetTab::doLoadOther() {
3323  TDEConfigGroup composer( KMKernel::config(), "Composer" );
3324 
3325  TQStringList charsets = composer.readListEntry( "pref-charsets" );
3326  for ( TQStringList::Iterator it = charsets.begin() ;
3327  it != charsets.end() ; ++it )
3328  if ( (*it) == TQString::fromLatin1("locale") ) {
3329  TQCString cset = kmkernel->networkCodec()->mimeName();
3330  kasciitolower( cset.data() );
3331  (*it) = TQString("%1 (locale)").arg( TQString(cset) );
3332  }
3333 
3334  mCharsetListEditor->setStringList( charsets );
3335  mKeepReplyCharsetCheck->setChecked( !composer.readBoolEntry( "force-reply-charset", false ) );
3336 }
3337 
3338 void ComposerPage::CharsetTab::save() {
3339  TDEConfigGroup composer( KMKernel::config(), "Composer" );
3340 
3341  TQStringList charsetList = mCharsetListEditor->stringList();
3342  TQStringList::Iterator it = charsetList.begin();
3343  for ( ; it != charsetList.end() ; ++it )
3344  if ( (*it).endsWith("(locale)") )
3345  (*it) = "locale";
3346  composer.writeEntry( "pref-charsets", charsetList );
3347  composer.writeEntry( "force-reply-charset",
3348  !mKeepReplyCharsetCheck->isChecked() );
3349 }
3350 
3351 TQString ComposerPage::HeadersTab::helpAnchor() const {
3352  return TQString::fromLatin1("configure-composer-headers");
3353 }
3354 
3355 ComposerPageHeadersTab::ComposerPageHeadersTab( TQWidget * parent, const char * name )
3356  : ConfigModuleTab( parent, name )
3357 {
3358  // tmp. vars:
3359  TQVBoxLayout *vlay;
3360  TQHBoxLayout *hlay;
3361  TQGridLayout *glay;
3362  TQLabel *label;
3363  TQPushButton *button;
3364 
3365  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
3366 
3367  // "Use custom Message-Id suffix" checkbox:
3368  mCreateOwnMessageIdCheck =
3369  new TQCheckBox( i18n("&Use custom message-id suffix"), this );
3370  connect( mCreateOwnMessageIdCheck, TQ_SIGNAL ( stateChanged( int ) ),
3371  this, TQ_SLOT( slotEmitChanged( void ) ) );
3372  vlay->addWidget( mCreateOwnMessageIdCheck );
3373 
3374  // "Message-Id suffix" line edit and label:
3375  hlay = new TQHBoxLayout( vlay ); // inherits spacing
3376  mMessageIdSuffixEdit = new KLineEdit( this );
3377  // only ASCII letters, digits, plus, minus and dots are allowed
3378  mMessageIdSuffixValidator =
3379  new TQRegExpValidator( TQRegExp( "[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*" ), this );
3380  mMessageIdSuffixEdit->setValidator( mMessageIdSuffixValidator );
3381  label = new TQLabel( mMessageIdSuffixEdit,
3382  i18n("Custom message-&id suffix:"), this );
3383  label->setEnabled( false ); // since !mCreateOwnMessageIdCheck->isChecked()
3384  mMessageIdSuffixEdit->setEnabled( false );
3385  hlay->addWidget( label );
3386  hlay->addWidget( mMessageIdSuffixEdit, 1 );
3387  connect( mCreateOwnMessageIdCheck, TQ_SIGNAL(toggled(bool) ),
3388  label, TQ_SLOT(setEnabled(bool)) );
3389  connect( mCreateOwnMessageIdCheck, TQ_SIGNAL(toggled(bool) ),
3390  mMessageIdSuffixEdit, TQ_SLOT(setEnabled(bool)) );
3391  connect( mMessageIdSuffixEdit, TQ_SIGNAL( textChanged( const TQString& ) ),
3392  this, TQ_SLOT( slotEmitChanged( void ) ) );
3393 
3394  // horizontal rule and "custom header fields" label:
3395  vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
3396  vlay->addWidget( new TQLabel( i18n("Define custom mime header fields:"), this) );
3397 
3398  // "custom header fields" listbox:
3399  glay = new TQGridLayout( vlay, 5, 3 ); // inherits spacing
3400  glay->setRowStretch( 2, 1 );
3401  glay->setColStretch( 1, 1 );
3402  mTagList = new ListView( this, "tagList" );
3403  mTagList->addColumn( i18n("Name") );
3404  mTagList->addColumn( i18n("Value") );
3405  mTagList->setAllColumnsShowFocus( true );
3406  mTagList->setSorting( -1 );
3407  connect( mTagList, TQ_SIGNAL(selectionChanged()),
3408  this, TQ_SLOT(slotMimeHeaderSelectionChanged()) );
3409  glay->addMultiCellWidget( mTagList, 0, 2, 0, 1 );
3410 
3411  // "new" and "remove" buttons:
3412  button = new TQPushButton( i18n("Ne&w"), this );
3413  connect( button, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotNewMimeHeader()) );
3414  button->setAutoDefault( false );
3415  glay->addWidget( button, 0, 2 );
3416  mRemoveHeaderButton = new TQPushButton( i18n("Re&move"), this );
3417  connect( mRemoveHeaderButton, TQ_SIGNAL(clicked()),
3418  this, TQ_SLOT(slotRemoveMimeHeader()) );
3419  button->setAutoDefault( false );
3420  glay->addWidget( mRemoveHeaderButton, 1, 2 );
3421 
3422  // "name" and "value" line edits and labels:
3423  mTagNameEdit = new KLineEdit( this );
3424  mTagNameEdit->setEnabled( false );
3425  mTagNameLabel = new TQLabel( mTagNameEdit, i18n("&Name:"), this );
3426  mTagNameLabel->setEnabled( false );
3427  glay->addWidget( mTagNameLabel, 3, 0 );
3428  glay->addWidget( mTagNameEdit, 3, 1 );
3429  connect( mTagNameEdit, TQ_SIGNAL(textChanged(const TQString&)),
3430  this, TQ_SLOT(slotMimeHeaderNameChanged(const TQString&)) );
3431 
3432  mTagValueEdit = new KLineEdit( this );
3433  mTagValueEdit->setEnabled( false );
3434  mTagValueLabel = new TQLabel( mTagValueEdit, i18n("&Value:"), this );
3435  mTagValueLabel->setEnabled( false );
3436  glay->addWidget( mTagValueLabel, 4, 0 );
3437  glay->addWidget( mTagValueEdit, 4, 1 );
3438  connect( mTagValueEdit, TQ_SIGNAL(textChanged(const TQString&)),
3439  this, TQ_SLOT(slotMimeHeaderValueChanged(const TQString&)) );
3440 }
3441 
3442 void ComposerPage::HeadersTab::slotMimeHeaderSelectionChanged()
3443 {
3444  TQListViewItem * item = mTagList->selectedItem();
3445 
3446  if ( item ) {
3447  mTagNameEdit->setText( item->text( 0 ) );
3448  mTagValueEdit->setText( item->text( 1 ) );
3449  } else {
3450  mTagNameEdit->clear();
3451  mTagValueEdit->clear();
3452  }
3453  mRemoveHeaderButton->setEnabled( item );
3454  mTagNameEdit->setEnabled( item );
3455  mTagValueEdit->setEnabled( item );
3456  mTagNameLabel->setEnabled( item );
3457  mTagValueLabel->setEnabled( item );
3458 }
3459 
3460 
3461 void ComposerPage::HeadersTab::slotMimeHeaderNameChanged( const TQString & text ) {
3462  // is called on ::setup(), when clearing the line edits. So be
3463  // prepared to not find a selection:
3464  TQListViewItem * item = mTagList->selectedItem();
3465  if ( item )
3466  item->setText( 0, text );
3467  emit changed( true );
3468 }
3469 
3470 
3471 void ComposerPage::HeadersTab::slotMimeHeaderValueChanged( const TQString & text ) {
3472  // is called on ::setup(), when clearing the line edits. So be
3473  // prepared to not find a selection:
3474  TQListViewItem * item = mTagList->selectedItem();
3475  if ( item )
3476  item->setText( 1, text );
3477  emit changed( true );
3478 }
3479 
3480 
3481 void ComposerPage::HeadersTab::slotNewMimeHeader()
3482 {
3483  TQListViewItem *listItem = new TQListViewItem( mTagList );
3484  mTagList->setCurrentItem( listItem );
3485  mTagList->setSelected( listItem, true );
3486  emit changed( true );
3487 }
3488 
3489 
3490 void ComposerPage::HeadersTab::slotRemoveMimeHeader()
3491 {
3492  // calling this w/o selection is a programming error:
3493  TQListViewItem * item = mTagList->selectedItem();
3494  if ( !item ) {
3495  kdDebug(5006) << "==================================================\n"
3496  << "Error: Remove button was pressed although no custom header was selected\n"
3497  << "==================================================\n";
3498  return;
3499  }
3500 
3501  TQListViewItem * below = item->nextSibling();
3502  delete item;
3503 
3504  if ( below )
3505  mTagList->setSelected( below, true );
3506  else if ( mTagList->lastItem() )
3507  mTagList->setSelected( mTagList->lastItem(), true );
3508  emit changed( true );
3509 }
3510 
3511 void ComposerPage::HeadersTab::doLoadOther() {
3512  TDEConfigGroup general( KMKernel::config(), "General" );
3513 
3514  TQString suffix = general.readEntry( "myMessageIdSuffix" );
3515  mMessageIdSuffixEdit->setText( suffix );
3516  bool state = ( !suffix.isEmpty() &&
3517  general.readBoolEntry( "useCustomMessageIdSuffix", false ) );
3518  mCreateOwnMessageIdCheck->setChecked( state );
3519 
3520  mTagList->clear();
3521  mTagNameEdit->clear();
3522  mTagValueEdit->clear();
3523 
3524  TQListViewItem * item = 0;
3525 
3526  int count = general.readNumEntry( "mime-header-count", 0 );
3527  for( int i = 0 ; i < count ; i++ ) {
3528  TDEConfigGroup config( KMKernel::config(),
3529  TQCString("Mime #") + TQCString().setNum(i) );
3530  TQString name = config.readEntry( "name" );
3531  TQString value = config.readEntry( "value" );
3532  if( !name.isEmpty() )
3533  item = new TQListViewItem( mTagList, item, name, value );
3534  }
3535  if ( mTagList->childCount() ) {
3536  mTagList->setCurrentItem( mTagList->firstChild() );
3537  mTagList->setSelected( mTagList->firstChild(), true );
3538  }
3539  else {
3540  // disable the "Remove" button
3541  mRemoveHeaderButton->setEnabled( false );
3542  }
3543 }
3544 
3545 void ComposerPage::HeadersTab::save() {
3546  TDEConfigGroup general( KMKernel::config(), "General" );
3547 
3548  general.writeEntry( "useCustomMessageIdSuffix",
3549  mCreateOwnMessageIdCheck->isChecked() );
3550  general.writeEntry( "myMessageIdSuffix",
3551  mMessageIdSuffixEdit->text() );
3552 
3553  int numValidEntries = 0;
3554  TQListViewItem * item = mTagList->firstChild();
3555  for ( ; item ; item = item->itemBelow() )
3556  if( !item->text(0).isEmpty() ) {
3557  TDEConfigGroup config( KMKernel::config(), TQCString("Mime #")
3558  + TQCString().setNum( numValidEntries ) );
3559  config.writeEntry( "name", item->text( 0 ) );
3560  config.writeEntry( "value", item->text( 1 ) );
3561  numValidEntries++;
3562  }
3563  general.writeEntry( "mime-header-count", numValidEntries );
3564 }
3565 
3566 TQString ComposerPage::AttachmentsTab::helpAnchor() const {
3567  return TQString::fromLatin1("configure-composer-attachments");
3568 }
3569 
3570 ComposerPageAttachmentsTab::ComposerPageAttachmentsTab( TQWidget * parent,
3571  const char * name )
3572  : ConfigModuleTab( parent, name ) {
3573  // tmp. vars:
3574  TQVBoxLayout *vlay;
3575  TQLabel *label;
3576 
3577  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
3578 
3579  // "Outlook compatible attachment naming" check box
3580  mOutlookCompatibleCheck =
3581  new TQCheckBox( i18n( "Outlook-compatible attachment naming" ), this );
3582  mOutlookCompatibleCheck->setChecked( false );
3583  TQToolTip::add( mOutlookCompatibleCheck, i18n(
3584  "Turn this option on to make Outlook(tm) understand attachment names "
3585  "containing non-English characters" ) );
3586  connect( mOutlookCompatibleCheck, TQ_SIGNAL( stateChanged( int ) ),
3587  this, TQ_SLOT( slotEmitChanged( void ) ) );
3588  connect( mOutlookCompatibleCheck, TQ_SIGNAL( clicked() ),
3589  this, TQ_SLOT( slotOutlookCompatibleClicked() ) );
3590  vlay->addWidget( mOutlookCompatibleCheck );
3591  vlay->addSpacing( 5 );
3592 
3593  // "Enable detection of missing attachments" check box
3594  mMissingAttachmentDetectionCheck =
3595  new TQCheckBox( i18n("E&nable detection of missing attachments"), this );
3596  mMissingAttachmentDetectionCheck->setChecked( true );
3597  connect( mMissingAttachmentDetectionCheck, TQ_SIGNAL( stateChanged( int ) ),
3598  this, TQ_SLOT( slotEmitChanged( void ) ) );
3599  vlay->addWidget( mMissingAttachmentDetectionCheck );
3600 
3601  // "Attachment key words" label and string list editor
3602  label = new TQLabel( i18n("Recognize any of the following key words as "
3603  "intention to attach a file:"), this );
3604  label->setAlignment( AlignLeft|WordBreak );
3605  vlay->addWidget( label );
3606 
3607  SimpleStringListEditor::ButtonCode buttonCode =
3608  static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
3609  mAttachWordsListEditor =
3610  new SimpleStringListEditor( this, 0, buttonCode,
3611  i18n("A&dd..."), i18n("Re&move"),
3612  i18n("Mod&ify..."),
3613  i18n("Enter new key word:") );
3614  connect( mAttachWordsListEditor, TQ_SIGNAL( changed( void ) ),
3615  this, TQ_SLOT( slotEmitChanged( void ) ) );
3616  vlay->addWidget( mAttachWordsListEditor );
3617 
3618  connect( mMissingAttachmentDetectionCheck, TQ_SIGNAL(toggled(bool) ),
3619  label, TQ_SLOT(setEnabled(bool)) );
3620  connect( mMissingAttachmentDetectionCheck, TQ_SIGNAL(toggled(bool) ),
3621  mAttachWordsListEditor, TQ_SLOT(setEnabled(bool)) );
3622 }
3623 
3624 void ComposerPage::AttachmentsTab::doLoadFromGlobalSettings() {
3625  mOutlookCompatibleCheck->setChecked(
3626  GlobalSettings::self()->outlookCompatibleAttachments() );
3627  mMissingAttachmentDetectionCheck->setChecked(
3628  GlobalSettings::self()->showForgottenAttachmentWarning() );
3629  TQStringList attachWordsList = GlobalSettings::self()->attachmentKeywords();
3630  if ( attachWordsList.isEmpty() ) {
3631  // default value
3632  attachWordsList << TQString::fromLatin1("attachment")
3633  << TQString::fromLatin1("attached");
3634  if ( TQString::fromLatin1("attachment") != i18n("attachment") )
3635  attachWordsList << i18n("attachment");
3636  if ( TQString::fromLatin1("attached") != i18n("attached") )
3637  attachWordsList << i18n("attached");
3638  }
3639 
3640  mAttachWordsListEditor->setStringList( attachWordsList );
3641 }
3642 
3643 void ComposerPage::AttachmentsTab::save() {
3644  GlobalSettings::self()->setOutlookCompatibleAttachments(
3645  mOutlookCompatibleCheck->isChecked() );
3646  GlobalSettings::self()->setShowForgottenAttachmentWarning(
3647  mMissingAttachmentDetectionCheck->isChecked() );
3648  GlobalSettings::self()->setAttachmentKeywords(
3649  mAttachWordsListEditor->stringList() );
3650 }
3651 
3652 void ComposerPageAttachmentsTab::slotOutlookCompatibleClicked()
3653 {
3654  if (mOutlookCompatibleCheck->isChecked()) {
3655  KMessageBox::information(0,i18n("You have chosen to "
3656  "encode attachment names containing non-English characters in a way that "
3657  "is understood by Outlook(tm) and other mail clients that do not "
3658  "support standard-compliant encoded attachment names.\n"
3659  "Note that KMail may create non-standard compliant messages, "
3660  "and consequently it is possible that your messages will not be "
3661  "understood by standard-compliant mail clients; so, unless you have no "
3662  "other choice, you should not enable this option." ) );
3663  }
3664 }
3665 
3666 // *************************************************************
3667 // * *
3668 // * SecurityPage *
3669 // * *
3670 // *************************************************************
3671 TQString SecurityPage::helpAnchor() const {
3672  return TQString::fromLatin1("configure-security");
3673 }
3674 
3675 SecurityPage::SecurityPage( TQWidget * parent, const char * name )
3676  : ConfigModuleWithTabs( parent, name )
3677 {
3678  //
3679  // "Reading" tab:
3680  //
3681  mGeneralTab = new GeneralTab(); // @TODO: rename
3682  addTab( mGeneralTab, i18n("&Reading") );
3683 
3684  //
3685  // "Composing" tab:
3686  //
3687  mComposerCryptoTab = new ComposerCryptoTab();
3688  addTab( mComposerCryptoTab, i18n("Composing") );
3689 
3690  //
3691  // "Warnings" tab:
3692  //
3693  mWarningTab = new WarningTab();
3694  addTab( mWarningTab, i18n("Warnings") );
3695 
3696  //
3697  // "S/MIME Validation" tab:
3698  //
3699  mSMimeTab = new SMimeTab();
3700  addTab( mSMimeTab, i18n("S/MIME &Validation") );
3701 
3702  //
3703  // "Crypto Backends" tab:
3704  //
3705  mCryptPlugTab = new CryptPlugTab();
3706  addTab( mCryptPlugTab, i18n("Crypto Backe&nds") );
3707  load();
3708 }
3709 
3710 
3711 void SecurityPage::installProfile( TDEConfig * profile ) {
3712  mGeneralTab->installProfile( profile );
3713  mComposerCryptoTab->installProfile( profile );
3714  mWarningTab->installProfile( profile );
3715  mSMimeTab->installProfile( profile );
3716 }
3717 
3718 TQString SecurityPage::GeneralTab::helpAnchor() const {
3719  return TQString::fromLatin1("configure-security-reading");
3720 }
3721 
3722 SecurityPageGeneralTab::SecurityPageGeneralTab( TQWidget * parent, const char * name )
3723  : ConfigModuleTab ( parent, name )
3724 {
3725  // tmp. vars:
3726  TQVBoxLayout *vlay;
3727  TQHBox *hbox;
3728  TQGroupBox *group;
3729  TQRadioButton *radio;
3730  KActiveLabel *label;
3731  TQWidget *w;
3732  TQString msg;
3733 
3734  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
3735 
3736  // TQWhat'sThis texts
3737  TQString htmlWhatsThis = i18n( "<qt><p>Messages sometimes come in both formats. "
3738  "This option controls whether you want the HTML part or the plain "
3739  "text part to be displayed.</p>"
3740  "<p>Displaying the HTML part makes the message look better, "
3741  "but at the same time increases the risk of security holes "
3742  "being exploited.</p>"
3743  "<p>Displaying the plain text part loses much of the message's "
3744  "formatting, but makes it almost <em>impossible</em> "
3745  "to exploit security holes in the HTML renderer (Konqueror).</p>"
3746  "<p>The option below guards against one common misuse of HTML "
3747  "messages, but it cannot guard against security issues that were "
3748  "not known at the time this version of KMail was written.</p>"
3749  "<p>It is therefore advisable to <em>not</em> prefer HTML to "
3750  "plain text.</p>"
3751  "<p><b>Note:</b> You can set this option on a per-folder basis "
3752  "from the <i>Folder</i> menu of KMail's main window.</p></qt>" );
3753 
3754  TQString externalWhatsThis = i18n( "<qt><p>Some mail advertisements are in HTML "
3755  "and contain references to, for example, images that the advertisers"
3756  " employ to find out that you have read their message "
3757  "(&quot;web bugs&quot;).</p>"
3758  "<p>There is no valid reason to load images off the Internet like "
3759  "this, since the sender can always attach the required images "
3760  "directly to the message.</p>"
3761  "<p>To guard from such a misuse of the HTML displaying feature "
3762  "of KMail, this option is <em>disabled</em> by default.</p>"
3763  "<p>However, if you wish to, for example, view images in HTML "
3764  "messages that were not attached to it, you can enable this "
3765  "option, but you should be aware of the possible problem.</p></qt>" );
3766 
3767  TQString receiptWhatsThis = i18n( "<qt><h3>Message Disposition "
3768  "Notification Policy</h3>"
3769  "<p>MDNs are a generalization of what is commonly called <b>read "
3770  "receipt</b>. The message author requests a disposition "
3771  "notification to be sent and the receiver's mail program "
3772  "generates a reply from which the author can learn what "
3773  "happened to their message. Common disposition types include "
3774  "<b>displayed</b> (i.e. read), <b>deleted</b> and <b>dispatched</b> "
3775  "(e.g. forwarded).</p>"
3776  "<p>The following options are available to control KMail's "
3777  "sending of MDNs:</p>"
3778  "<ul>"
3779  "<li><em>Ignore</em>: Ignores any request for disposition "
3780  "notifications. No MDN will ever be sent automatically "
3781  "(recommended).</li>"
3782  "<li><em>Ask</em>: Answers requests only after asking the user "
3783  "for permission. This way, you can send MDNs for selected "
3784  "messages while denying or ignoring them for others.</li>"
3785  "<li><em>Deny</em>: Always sends a <b>denied</b> notification. This "
3786  "is only <em>slightly</em> better than always sending MDNs. "
3787  "The author will still know that the messages has been acted "
3788  "upon, they just cannot tell whether it was deleted or read etc.</li>"
3789  "<li><em>Always send</em>: Always sends the requested "
3790  "disposition notification. That means that the author of the "
3791  "message gets to know when the message was acted upon and, "
3792  "in addition, what happened to it (displayed, deleted, "
3793  "etc.). This option is strongly discouraged, but since it "
3794  "makes much sense e.g. for customer relationship management, "
3795  "it has been made available.</li>"
3796  "</ul></qt>" );
3797 
3798 
3799  // "HTML Messages" group box:
3800  group = new TQVGroupBox( i18n( "HTML Messages" ), this );
3801  group->layout()->setSpacing( KDialog::spacingHint() );
3802 
3803  mHtmlMailCheck = new TQCheckBox( i18n("Prefer H&TML to plain text"), group );
3804  TQWhatsThis::add( mHtmlMailCheck, htmlWhatsThis );
3805  connect( mHtmlMailCheck, TQ_SIGNAL( stateChanged( int ) ),
3806  this, TQ_SLOT( slotEmitChanged( void ) ) );
3807  mExternalReferences = new TQCheckBox( i18n("Allow messages to load e&xternal "
3808  "references from the Internet" ), group );
3809  TQWhatsThis::add( mExternalReferences, externalWhatsThis );
3810  connect( mExternalReferences, TQ_SIGNAL( stateChanged( int ) ),
3811  this, TQ_SLOT( slotEmitChanged( void ) ) );
3812  label = new KActiveLabel( i18n("<b>WARNING:</b> Allowing HTML in email may "
3813  "increase the risk that your system will be "
3814  "compromised by present and anticipated security "
3815  "exploits. <a href=\"whatsthis:%1\">More about "
3816  "HTML mails...</a> <a href=\"whatsthis:%2\">More "
3817  "about external references...</a>")
3818  .arg(htmlWhatsThis).arg(externalWhatsThis),
3819  group );
3820 
3821  vlay->addWidget( group );
3822 
3823  // encrypted messages group
3824  group = new TQVGroupBox( i18n("Encrypted Messages"), this );
3825  group->layout()->setSpacing( KDialog::spacingHint() );
3826  mAlwaysDecrypt = new TQCheckBox( i18n( "Attempt decryption of encrypted messages when viewing" ), group );
3827  connect( mAlwaysDecrypt, TQ_SIGNAL(stateChanged(int)), this, TQ_SLOT(slotEmitChanged()) );
3828  vlay->addWidget( group );
3829 
3830  // "Message Disposition Notification" groupbox:
3831  group = new TQVGroupBox( i18n("Message Disposition Notifications"), this );
3832  group->layout()->setSpacing( KDialog::spacingHint() );
3833 
3834 
3835  // "ignore", "ask", "deny", "always send" radiobutton line:
3836  mMDNGroup = new TQButtonGroup( group );
3837  mMDNGroup->hide();
3838  connect( mMDNGroup, TQ_SIGNAL( clicked( int ) ),
3839  this, TQ_SLOT( slotEmitChanged( void ) ) );
3840  hbox = new TQHBox( group );
3841  hbox->setSpacing( KDialog::spacingHint() );
3842 
3843  (void)new TQLabel( i18n("Send policy:"), hbox );
3844 
3845  radio = new TQRadioButton( i18n("&Ignore"), hbox );
3846  mMDNGroup->insert( radio );
3847 
3848  radio = new TQRadioButton( i18n("As&k"), hbox );
3849  mMDNGroup->insert( radio );
3850 
3851  radio = new TQRadioButton( i18n("&Deny"), hbox );
3852  mMDNGroup->insert( radio );
3853 
3854  radio = new TQRadioButton( i18n("Al&ways send"), hbox );
3855  mMDNGroup->insert( radio );
3856 
3857  for ( int i = 0 ; i < mMDNGroup->count() ; ++i )
3858  TQWhatsThis::add( mMDNGroup->find( i ), receiptWhatsThis );
3859 
3860  w = new TQWidget( hbox ); // spacer
3861  hbox->setStretchFactor( w, 1 );
3862 
3863  // "Original Message quote" radiobutton line:
3864  mOrigQuoteGroup = new TQButtonGroup( group );
3865  mOrigQuoteGroup->hide();
3866  connect( mOrigQuoteGroup, TQ_SIGNAL( clicked( int ) ),
3867  this, TQ_SLOT( slotEmitChanged( void ) ) );
3868 
3869  hbox = new TQHBox( group );
3870  hbox->setSpacing( KDialog::spacingHint() );
3871 
3872  (void)new TQLabel( i18n("Quote original message:"), hbox );
3873 
3874  radio = new TQRadioButton( i18n("Nothin&g"), hbox );
3875  mOrigQuoteGroup->insert( radio );
3876 
3877  radio = new TQRadioButton( i18n("&Full message"), hbox );
3878  mOrigQuoteGroup->insert( radio );
3879 
3880  radio = new TQRadioButton( i18n("Onl&y headers"), hbox );
3881  mOrigQuoteGroup->insert( radio );
3882 
3883  w = new TQWidget( hbox );
3884  hbox->setStretchFactor( w, 1 );
3885 
3886  mNoMDNsWhenEncryptedCheck = new TQCheckBox( i18n("Do not send MDNs in response to encrypted messages"), group );
3887  connect( mNoMDNsWhenEncryptedCheck, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
3888 
3889  // Warning label:
3890  label = new KActiveLabel( i18n("<b>WARNING:</b> Unconditionally returning "
3891  "confirmations undermines your privacy. "
3892  "<a href=\"whatsthis:%1\">More...</a>")
3893  .arg(receiptWhatsThis),
3894  group );
3895 
3896  vlay->addWidget( group );
3897 
3898  // "Attached keys" group box:
3899  group = new TQVGroupBox( i18n( "Certificate && Key Bundle Attachments" ), this );
3900  group->layout()->setSpacing( KDialog::spacingHint() );
3901 
3902  mAutomaticallyImportAttachedKeysCheck = new TQCheckBox( i18n("Automatically import keys and certificates"), group );
3903  connect( mAutomaticallyImportAttachedKeysCheck, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
3904 
3905  vlay->addWidget( group );
3906 
3907 
3908 
3909  vlay->addStretch( 10 ); // spacer
3910 }
3911 
3912 void SecurityPage::GeneralTab::doLoadOther() {
3913  const TDEConfigGroup reader( KMKernel::config(), "Reader" );
3914 
3915  mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail", false ) );
3916  mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal", false ) );
3917  mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys", false ) );
3918 
3919  mAlwaysDecrypt->setChecked( GlobalSettings::self()->alwaysDecrypt() );
3920 
3921  const TDEConfigGroup mdn( KMKernel::config(), "MDN" );
3922 
3923  int num = mdn.readNumEntry( "default-policy", 0 );
3924  if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
3925  mMDNGroup->setButton( num );
3926  num = mdn.readNumEntry( "quote-message", 0 );
3927  if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
3928  mOrigQuoteGroup->setButton( num );
3929  mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted", true ));
3930 }
3931 
3932 void SecurityPage::GeneralTab::installProfile( TDEConfig * profile ) {
3933  const TDEConfigGroup reader( profile, "Reader" );
3934  const TDEConfigGroup mdn( profile, "MDN" );
3935 
3936  if ( reader.hasKey( "htmlMail" ) )
3937  mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail" ) );
3938  if ( reader.hasKey( "htmlLoadExternal" ) )
3939  mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal" ) );
3940  if ( reader.hasKey( "AutoImportKeys" ) )
3941  mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys" ) );
3942 
3943  if ( mdn.hasKey( "default-policy" ) ) {
3944  int num = mdn.readNumEntry( "default-policy" );
3945  if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
3946  mMDNGroup->setButton( num );
3947  }
3948  if ( mdn.hasKey( "quote-message" ) ) {
3949  int num = mdn.readNumEntry( "quote-message" );
3950  if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
3951  mOrigQuoteGroup->setButton( num );
3952  }
3953  if ( mdn.hasKey( "not-send-when-encrypted" ) )
3954  mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted" ));
3955 }
3956 
3957 void SecurityPage::GeneralTab::save() {
3958  TDEConfigGroup reader( KMKernel::config(), "Reader" );
3959  TDEConfigGroup mdn( KMKernel::config(), "MDN" );
3960 
3961  if (reader.readBoolEntry( "htmlMail", false ) != mHtmlMailCheck->isChecked())
3962  {
3963  if (KMessageBox::warningContinueCancel(this, i18n("Changing the global "
3964  "HTML setting will override all folder specific values."), TQString(),
3965  KStdGuiItem::cont(), "htmlMailOverride") == KMessageBox::Continue)
3966  {
3967  reader.writeEntry( "htmlMail", mHtmlMailCheck->isChecked() );
3968  TQStringList names;
3969  TQValueList<TQGuardedPtr<KMFolder> > folders;
3970  kmkernel->folderMgr()->createFolderList(&names, &folders);
3971  kmkernel->imapFolderMgr()->createFolderList(&names, &folders);
3972  kmkernel->dimapFolderMgr()->createFolderList(&names, &folders);
3973  kmkernel->searchFolderMgr()->createFolderList(&names, &folders);
3974  for (TQValueList<TQGuardedPtr<KMFolder> >::iterator it = folders.begin();
3975  it != folders.end(); ++it)
3976  {
3977  if (*it)
3978  {
3979  TDEConfigGroupSaver saver(KMKernel::config(),
3980  "Folder-" + (*it)->idString());
3981  KMKernel::config()->writeEntry("htmlMailOverride", false);
3982  }
3983  }
3984  }
3985  }
3986  reader.writeEntry( "htmlLoadExternal", mExternalReferences->isChecked() );
3987  reader.writeEntry( "AutoImportKeys", mAutomaticallyImportAttachedKeysCheck->isChecked() );
3988  mdn.writeEntry( "default-policy", mMDNGroup->id( mMDNGroup->selected() ) );
3989  mdn.writeEntry( "quote-message", mOrigQuoteGroup->id( mOrigQuoteGroup->selected() ) );
3990  mdn.writeEntry( "not-send-when-encrypted", mNoMDNsWhenEncryptedCheck->isChecked() );
3991  GlobalSettings::self()->setAlwaysDecrypt( mAlwaysDecrypt->isChecked() );
3992 }
3993 
3994 
3995 TQString SecurityPage::ComposerCryptoTab::helpAnchor() const {
3996  return TQString::fromLatin1("configure-security-composing");
3997 }
3998 
3999 SecurityPageComposerCryptoTab::SecurityPageComposerCryptoTab( TQWidget * parent, const char * name )
4000  : ConfigModuleTab ( parent, name )
4001 {
4002  // the margins are inside mWidget itself
4003  TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
4004 
4005  mWidget = new ComposerCryptoConfiguration( this );
4006  connect( mWidget->mAutoSignature, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4007  connect( mWidget->mEncToSelf, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4008  connect( mWidget->mShowEncryptionResult, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4009  connect( mWidget->mShowKeyApprovalDlg, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4010  connect( mWidget->mAutoEncrypt, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4011  connect( mWidget->mNeverEncryptWhenSavingInDrafts, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4012  connect( mWidget->mStoreEncrypted, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT( slotEmitChanged() ) );
4013  vlay->addWidget( mWidget );
4014 }
4015 
4016 void SecurityPage::ComposerCryptoTab::doLoadOther() {
4017  const TDEConfigGroup composer( KMKernel::config(), "Composer" );
4018 
4019  // If you change default values, sync messagecomposer.cpp too
4020 
4021  mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign", false ) );
4022 
4023  mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self", true ) );
4024  mWidget->mShowEncryptionResult->setChecked( false ); //composer.readBoolEntry( "crypto-show-encryption-result", true ) );
4025  mWidget->mShowEncryptionResult->hide();
4026  mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval", true ) );
4027 
4028  mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt", false ) );
4029  mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts", true ) );
4030 
4031  mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted", true ) );
4032 }
4033 
4034 void SecurityPage::ComposerCryptoTab::installProfile( TDEConfig * profile ) {
4035  const TDEConfigGroup composer( profile, "Composer" );
4036 
4037  if ( composer.hasKey( "pgp-auto-sign" ) )
4038  mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign" ) );
4039 
4040  if ( composer.hasKey( "crypto-encrypt-to-self" ) )
4041  mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self" ) );
4042  if ( composer.hasKey( "crypto-show-encryption-result" ) )
4043  mWidget->mShowEncryptionResult->setChecked( composer.readBoolEntry( "crypto-show-encryption-result" ) );
4044  if ( composer.hasKey( "crypto-show-keys-for-approval" ) )
4045  mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval" ) );
4046  if ( composer.hasKey( "pgp-auto-encrypt" ) )
4047  mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt" ) );
4048  if ( composer.hasKey( "never-encrypt-drafts" ) )
4049  mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts" ) );
4050 
4051  if ( composer.hasKey( "crypto-store-encrypted" ) )
4052  mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted" ) );
4053 }
4054 
4055 void SecurityPage::ComposerCryptoTab::save() {
4056  TDEConfigGroup composer( KMKernel::config(), "Composer" );
4057 
4058  composer.writeEntry( "pgp-auto-sign", mWidget->mAutoSignature->isChecked() );
4059 
4060  composer.writeEntry( "crypto-encrypt-to-self", mWidget->mEncToSelf->isChecked() );
4061  composer.writeEntry( "crypto-show-encryption-result", mWidget->mShowEncryptionResult->isChecked() );
4062  composer.writeEntry( "crypto-show-keys-for-approval", mWidget->mShowKeyApprovalDlg->isChecked() );
4063 
4064  composer.writeEntry( "pgp-auto-encrypt", mWidget->mAutoEncrypt->isChecked() );
4065  composer.writeEntry( "never-encrypt-drafts", mWidget->mNeverEncryptWhenSavingInDrafts->isChecked() );
4066 
4067  composer.writeEntry( "crypto-store-encrypted", mWidget->mStoreEncrypted->isChecked() );
4068 }
4069 
4070 TQString SecurityPage::WarningTab::helpAnchor() const {
4071  return TQString::fromLatin1("configure-security-warnings");
4072 }
4073 
4074 SecurityPageWarningTab::SecurityPageWarningTab( TQWidget * parent, const char * name )
4075  : ConfigModuleTab( parent, name )
4076 {
4077  // the margins are inside mWidget itself
4078  TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
4079 
4080  mWidget = new WarningConfiguration( this );
4081  vlay->addWidget( mWidget );
4082 
4083  connect( mWidget->warnGroupBox, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4084  connect( mWidget->mWarnUnsigned, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4085  connect( mWidget->warnUnencryptedCB, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4086  connect( mWidget->warnReceiverNotInCertificateCB, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4087  connect( mWidget->mWarnSignKeyExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4088  connect( mWidget->mWarnSignChainCertExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4089  connect( mWidget->mWarnSignRootCertExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4090 
4091  connect( mWidget->mWarnEncrKeyExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4092  connect( mWidget->mWarnEncrChainCertExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4093  connect( mWidget->mWarnEncrRootCertExpiresSB, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotEmitChanged() ) );
4094 
4095  connect( mWidget->enableAllWarningsPB, TQ_SIGNAL(clicked()),
4096  TQ_SLOT(slotReenableAllWarningsClicked()) );
4097 }
4098 
4099 void SecurityPage::WarningTab::doLoadOther() {
4100  const TDEConfigGroup composer( KMKernel::config(), "Composer" );
4101 
4102  mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted", false ) );
4103  mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned", false ) );
4104  mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert", true ) );
4105 
4106  // The "-int" part of the key name is because there used to be a separate boolean
4107  // config entry for enabling/disabling. This is done with the single bool value now.
4108  mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire", true ) );
4109 
4110  mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int", 14 ) );
4111  mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int", 14 ) );
4112  mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int", 14 ) );
4113 
4114  mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int", 14 ) );
4115  mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int", 14 ) );
4116  mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int", 14 ) );
4117 
4118  mWidget->enableAllWarningsPB->setEnabled( true );
4119 }
4120 
4121 void SecurityPage::WarningTab::installProfile( TDEConfig * profile ) {
4122  const TDEConfigGroup composer( profile, "Composer" );
4123 
4124  if ( composer.hasKey( "crypto-warning-unencrypted" ) )
4125  mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted" ) );
4126  if ( composer.hasKey( "crypto-warning-unsigned" ) )
4127  mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned" ) );
4128  if ( composer.hasKey( "crypto-warn-recv-not-in-cert" ) )
4129  mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert" ) );
4130 
4131  if ( composer.hasKey( "crypto-warn-when-near-expire" ) )
4132  mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire" ) );
4133 
4134  if ( composer.hasKey( "crypto-warn-sign-key-near-expire-int" ) )
4135  mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int" ) );
4136  if ( composer.hasKey( "crypto-warn-sign-chaincert-near-expire-int" ) )
4137  mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int" ) );
4138  if ( composer.hasKey( "crypto-warn-sign-root-near-expire-int" ) )
4139  mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int" ) );
4140 
4141  if ( composer.hasKey( "crypto-warn-encr-key-near-expire-int" ) )
4142  mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int" ) );
4143  if ( composer.hasKey( "crypto-warn-encr-chaincert-near-expire-int" ) )
4144  mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int" ) );
4145  if ( composer.hasKey( "crypto-warn-encr-root-near-expire-int" ) )
4146  mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int" ) );
4147 }
4148 
4149 void SecurityPage::WarningTab::save() {
4150  TDEConfigGroup composer( KMKernel::config(), "Composer" );
4151 
4152  composer.writeEntry( "crypto-warn-recv-not-in-cert", mWidget->warnReceiverNotInCertificateCB->isChecked() );
4153  composer.writeEntry( "crypto-warning-unencrypted", mWidget->warnUnencryptedCB->isChecked() );
4154  composer.writeEntry( "crypto-warning-unsigned", mWidget->mWarnUnsigned->isChecked() );
4155 
4156  composer.writeEntry( "crypto-warn-when-near-expire", mWidget->warnGroupBox->isChecked() );
4157  composer.writeEntry( "crypto-warn-sign-key-near-expire-int",
4158  mWidget->mWarnSignKeyExpiresSB->value() );
4159  composer.writeEntry( "crypto-warn-sign-chaincert-near-expire-int",
4160  mWidget->mWarnSignChainCertExpiresSB->value() );
4161  composer.writeEntry( "crypto-warn-sign-root-near-expire-int",
4162  mWidget->mWarnSignRootCertExpiresSB->value() );
4163 
4164  composer.writeEntry( "crypto-warn-encr-key-near-expire-int",
4165  mWidget->mWarnEncrKeyExpiresSB->value() );
4166  composer.writeEntry( "crypto-warn-encr-chaincert-near-expire-int",
4167  mWidget->mWarnEncrChainCertExpiresSB->value() );
4168  composer.writeEntry( "crypto-warn-encr-root-near-expire-int",
4169  mWidget->mWarnEncrRootCertExpiresSB->value() );
4170 }
4171 
4172 void SecurityPage::WarningTab::slotReenableAllWarningsClicked() {
4173  KMessageBox::enableAllMessages();
4174  mWidget->enableAllWarningsPB->setEnabled( false );
4175 }
4176 
4178 
4179 TQString SecurityPage::SMimeTab::helpAnchor() const {
4180  return TQString::fromLatin1("configure-security-smime-validation");
4181 }
4182 
4183 SecurityPageSMimeTab::SecurityPageSMimeTab( TQWidget * parent, const char * name )
4184  : ConfigModuleTab( parent, name )
4185 {
4186  // the margins are inside mWidget itself
4187  TQVBoxLayout* vlay = new TQVBoxLayout( this, 0, 0 );
4188 
4189  mWidget = new SMimeConfiguration( this );
4190  vlay->addWidget( mWidget );
4191 
4192  // Button-group for exclusive radiobuttons
4193  TQButtonGroup* bg = new TQButtonGroup( mWidget );
4194  bg->hide();
4195  bg->insert( mWidget->CRLRB );
4196  bg->insert( mWidget->OCSPRB );
4197 
4198  // Settings for the keyrequester custom widget
4199  mWidget->OCSPResponderSignature->setAllowedKeys(
4200  Kleo::KeySelectionDialog::SMIMEKeys
4201  | Kleo::KeySelectionDialog::TrustedKeys
4202  | Kleo::KeySelectionDialog::ValidKeys
4203  | Kleo::KeySelectionDialog::SigningKeys
4204  | Kleo::KeySelectionDialog::PublicKeys );
4205  mWidget->OCSPResponderSignature->setMultipleKeysEnabled( false );
4206 
4207  mConfig = Kleo::CryptoBackendFactory::instance()->config();
4208 
4209  connect( mWidget->CRLRB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4210  connect( mWidget->OCSPRB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4211  connect( mWidget->OCSPResponderURL, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( slotEmitChanged() ) );
4212  connect( mWidget->OCSPResponderSignature, TQ_SIGNAL( changed() ), this, TQ_SLOT( slotEmitChanged() ) );
4213  connect( mWidget->doNotCheckCertPolicyCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4214  connect( mWidget->neverConsultCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4215  connect( mWidget->fetchMissingCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4216 
4217  connect( mWidget->ignoreServiceURLCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4218  connect( mWidget->ignoreHTTPDPCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4219  connect( mWidget->disableHTTPCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4220  connect( mWidget->honorHTTPProxyRB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4221  connect( mWidget->useCustomHTTPProxyRB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4222  connect( mWidget->customHTTPProxy, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( slotEmitChanged() ) );
4223  connect( mWidget->ignoreLDAPDPCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4224  connect( mWidget->disableLDAPCB, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotEmitChanged() ) );
4225  connect( mWidget->customLDAPProxy, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( slotEmitChanged() ) );
4226 
4227  connect( mWidget->disableHTTPCB, TQ_SIGNAL( toggled( bool ) ),
4228  this, TQ_SLOT( slotUpdateHTTPActions() ) );
4229  connect( mWidget->ignoreHTTPDPCB, TQ_SIGNAL( toggled( bool ) ),
4230  this, TQ_SLOT( slotUpdateHTTPActions() ) );
4231 
4232  // Button-group for exclusive radiobuttons
4233  TQButtonGroup* bgHTTPProxy = new TQButtonGroup( mWidget );
4234  bgHTTPProxy->hide();
4235  bgHTTPProxy->insert( mWidget->honorHTTPProxyRB );
4236  bgHTTPProxy->insert( mWidget->useCustomHTTPProxyRB );
4237 
4238  if ( !connectDCOPSignal( 0, "KPIM::CryptoConfig", "changed()",
4239  "load()", false ) )
4240  kdError(5650) << "SecurityPageSMimeTab: connection to CryptoConfig's changed() failed" << endl;
4241 
4242 }
4243 
4244 SecurityPageSMimeTab::~SecurityPageSMimeTab()
4245 {
4246 }
4247 
4248 static void disableDirmngrWidget( TQWidget* w ) {
4249  w->setEnabled( false );
4250  TQWhatsThis::remove( w );
4251  TQWhatsThis::add( w, i18n( "This option requires dirmngr >= 0.9.0" ) );
4252 }
4253 
4254 static void initializeDirmngrCheckbox( TQCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
4255  if ( entry )
4256  cb->setChecked( entry->boolValue() );
4257  else
4258  disableDirmngrWidget( cb );
4259 }
4260 
4261 struct SMIMECryptoConfigEntries {
4262  SMIMECryptoConfigEntries( Kleo::CryptoConfig* config )
4263  : mConfig( config ) {
4264 
4265  // Checkboxes
4266  mCheckUsingOCSPConfigEntry = configEntry( "gpgsm", "Security", "enable-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
4267  mEnableOCSPsendingConfigEntry = configEntry( "dirmngr", "OCSP", "allow-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
4268  mDoNotCheckCertPolicyConfigEntry = configEntry( "gpgsm", "Security", "disable-policy-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
4269  mNeverConsultConfigEntry = configEntry( "gpgsm", "Security", "disable-crl-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
4270  mFetchMissingConfigEntry = configEntry( "gpgsm", "Security", "auto-issuer-key-retrieve", Kleo::CryptoConfigEntry::ArgType_None, false );
4271  // dirmngr-0.9.0 options
4272  mIgnoreServiceURLEntry = configEntry( "dirmngr", "OCSP", "ignore-ocsp-service-url", Kleo::CryptoConfigEntry::ArgType_None, false );
4273  mIgnoreHTTPDPEntry = configEntry( "dirmngr", "HTTP", "ignore-http-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
4274  mDisableHTTPEntry = configEntry( "dirmngr", "HTTP", "disable-http", Kleo::CryptoConfigEntry::ArgType_None, false );
4275  mHonorHTTPProxy = configEntry( "dirmngr", "HTTP", "honor-http-proxy", Kleo::CryptoConfigEntry::ArgType_None, false );
4276 
4277  mIgnoreLDAPDPEntry = configEntry( "dirmngr", "LDAP", "ignore-ldap-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
4278  mDisableLDAPEntry = configEntry( "dirmngr", "LDAP", "disable-ldap", Kleo::CryptoConfigEntry::ArgType_None, false );
4279  // Other widgets
4280  mOCSPResponderURLConfigEntry = configEntry( "dirmngr", "OCSP", "ocsp-responder", Kleo::CryptoConfigEntry::ArgType_String, false );
4281  mOCSPResponderSignature = configEntry( "dirmngr", "OCSP", "ocsp-signer", Kleo::CryptoConfigEntry::ArgType_String, false );
4282  mCustomHTTPProxy = configEntry( "dirmngr", "HTTP", "http-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
4283  mCustomLDAPProxy = configEntry( "dirmngr", "LDAP", "ldap-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
4284  }
4285 
4286  Kleo::CryptoConfigEntry* configEntry( const char* componentName,
4287  const char* groupName,
4288  const char* entryName,
4289  int argType,
4290  bool isList );
4291 
4292  // Checkboxes
4293  Kleo::CryptoConfigEntry* mCheckUsingOCSPConfigEntry;
4294  Kleo::CryptoConfigEntry* mEnableOCSPsendingConfigEntry;
4295  Kleo::CryptoConfigEntry* mDoNotCheckCertPolicyConfigEntry;
4296  Kleo::CryptoConfigEntry* mNeverConsultConfigEntry;
4297  Kleo::CryptoConfigEntry* mFetchMissingConfigEntry;
4298  Kleo::CryptoConfigEntry* mIgnoreServiceURLEntry;
4299  Kleo::CryptoConfigEntry* mIgnoreHTTPDPEntry;
4300  Kleo::CryptoConfigEntry* mDisableHTTPEntry;
4301  Kleo::CryptoConfigEntry* mHonorHTTPProxy;
4302  Kleo::CryptoConfigEntry* mIgnoreLDAPDPEntry;
4303  Kleo::CryptoConfigEntry* mDisableLDAPEntry;
4304  // Other widgets
4305  Kleo::CryptoConfigEntry* mOCSPResponderURLConfigEntry;
4306  Kleo::CryptoConfigEntry* mOCSPResponderSignature;
4307  Kleo::CryptoConfigEntry* mCustomHTTPProxy;
4308  Kleo::CryptoConfigEntry* mCustomLDAPProxy;
4309 
4310  Kleo::CryptoConfig* mConfig;
4311 };
4312 
4313 void SecurityPage::SMimeTab::doLoadOther() {
4314  if ( !mConfig ) {
4315  setEnabled( false );
4316  return;
4317  }
4318 
4319  // Force re-parsing gpgconf data, in case e.g. kleopatra or "configure backend" was used
4320  // (which ends up calling us via dcop)
4321  mConfig->clear();
4322 
4323  // Create config entries
4324  // Don't keep them around, they'll get deleted by clear(), which could be
4325  // done by the "configure backend" button even before we save().
4326  SMIMECryptoConfigEntries e( mConfig );
4327 
4328  // Initialize GUI items from the config entries
4329 
4330  if ( e.mCheckUsingOCSPConfigEntry ) {
4331  bool b = e.mCheckUsingOCSPConfigEntry->boolValue();
4332  mWidget->OCSPRB->setChecked( b );
4333  mWidget->CRLRB->setChecked( !b );
4334  mWidget->OCSPGroupBox->setEnabled( b );
4335  } else {
4336  mWidget->OCSPGroupBox->setEnabled( false );
4337  }
4338  if ( e.mDoNotCheckCertPolicyConfigEntry )
4339  mWidget->doNotCheckCertPolicyCB->setChecked( e.mDoNotCheckCertPolicyConfigEntry->boolValue() );
4340  if ( e.mNeverConsultConfigEntry )
4341  mWidget->neverConsultCB->setChecked( e.mNeverConsultConfigEntry->boolValue() );
4342  if ( e.mFetchMissingConfigEntry )
4343  mWidget->fetchMissingCB->setChecked( e.mFetchMissingConfigEntry->boolValue() );
4344 
4345  if ( e.mOCSPResponderURLConfigEntry )
4346  mWidget->OCSPResponderURL->setText( e.mOCSPResponderURLConfigEntry->stringValue() );
4347  if ( e.mOCSPResponderSignature ) {
4348  mWidget->OCSPResponderSignature->setFingerprint( e.mOCSPResponderSignature->stringValue() );
4349  }
4350 
4351  // dirmngr-0.9.0 options
4352  initializeDirmngrCheckbox( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
4353  initializeDirmngrCheckbox( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
4354  initializeDirmngrCheckbox( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
4355  initializeDirmngrCheckbox( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
4356  initializeDirmngrCheckbox( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
4357  if ( e.mCustomHTTPProxy ) {
4358  TQString systemProxy = TQString::fromLocal8Bit( getenv( "http_proxy" ) );
4359  if ( systemProxy.isEmpty() )
4360  systemProxy = i18n( "no proxy" );
4361  mWidget->systemHTTPProxy->setText( i18n( "(Current system setting: %1)" ).arg( systemProxy ) );
4362  bool honor = e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue();
4363  mWidget->honorHTTPProxyRB->setChecked( honor );
4364  mWidget->useCustomHTTPProxyRB->setChecked( !honor );
4365  mWidget->customHTTPProxy->setText( e.mCustomHTTPProxy->stringValue() );
4366  } else {
4367  disableDirmngrWidget( mWidget->honorHTTPProxyRB );
4368  disableDirmngrWidget( mWidget->useCustomHTTPProxyRB );
4369  disableDirmngrWidget( mWidget->systemHTTPProxy );
4370  disableDirmngrWidget( mWidget->customHTTPProxy );
4371  }
4372  if ( e.mCustomLDAPProxy )
4373  mWidget->customLDAPProxy->setText( e.mCustomLDAPProxy->stringValue() );
4374  else {
4375  disableDirmngrWidget( mWidget->customLDAPProxy );
4376  disableDirmngrWidget( mWidget->customLDAPLabel );
4377  }
4378  slotUpdateHTTPActions();
4379 }
4380 
4381 void SecurityPage::SMimeTab::slotUpdateHTTPActions() {
4382  mWidget->ignoreHTTPDPCB->setEnabled( !mWidget->disableHTTPCB->isChecked() );
4383 
4384  // The proxy settings only make sense when "Ignore HTTP CRL DPs of certificate" is checked.
4385  bool enableProxySettings = !mWidget->disableHTTPCB->isChecked()
4386  && mWidget->ignoreHTTPDPCB->isChecked();
4387  mWidget->systemHTTPProxy->setEnabled( enableProxySettings );
4388  mWidget->useCustomHTTPProxyRB->setEnabled( enableProxySettings );
4389  mWidget->honorHTTPProxyRB->setEnabled( enableProxySettings );
4390  mWidget->customHTTPProxy->setEnabled( enableProxySettings );
4391 }
4392 
4393 void SecurityPage::SMimeTab::installProfile( TDEConfig * ) {
4394 }
4395 
4396 static void saveCheckBoxToKleoEntry( TQCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
4397  const bool b = cb->isChecked();
4398  if ( entry && entry->boolValue() != b )
4399  entry->setBoolValue( b );
4400 }
4401 
4402 void SecurityPage::SMimeTab::save() {
4403  if ( !mConfig ) {
4404  return;
4405  }
4406  // Create config entries
4407  // Don't keep them around, they'll get deleted by clear(), which could be done by the
4408  // "configure backend" button.
4409  SMIMECryptoConfigEntries e( mConfig );
4410 
4411  bool b = mWidget->OCSPRB->isChecked();
4412  if ( e.mCheckUsingOCSPConfigEntry && e.mCheckUsingOCSPConfigEntry->boolValue() != b )
4413  e.mCheckUsingOCSPConfigEntry->setBoolValue( b );
4414  // Set allow-ocsp together with enable-ocsp
4415  if ( e.mEnableOCSPsendingConfigEntry && e.mEnableOCSPsendingConfigEntry->boolValue() != b )
4416  e.mEnableOCSPsendingConfigEntry->setBoolValue( b );
4417 
4418  saveCheckBoxToKleoEntry( mWidget->doNotCheckCertPolicyCB, e.mDoNotCheckCertPolicyConfigEntry );
4419  saveCheckBoxToKleoEntry( mWidget->neverConsultCB, e.mNeverConsultConfigEntry );
4420  saveCheckBoxToKleoEntry( mWidget->fetchMissingCB, e.mFetchMissingConfigEntry );
4421 
4422  TQString txt = mWidget->OCSPResponderURL->text();
4423  if ( e.mOCSPResponderURLConfigEntry && e.mOCSPResponderURLConfigEntry->stringValue() != txt )
4424  e.mOCSPResponderURLConfigEntry->setStringValue( txt );
4425 
4426  txt = mWidget->OCSPResponderSignature->fingerprint();
4427  if ( e.mOCSPResponderSignature && e.mOCSPResponderSignature->stringValue() != txt ) {
4428  e.mOCSPResponderSignature->setStringValue( txt );
4429  }
4430 
4431  //dirmngr-0.9.0 options
4432  saveCheckBoxToKleoEntry( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
4433  saveCheckBoxToKleoEntry( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
4434  saveCheckBoxToKleoEntry( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
4435  saveCheckBoxToKleoEntry( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
4436  saveCheckBoxToKleoEntry( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
4437  if ( e.mCustomHTTPProxy ) {
4438  const bool honor = mWidget->honorHTTPProxyRB->isChecked();
4439  if ( e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue() != honor )
4440  e.mHonorHTTPProxy->setBoolValue( honor );
4441 
4442  TQString chosenProxy = mWidget->customHTTPProxy->text();
4443  if ( chosenProxy != e.mCustomHTTPProxy->stringValue() )
4444  e.mCustomHTTPProxy->setStringValue( chosenProxy );
4445  }
4446  txt = mWidget->customLDAPProxy->text();
4447  if ( e.mCustomLDAPProxy && e.mCustomLDAPProxy->stringValue() != txt )
4448  e.mCustomLDAPProxy->setStringValue( mWidget->customLDAPProxy->text() );
4449 
4450  mConfig->sync( true );
4451 }
4452 
4453 bool SecurityPageSMimeTab::process(const TQCString &fun, const TQByteArray &data, TQCString& replyType, TQByteArray &replyData)
4454 {
4455  if ( fun == "load()" ) {
4456  replyType = "void";
4457  load();
4458  } else {
4459  return DCOPObject::process( fun, data, replyType, replyData );
4460  }
4461  return true;
4462 }
4463 
4464 QCStringList SecurityPageSMimeTab::interfaces()
4465 {
4466  QCStringList ifaces = DCOPObject::interfaces();
4467  ifaces += "SecurityPageSMimeTab";
4468  return ifaces;
4469 }
4470 
4471 QCStringList SecurityPageSMimeTab::functions()
4472 {
4473  // Hide our slot, just because it's simpler to do so.
4474  return DCOPObject::functions();
4475 }
4476 
4477 Kleo::CryptoConfigEntry* SMIMECryptoConfigEntries::configEntry( const char* componentName,
4478  const char* groupName,
4479  const char* entryName,
4480  int /*Kleo::CryptoConfigEntry::ArgType*/ argType,
4481  bool isList )
4482 {
4483  Kleo::CryptoConfigEntry* entry = mConfig->entry( componentName, groupName, entryName );
4484  if ( !entry ) {
4485  kdWarning(5006) << TQString( "Backend error: gpgconf doesn't seem to know the entry for %1/%2/%3" ).arg( componentName, groupName, entryName ) << endl;
4486  return 0;
4487  }
4488  if( entry->argType() != argType || entry->isList() != isList ) {
4489  kdWarning(5006) << TQString( "Backend error: gpgconf has wrong type for %1/%2/%3: %4 %5" ).arg( componentName, groupName, entryName ).arg( entry->argType() ).arg( entry->isList() ) << endl;
4490  return 0;
4491  }
4492  return entry;
4493 }
4494 
4496 
4497 TQString SecurityPage::CryptPlugTab::helpAnchor() const {
4498  return TQString::fromLatin1("configure-security-crypto-backends");
4499 }
4500 
4501 SecurityPageCryptPlugTab::SecurityPageCryptPlugTab( TQWidget * parent, const char * name )
4502  : ConfigModuleTab( parent, name )
4503 {
4504  TQVBoxLayout * vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
4505 
4506  mBackendConfig = Kleo::CryptoBackendFactory::instance()->configWidget( this, "mBackendConfig" );
4507  connect( mBackendConfig, TQ_SIGNAL( changed( bool ) ), this, TQ_SIGNAL( changed( bool ) ) );
4508 
4509  vlay->addWidget( mBackendConfig );
4510 }
4511 
4512 SecurityPageCryptPlugTab::~SecurityPageCryptPlugTab()
4513 {
4514 
4515 }
4516 
4517 void SecurityPage::CryptPlugTab::doLoadOther() {
4518  mBackendConfig->load();
4519 }
4520 
4521 void SecurityPage::CryptPlugTab::save() {
4522  mBackendConfig->save();
4523 }
4524 
4525 // *************************************************************
4526 // * *
4527 // * MiscPage *
4528 // * *
4529 // *************************************************************
4530 TQString MiscPage::helpAnchor() const {
4531  return TQString::fromLatin1("configure-misc");
4532 }
4533 
4534 MiscPage::MiscPage( TQWidget * parent, const char * name )
4535  : ConfigModuleWithTabs( parent, name )
4536 {
4537  mFolderTab = new FolderTab();
4538  addTab( mFolderTab, i18n("&Folders") );
4539 
4540  mGroupwareTab = new GroupwareTab();
4541  addTab( mGroupwareTab, i18n("&Groupware") );
4542  load();
4543 }
4544 
4545 TQString MiscPage::FolderTab::helpAnchor() const {
4546  return TQString::fromLatin1("configure-misc-folders");
4547 }
4548 
4549 MiscPageFolderTab::MiscPageFolderTab( TQWidget * parent, const char * name )
4550  : ConfigModuleTab( parent, name )
4551 {
4552  // temp. vars:
4553  TQVBoxLayout *vlay;
4554  TQHBoxLayout *hlay;
4555  TQLabel *label;
4556 
4557  vlay = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
4558 
4559  // "confirm before emptying folder" check box: stretch 0
4560  mEmptyFolderConfirmCheck =
4561  new TQCheckBox( i18n("Corresponds to Folder->Move All Messages to Trash",
4562  "Ask for co&nfirmation before moving all messages to "
4563  "trash"),
4564  this );
4565  vlay->addWidget( mEmptyFolderConfirmCheck );
4566  connect( mEmptyFolderConfirmCheck, TQ_SIGNAL( stateChanged( int ) ),
4567  this, TQ_SLOT( slotEmitChanged( void ) ) );
4568  mExcludeImportantFromExpiry =
4569  new TQCheckBox( i18n("E&xclude important messages from expiry"), this );
4570  vlay->addWidget( mExcludeImportantFromExpiry );
4571  connect( mExcludeImportantFromExpiry, TQ_SIGNAL( stateChanged( int ) ),
4572  this, TQ_SLOT( slotEmitChanged( void ) ) );
4573 
4574  // "when trying to find unread messages" combo + label: stretch 0
4575  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4576  mLoopOnGotoUnread = new TQComboBox( false, this );
4577  label = new TQLabel( mLoopOnGotoUnread,
4578  i18n("to be continued with \"do not loop\", \"loop in current folder\", "
4579  "and \"loop in all folders\".",
4580  "When trying to find unread messages:"), this );
4581  mLoopOnGotoUnread->insertStringList( TQStringList()
4582  << i18n("continuation of \"When trying to find unread messages:\"",
4583  "Do not Loop")
4584  << i18n("continuation of \"When trying to find unread messages:\"",
4585  "Loop in Current Folder")
4586  << i18n("continuation of \"When trying to find unread messages:\"",
4587  "Loop in All Folders"));
4588  hlay->addWidget( label );
4589  hlay->addWidget( mLoopOnGotoUnread, 1 );
4590  connect( mLoopOnGotoUnread, TQ_SIGNAL( activated( int ) ),
4591  this, TQ_SLOT( slotEmitChanged( void ) ) );
4592 
4593  // when entering a folder
4594  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4595  mActionEnterFolder = new TQComboBox( false, this );
4596  label = new TQLabel( mActionEnterFolder,
4597  i18n("to be continued with \"jump to first new message\", "
4598  "\"jump to first unread or new message\","
4599  "and \"jump to last selected message\".",
4600  "When entering a folder:"), this );
4601  mActionEnterFolder->insertStringList( TQStringList()
4602  << i18n("continuation of \"When entering a folder:\"",
4603  "Jump to First New Message")
4604  << i18n("continuation of \"When entering a folder:\"",
4605  "Jump to First Unread or New Message")
4606  << i18n("continuation of \"When entering a folder:\"",
4607  "Jump to Last Selected Message")
4608  << i18n("continuation of \"When entering a folder:\"",
4609  "Jump to Newest Message")
4610  << i18n("continuation of \"When entering a folder:\"",
4611  "Jump to Oldest Message") );
4612  hlay->addWidget( label );
4613  hlay->addWidget( mActionEnterFolder, 1 );
4614  connect( mActionEnterFolder, TQ_SIGNAL( activated( int ) ),
4615  this, TQ_SLOT( slotEmitChanged( void ) ) );
4616 
4617  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4618  mDelayedMarkAsRead = new TQCheckBox( i18n("Mar&k selected message as read after"), this );
4619  hlay->addWidget( mDelayedMarkAsRead );
4620  mDelayedMarkTime = new KIntSpinBox( 0 /*min*/, 60 /*max*/, 1/*step*/,
4621  0 /*init*/, 10 /*base*/, this);
4622  mDelayedMarkTime->setSuffix( i18n(" sec") );
4623  mDelayedMarkTime->setEnabled( false ); // since mDelayedMarkAsREad is off
4624  hlay->addWidget( mDelayedMarkTime );
4625  hlay->addStretch( 1 );
4626  connect( mDelayedMarkTime, TQ_SIGNAL( valueChanged( int ) ),
4627  this, TQ_SLOT( slotEmitChanged( void ) ) );
4628  connect( mDelayedMarkAsRead, TQ_SIGNAL(toggled(bool)),
4629  mDelayedMarkTime, TQ_SLOT(setEnabled(bool)));
4630  connect( mDelayedMarkAsRead, TQ_SIGNAL(toggled(bool)),
4631  this , TQ_SLOT(slotEmitChanged( void )));
4632 
4633  // "show popup after Drag'n'Drop" checkbox: stretch 0
4634  mShowPopupAfterDnD =
4635  new TQCheckBox( i18n("Ask for action after &dragging messages to another folder"), this );
4636  vlay->addWidget( mShowPopupAfterDnD );
4637  connect( mShowPopupAfterDnD, TQ_SIGNAL( stateChanged( int ) ),
4638  this, TQ_SLOT( slotEmitChanged( void ) ) );
4639 
4640  // "default mailbox format" combo + label: stretch 0
4641  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4642  mMailboxPrefCombo = new TQComboBox( false, this );
4643  label = new TQLabel( mMailboxPrefCombo,
4644  i18n("to be continued with \"flat files\" and "
4645  "\"directories\", resp.",
4646  "By default, &message folders on disk are:"), this );
4647  mMailboxPrefCombo->insertStringList( TQStringList()
4648  << i18n("continuation of \"By default, &message folders on disk are\"",
4649  "Flat Files (\"mbox\" format)")
4650  << i18n("continuation of \"By default, &message folders on disk are\"",
4651  "Directories (\"maildir\" format)") );
4652  // and now: add TQWhatsThis:
4653  TQString msg = i18n( "what's this help",
4654  "<qt><p>This selects which mailbox format will be "
4655  "the default for local folders:</p>"
4656  "<p><b>mbox:</b> KMail's mail "
4657  "folders are represented by a single file each. "
4658  "Individual messages are separated from each other by a "
4659  "line starting with \"From \". This saves space on "
4660  "disk, but may be less robust, e.g. when moving messages "
4661  "between folders.</p>"
4662  "<p><b>maildir:</b> KMail's mail folders are "
4663  "represented by real folders on disk. Individual messages "
4664  "are separate files. This may waste a bit of space on "
4665  "disk, but should be more robust, e.g. when moving "
4666  "messages between folders.</p></qt>");
4667  TQWhatsThis::add( mMailboxPrefCombo, msg );
4668  TQWhatsThis::add( label, msg );
4669  hlay->addWidget( label );
4670  hlay->addWidget( mMailboxPrefCombo, 1 );
4671  connect( mMailboxPrefCombo, TQ_SIGNAL( activated( int ) ),
4672  this, TQ_SLOT( slotEmitChanged( void ) ) );
4673 
4674  // "On startup..." option:
4675  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4676  mOnStartupOpenFolder = new FolderRequester( this,
4677  kmkernel->getKMMainWidget()->folderTree() );
4678  label = new TQLabel( mOnStartupOpenFolder,
4679  i18n("Open this folder on startup:"), this );
4680  hlay->addWidget( label );
4681  hlay->addWidget( mOnStartupOpenFolder, 1 );
4682  connect( mOnStartupOpenFolder, TQ_SIGNAL( folderChanged( KMFolder* ) ),
4683  this, TQ_SLOT( slotEmitChanged( void ) ) );
4684 
4685  // "Empty &trash on program exit" option:
4686  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4687  mEmptyTrashCheck = new TQCheckBox( i18n("Empty local &trash folder on program exit"),
4688  this );
4689  hlay->addWidget( mEmptyTrashCheck );
4690  connect( mEmptyTrashCheck, TQ_SIGNAL( stateChanged( int ) ),
4691  this, TQ_SLOT( slotEmitChanged( void ) ) );
4692 
4693 #ifdef HAVE_INDEXLIB
4694  // indexing enabled option:
4695  mIndexingEnabled = new TQCheckBox( i18n("Enable full text &indexing"), this );
4696  vlay->addWidget( mIndexingEnabled );
4697  connect( mIndexingEnabled, TQ_SIGNAL( stateChanged( int ) ),
4698  this, TQ_SLOT( slotEmitChanged( void ) ) );
4699 #endif
4700 
4701  // "Quota Units"
4702  hlay = new TQHBoxLayout( vlay ); // inherits spacing
4703  mQuotaCmbBox = new TQComboBox( false, this );
4704  label = new TQLabel( mQuotaCmbBox,
4705  i18n("Quota units: "), this );
4706  mQuotaCmbBox->insertStringList( TQStringList()
4707  << i18n("KB")
4708  << i18n("MB")
4709  << i18n("GB") );
4710  hlay->addWidget( label );
4711  hlay->addWidget( mQuotaCmbBox, 1 );
4712  connect( mQuotaCmbBox, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( slotEmitChanged( void ) ) );
4713 
4714  vlay->addStretch( 1 );
4715 
4716  // @TODO: Till, move into .kcgc file
4717  msg = i18n( "what's this help",
4718  "<qt><p>When jumping to the next unread message, it may occur "
4719  "that no more unread messages are below the current message.</p>"
4720  "<p><b>Do not loop:</b> The search will stop at the last message in "
4721  "the current folder.</p>"
4722  "<p><b>Loop in current folder:</b> The search will continue at the "
4723  "top of the message list, but not go to another folder.</p>"
4724  "<p><b>Loop in all folders:</b> The search will continue at the top of "
4725  "the message list. If no unread messages are found it will then continue "
4726  "to the next folder.</p>"
4727  "<p>Similarly, when searching for the previous unread message, "
4728  "the search will start from the bottom of the message list and continue to "
4729  "the previous folder depending on which option is selected.</p></qt>" );
4730  TQWhatsThis::add( mLoopOnGotoUnread, msg );
4731 
4732 #ifdef HAVE_INDEXLIB
4733  // this is probably overly pessimistic
4734  msg = i18n( "what's this help",
4735  "<qt><p>Full text indexing allows very fast searches on the content "
4736  "of your messages. When enabled, the search dialog will work very fast. "
4737  "Also, the search tool bar will select messages based on content.</p>"
4738  "<p>It takes up a certain amount of disk space "
4739  "(about half the disk space for the messages).</p>"
4740  "<p>After enabling, the index will need to be built, but you can continue to use KMail "
4741  "while this operation is running.</p>"
4742  "</qt>"
4743  );
4744 
4745  TQWhatsThis::add( mIndexingEnabled, msg );
4746 #endif
4747 }
4748 
4749 void MiscPage::FolderTab::doLoadFromGlobalSettings() {
4750  mExcludeImportantFromExpiry->setChecked( GlobalSettings::self()->excludeImportantMailFromExpiry() );
4751  // default = "Loop in current folder"
4752  mLoopOnGotoUnread->setCurrentItem( GlobalSettings::self()->loopOnGotoUnread() );
4753  mActionEnterFolder->setCurrentItem( GlobalSettings::self()->actionEnterFolder() );
4754  mDelayedMarkAsRead->setChecked( GlobalSettings::self()->delayedMarkAsRead() );
4755  mDelayedMarkTime->setValue( GlobalSettings::self()->delayedMarkTime() );
4756  mShowPopupAfterDnD->setChecked( GlobalSettings::self()->showPopupAfterDnD() );
4757  mQuotaCmbBox->setCurrentItem( GlobalSettings::self()->quotaUnit() );
4758 }
4759 
4760 void MiscPage::FolderTab::doLoadOther() {
4761  TDEConfigGroup general( KMKernel::config(), "General" );
4762 
4763  mEmptyTrashCheck->setChecked( general.readBoolEntry( "empty-trash-on-exit", true ) );
4764  mOnStartupOpenFolder->setFolder( general.readEntry( "startupFolder",
4765  kmkernel->inboxFolder()->idString() ) );
4766  mEmptyFolderConfirmCheck->setChecked( general.readBoolEntry( "confirm-before-empty", true ) );
4767 
4768  int num = general.readNumEntry("default-mailbox-format", 1 );
4769  if ( num < 0 || num > 1 ) num = 1;
4770  mMailboxPrefCombo->setCurrentItem( num );
4771 
4772 #ifdef HAVE_INDEXLIB
4773  mIndexingEnabled->setChecked( kmkernel->msgIndex() && kmkernel->msgIndex()->isEnabled() );
4774 #endif
4775 }
4776 
4777 void MiscPage::FolderTab::save() {
4778  TDEConfigGroup general( KMKernel::config(), "General" );
4779 
4780  general.writeEntry( "empty-trash-on-exit", mEmptyTrashCheck->isChecked() );
4781  general.writeEntry( "confirm-before-empty", mEmptyFolderConfirmCheck->isChecked() );
4782  general.writeEntry( "default-mailbox-format", mMailboxPrefCombo->currentItem() );
4783  general.writeEntry( "startupFolder", mOnStartupOpenFolder->folder() ?
4784  mOnStartupOpenFolder->folder()->idString() : TQString() );
4785 
4786  GlobalSettings::self()->setDelayedMarkAsRead( mDelayedMarkAsRead->isChecked() );
4787  GlobalSettings::self()->setDelayedMarkTime( mDelayedMarkTime->value() );
4788  GlobalSettings::self()->setActionEnterFolder( mActionEnterFolder->currentItem() );
4789  GlobalSettings::self()->setLoopOnGotoUnread( mLoopOnGotoUnread->currentItem() );
4790  GlobalSettings::self()->setShowPopupAfterDnD( mShowPopupAfterDnD->isChecked() );
4791  GlobalSettings::self()->setExcludeImportantMailFromExpiry(
4792  mExcludeImportantFromExpiry->isChecked() );
4793  GlobalSettings::self()->setQuotaUnit( mQuotaCmbBox->currentItem() );
4794 #ifdef HAVE_INDEXLIB
4795  if ( kmkernel->msgIndex() ) kmkernel->msgIndex()->setEnabled( mIndexingEnabled->isChecked() );
4796 #endif
4797 }
4798 
4799 TQString MiscPage::GroupwareTab::helpAnchor() const {
4800  return TQString::fromLatin1("configure-misc-groupware");
4801 }
4802 
4803 MiscPageGroupwareTab::MiscPageGroupwareTab( TQWidget* parent, const char* name )
4804  : ConfigModuleTab( parent, name )
4805 {
4806  TQBoxLayout* vlay = new TQVBoxLayout( this, KDialog::marginHint(),
4807  KDialog::spacingHint() );
4808  vlay->setAutoAdd( true );
4809 
4810  // IMAP resource setup
4811  TQVGroupBox* b1 = new TQVGroupBox( i18n("&IMAP Resource Folder Options"),
4812  this );
4813 
4814  mEnableImapResCB =
4815  new TQCheckBox( i18n("&Enable IMAP resource functionality"), b1 );
4816  TQToolTip::add( mEnableImapResCB, i18n( "This enables the IMAP storage for "
4817  "the Kontact applications" ) );
4818  TQWhatsThis::add( mEnableImapResCB,
4819  i18n( GlobalSettings::self()->theIMAPResourceEnabledItem()->whatsThis().utf8() ) );
4820  connect( mEnableImapResCB, TQ_SIGNAL( stateChanged( int ) ),
4821  this, TQ_SLOT( slotEmitChanged( void ) ) );
4822 
4823  mBox = new TQWidget( b1 );
4824  TQGridLayout* grid = new TQGridLayout( mBox, 5, 2, 0, KDialog::spacingHint() );
4825  grid->setColStretch( 1, 1 );
4826  connect( mEnableImapResCB, TQ_SIGNAL( toggled(bool) ),
4827  mBox, TQ_SLOT( setEnabled(bool) ) );
4828 
4829  TQLabel* storageFormatLA = new TQLabel( i18n("&Format used for the groupware folders:"),
4830  mBox );
4831  TQString toolTip = i18n( "Choose the format to use to store the contents of the groupware folders." );
4832  TQString whatsThis = i18n( GlobalSettings::self()
4833  ->theIMAPResourceStorageFormatItem()->whatsThis().utf8() );
4834  grid->addWidget( storageFormatLA, 0, 0 );
4835  TQToolTip::add( storageFormatLA, toolTip );
4836  TQWhatsThis::add( storageFormatLA, whatsThis );
4837  mStorageFormatCombo = new TQComboBox( false, mBox );
4838  storageFormatLA->setBuddy( mStorageFormatCombo );
4839  TQStringList formatLst;
4840  formatLst << i18n("Deprecated Kolab1 (iCal/vCard)") << i18n("Kolab2 (XML)");
4841  mStorageFormatCombo->insertStringList( formatLst );
4842  grid->addWidget( mStorageFormatCombo, 0, 1 );
4843  TQToolTip::add( mStorageFormatCombo, toolTip );
4844  TQWhatsThis::add( mStorageFormatCombo, whatsThis );
4845  connect( mStorageFormatCombo, TQ_SIGNAL( activated( int ) ),
4846  this, TQ_SLOT( slotStorageFormatChanged( int ) ) );
4847 
4848  TQLabel* languageLA = new TQLabel( i18n("&Language of the groupware folders:"),
4849  mBox );
4850 
4851  toolTip = i18n( "Set the language of the folder names" );
4852  whatsThis = i18n( GlobalSettings::self()
4853  ->theIMAPResourceFolderLanguageItem()->whatsThis().utf8() );
4854  grid->addWidget( languageLA, 1, 0 );
4855  TQToolTip::add( languageLA, toolTip );
4856  TQWhatsThis::add( languageLA, whatsThis );
4857  mLanguageCombo = new TQComboBox( false, mBox );
4858  languageLA->setBuddy( mLanguageCombo );
4859  TQStringList lst;
4860  lst << i18n("English") << i18n("German") << i18n("French") << i18n("Dutch");
4861  mLanguageCombo->insertStringList( lst );
4862  grid->addWidget( mLanguageCombo, 1, 1 );
4863  TQToolTip::add( mLanguageCombo, toolTip );
4864  TQWhatsThis::add( mLanguageCombo, whatsThis );
4865  connect( mLanguageCombo, TQ_SIGNAL( activated( int ) ),
4866  this, TQ_SLOT( slotEmitChanged( void ) ) );
4867 
4868  mFolderComboLabel = new TQLabel( mBox ); // text depends on storage format
4869  toolTip = i18n( "Set the parent of the resource folders" );
4870  whatsThis = i18n( GlobalSettings::self()->theIMAPResourceFolderParentItem()->whatsThis().utf8() );
4871  TQToolTip::add( mFolderComboLabel, toolTip );
4872  TQWhatsThis::add( mFolderComboLabel, whatsThis );
4873  grid->addWidget( mFolderComboLabel, 2, 0 );
4874 
4875  mFolderComboStack = new TQWidgetStack( mBox );
4876  grid->addWidget( mFolderComboStack, 2, 1 );
4877 
4878  // First possibility in the widgetstack: a combo showing the list of all folders
4879  // This is used with the ical/vcard storage
4880  mFolderCombo = new FolderRequester( mBox,
4881  kmkernel->getKMMainWidget()->folderTree() );
4882  mFolderComboStack->addWidget( mFolderCombo, 0 );
4883  TQToolTip::add( mFolderCombo, toolTip );
4884  TQWhatsThis::add( mFolderCombo, whatsThis );
4885  connect( mFolderCombo, TQ_SIGNAL( folderChanged( KMFolder* ) ),
4886  this, TQ_SLOT( slotEmitChanged() ) );
4887 
4888  // Second possibility in the widgetstack: a combo showing the list of accounts
4889  // This is used with the kolab xml storage since the groupware folders
4890  // are always under the inbox.
4891  mAccountCombo = new KMail::AccountComboBox( mBox );
4892  mFolderComboStack->addWidget( mAccountCombo, 1 );
4893  TQToolTip::add( mAccountCombo, toolTip );
4894  TQWhatsThis::add( mAccountCombo, whatsThis );
4895  connect( mAccountCombo, TQ_SIGNAL( activated( int ) ),
4896  this, TQ_SLOT( slotEmitChanged() ) );
4897 
4898  mHideGroupwareFolders = new TQCheckBox( i18n( "&Hide groupware folders" ),
4899  mBox, "HideGroupwareFoldersBox" );
4900  grid->addMultiCellWidget( mHideGroupwareFolders, 3, 3, 0, 0 );
4901  TQToolTip::add( mHideGroupwareFolders,
4902  i18n( "When this is checked, you will not see the IMAP "
4903  "resource folders in the folder tree." ) );
4904  TQWhatsThis::add( mHideGroupwareFolders, i18n( GlobalSettings::self()
4905  ->hideGroupwareFoldersItem()->whatsThis().utf8() ) );
4906  connect( mHideGroupwareFolders, TQ_SIGNAL( toggled( bool ) ),
4907  this, TQ_SLOT( slotEmitChanged() ) );
4908 
4909  mOnlyShowGroupwareFolders = new TQCheckBox( i18n( "&Only show groupware folders for this account" ),
4910  mBox, "OnlyGroupwareFoldersBox" );
4911  grid->addMultiCellWidget( mOnlyShowGroupwareFolders, 3, 3, 1, 1 );
4912  TQToolTip::add( mOnlyShowGroupwareFolders,
4913  i18n( "When this is checked, you will not see normal "
4914  "mail folders in the folder tree for the account "
4915  "configured for groupware." ) );
4916  TQWhatsThis::add( mOnlyShowGroupwareFolders, i18n( GlobalSettings::self()
4917  ->showOnlyGroupwareFoldersForGroupwareAccountItem()->whatsThis().utf8() ) );
4918  connect( mOnlyShowGroupwareFolders, TQ_SIGNAL( toggled( bool ) ),
4919  this, TQ_SLOT( slotEmitChanged() ) );
4920 
4921  mSyncImmediately = new TQCheckBox( i18n( "Synchronize groupware changes immediately" ), mBox );
4922  TQToolTip::add( mSyncImmediately,
4923  i18n( "Synchronize groupware changes in disconnected IMAP folders immediately when being online." ) );
4924  connect( mSyncImmediately, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4925  grid->addMultiCellWidget( mSyncImmediately, 4, 4, 0, 1 );
4926 
4927  mDeleteInvitations = new TQCheckBox(
4928  i18n( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReplyItem()->label().utf8() ), mBox );
4929  TQWhatsThis::add( mDeleteInvitations, i18n( GlobalSettings::self()
4930  ->deleteInvitationEmailsAfterSendingReplyItem()->whatsThis().utf8() ) );
4931  connect( mDeleteInvitations, TQ_SIGNAL(toggled(bool)), TQ_SLOT(slotEmitChanged()) );
4932  grid->addMultiCellWidget( mDeleteInvitations, 5, 5, 0, 1 );
4933 
4934  // Groupware functionality compatibility setup
4935  b1 = new TQVGroupBox( i18n("Groupware Compatibility && Legacy Options"), this );
4936 
4937  gBox = new TQVBox( b1 );
4938 #if 0
4939  // Currently believed to be disused.
4940  mEnableGwCB = new TQCheckBox( i18n("&Enable groupware functionality"), b1 );
4941  gBox->setSpacing( KDialog::spacingHint() );
4942  connect( mEnableGwCB, TQ_SIGNAL( toggled(bool) ),
4943  gBox, TQ_SLOT( setEnabled(bool) ) );
4944  connect( mEnableGwCB, TQ_SIGNAL( stateChanged( int ) ),
4945  this, TQ_SLOT( slotEmitChanged( void ) ) );
4946 #endif
4947  mEnableGwCB = 0;
4948  mLegacyMangleFromTo = new TQCheckBox( i18n( "Mangle From:/To: headers in replies to invitations" ), gBox );
4949  TQToolTip::add( mLegacyMangleFromTo, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitation replies" ) );
4950  TQWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
4951  legacyMangleFromToHeadersItem()->whatsThis().utf8() ) );
4952  connect( mLegacyMangleFromTo, TQ_SIGNAL( stateChanged( int ) ),
4953  this, TQ_SLOT( slotEmitChanged( void ) ) );
4954  mLegacyBodyInvites = new TQCheckBox( i18n( "Send invitations in the mail body" ), gBox );
4955  TQToolTip::add( mLegacyBodyInvites, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitations" ) );
4956  TQWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
4957  legacyBodyInvitesItem()->whatsThis().utf8() ) );
4958  connect( mLegacyBodyInvites, TQ_SIGNAL( toggled( bool ) ),
4959  this, TQ_SLOT( slotLegacyBodyInvitesToggled( bool ) ) );
4960  connect( mLegacyBodyInvites, TQ_SIGNAL( stateChanged( int ) ),
4961  this, TQ_SLOT( slotEmitChanged( void ) ) );
4962 
4963  mExchangeCompatibleInvitations = new TQCheckBox( i18n( "Exchange compatible invitation naming" ), gBox );
4964  TQToolTip::add( mExchangeCompatibleInvitations, i18n( "Outlook(tm), when used in combination with a Microsoft Exchange server,\nhas a problem understanding standards-compliant groupware e-mail.\nTurn this option on to send groupware invitations and replies in an Exchange compatible way." ) );
4965  TQWhatsThis::add( mExchangeCompatibleInvitations, i18n( GlobalSettings::self()->
4966  exchangeCompatibleInvitationsItem()->whatsThis().utf8() ) );
4967  connect( mExchangeCompatibleInvitations, TQ_SIGNAL( stateChanged( int ) ),
4968  this, TQ_SLOT( slotEmitChanged( void ) ) );
4969 
4970  mOutlookCompatibleInvitationComments = new TQCheckBox( i18n( "Outlook compatible invitation reply comments" ), gBox );
4971  TQToolTip::add( mOutlookCompatibleInvitationComments, i18n( "Send invitation reply comments in a way that Microsoft Outlook(tm) understands." ) );
4972  TQWhatsThis::add( mOutlookCompatibleInvitationComments, i18n( GlobalSettings::self()->
4973  outlookCompatibleInvitationReplyCommentsItem()->whatsThis().utf8() ) );
4974  connect( mOutlookCompatibleInvitationComments, TQ_SIGNAL( stateChanged( int ) ),
4975  this, TQ_SLOT( slotEmitChanged( void ) ) );
4976 
4977  mAutomaticSending = new TQCheckBox( i18n( "Automatic invitation sending" ), gBox );
4978  TQToolTip::add( mAutomaticSending, i18n( "When this is on, the user will not see the mail composer window. Invitation mails are sent automatically" ) );
4979  TQWhatsThis::add( mAutomaticSending, i18n( GlobalSettings::self()->
4980  automaticSendingItem()->whatsThis().utf8() ) );
4981  connect( mAutomaticSending, TQ_SIGNAL( stateChanged( int ) ),
4982  this, TQ_SLOT( slotEmitChanged( void ) ) );
4983 
4984  // Open space padding at the end
4985  new TQLabel( this );
4986 }
4987 
4988 void MiscPageGroupwareTab::slotLegacyBodyInvitesToggled( bool on )
4989 {
4990  if ( on ) {
4991  TQString txt = i18n( "<qt>Invitations are normally sent as attachments to "
4992  "a mail. This switch changes the invitation mails to "
4993  "be sent in the text of the mail instead; this is "
4994  "necessary to send invitations and replies to "
4995  "Microsoft Outlook.<br>But, when you do this, you no "
4996  "longer get descriptive text that mail programs "
4997  "can read; so, to people who have email programs "
4998  "that do not understand the invitations, the "
4999  "resulting messages look very odd.<br>People that have email "
5000  "programs that do understand invitations will still "
5001  "be able to work with this.</qt>" );
5002  KMessageBox::information( this, txt, TQString(),
5003  "LegacyBodyInvitesWarning" );
5004  }
5005  // Invitations in the body are autosent in any case (no point in editing raw ICAL)
5006  // So the autosend option is only available if invitations are sent as attachment.
5007  mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
5008 }
5009 
5010 void MiscPage::GroupwareTab::doLoadFromGlobalSettings() {
5011  if ( mEnableGwCB ) {
5012  mEnableGwCB->setChecked( GlobalSettings::self()->groupwareEnabled() );
5013  gBox->setEnabled( mEnableGwCB->isChecked() );
5014  }
5015 
5016  mLegacyMangleFromTo->setChecked( GlobalSettings::self()->legacyMangleFromToHeaders() );
5017  mLegacyBodyInvites->blockSignals( true );
5018 
5019  mLegacyBodyInvites->setChecked( GlobalSettings::self()->legacyBodyInvites() );
5020  mLegacyBodyInvites->blockSignals( false );
5021 
5022  mExchangeCompatibleInvitations->setChecked( GlobalSettings::self()->exchangeCompatibleInvitations() );
5023 
5024  mOutlookCompatibleInvitationComments->setChecked( GlobalSettings::self()->outlookCompatibleInvitationReplyComments() );
5025 
5026  mAutomaticSending->setChecked( GlobalSettings::self()->automaticSending() );
5027  mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
5028 
5029  // Read the IMAP resource config
5030  mEnableImapResCB->setChecked( GlobalSettings::self()->theIMAPResourceEnabled() );
5031  mBox->setEnabled( mEnableImapResCB->isChecked() );
5032 
5033  mHideGroupwareFolders->setChecked( GlobalSettings::self()->hideGroupwareFolders() );
5034  int i = GlobalSettings::self()->theIMAPResourceFolderLanguage();
5035  mLanguageCombo->setCurrentItem(i);
5036  i = GlobalSettings::self()->theIMAPResourceStorageFormat();
5037  mStorageFormatCombo->setCurrentItem(i);
5038  slotStorageFormatChanged( i );
5039  mOnlyShowGroupwareFolders->setChecked( GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount() );
5040  mSyncImmediately->setChecked( GlobalSettings::self()->immediatlySyncDIMAPOnGroupwareChanges() );
5041  mDeleteInvitations->setChecked( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReply() );
5042 
5043  TQString folderId( GlobalSettings::self()->theIMAPResourceFolderParent() );
5044  if( !folderId.isNull() && kmkernel->findFolderById( folderId ) ) {
5045  mFolderCombo->setFolder( folderId );
5046  } else {
5047  // Folder was deleted, we have to choose a new one
5048  mFolderCombo->setFolder( i18n( "<Choose a Folder>" ) );
5049  }
5050 
5051  KMAccount* selectedAccount = 0;
5052  int accountId = GlobalSettings::self()->theIMAPResourceAccount();
5053  if ( accountId )
5054  selectedAccount = kmkernel->acctMgr()->find( accountId );
5055  else {
5056  // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
5057  for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
5058  a = kmkernel->acctMgr()->next() ) {
5059  if( a->folder() && a->folder()->child() ) {
5060  // Look inside that folder for an INBOX
5061  KMFolderNode *node;
5062  for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next())
5063  if (!node->isDir() && node->name() == "INBOX") break;
5064 
5065  if ( node && static_cast<KMFolder*>(node)->idString() == folderId ) {
5066  selectedAccount = a;
5067  break;
5068  }
5069  }
5070  }
5071  }
5072  if ( selectedAccount )
5073  mAccountCombo->setCurrentAccount( selectedAccount );
5074  else if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == 1 )
5075  kdDebug(5006) << "Folder " << folderId << " not found as an account's inbox" << endl;
5076 }
5077 
5078 void MiscPage::GroupwareTab::save() {
5079  TDEConfigGroup groupware( KMKernel::config(), "Groupware" );
5080 
5081  // Write the groupware config
5082  if ( mEnableGwCB ) {
5083  groupware.writeEntry( "GroupwareEnabled", mEnableGwCB->isChecked() );
5084  }
5085  groupware.writeEntry( "LegacyMangleFromToHeaders", mLegacyMangleFromTo->isChecked() );
5086  groupware.writeEntry( "LegacyBodyInvites", mLegacyBodyInvites->isChecked() );
5087  groupware.writeEntry( "ExchangeCompatibleInvitations", mExchangeCompatibleInvitations->isChecked() );
5088  groupware.writeEntry( "OutlookCompatibleInvitationReplyComments", mOutlookCompatibleInvitationComments->isChecked() );
5089  groupware.writeEntry( "AutomaticSending", mAutomaticSending->isChecked() );
5090 
5091  if ( mEnableGwCB ) {
5092  GlobalSettings::self()->setGroupwareEnabled( mEnableGwCB->isChecked() );
5093  }
5094  GlobalSettings::self()->setLegacyMangleFromToHeaders( mLegacyMangleFromTo->isChecked() );
5095  GlobalSettings::self()->setLegacyBodyInvites( mLegacyBodyInvites->isChecked() );
5096  GlobalSettings::self()->setExchangeCompatibleInvitations( mExchangeCompatibleInvitations->isChecked() );
5097  GlobalSettings::self()->setOutlookCompatibleInvitationReplyComments( mOutlookCompatibleInvitationComments->isChecked() );
5098  GlobalSettings::self()->setAutomaticSending( mAutomaticSending->isChecked() );
5099 
5100  int format = mStorageFormatCombo->currentItem();
5101  GlobalSettings::self()->setTheIMAPResourceStorageFormat( format );
5102 
5103  // Write the IMAP resource config
5104  GlobalSettings::self()->setHideGroupwareFolders( mHideGroupwareFolders->isChecked() );
5105  GlobalSettings::self()->setShowOnlyGroupwareFoldersForGroupwareAccount( mOnlyShowGroupwareFolders->isChecked() );
5106  GlobalSettings::self()->setImmediatlySyncDIMAPOnGroupwareChanges( mSyncImmediately->isChecked() );
5107  GlobalSettings::self()->setDeleteInvitationEmailsAfterSendingReply( mDeleteInvitations->isChecked() );
5108 
5109  // If there is a leftover folder in the foldercombo, getFolder can
5110  // return 0. In that case we really don't have it enabled
5111  TQString folderId;
5112  if ( format == 0 ) {
5113  KMFolder* folder = mFolderCombo->folder();
5114  if ( folder )
5115  folderId = folder->idString();
5116  KMAccount* account = 0;
5117  // Didn't find an easy way to find the account for a given folder...
5118  // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
5119  for( KMAccount *a = kmkernel->acctMgr()->first();
5120  a && !account; // stop when found
5121  a = kmkernel->acctMgr()->next() ) {
5122  if( a->folder() && a->folder()->child() ) {
5123  KMFolderNode *node;
5124  for ( node = a->folder()->child()->first(); node; node = a->folder()->child()->next() )
5125  {
5126  if ( static_cast<KMFolder*>(node) == folder ) {
5127  account = a;
5128  break;
5129  }
5130  }
5131  }
5132  }
5133  GlobalSettings::self()->setTheIMAPResourceAccount( account ? account->id() : 0 );
5134  } else {
5135  // Inbox folder of the selected account
5136  KMAccount* acct = mAccountCombo->currentAccount();
5137  if ( acct ) {
5138  folderId = TQString( ".%1.directory/INBOX" ).arg( acct->id() );
5139  GlobalSettings::self()->setTheIMAPResourceAccount( acct->id() );
5140  }
5141  }
5142 
5143  bool enabled = mEnableImapResCB->isChecked() && !folderId.isEmpty();
5144  GlobalSettings::self()->setTheIMAPResourceEnabled( enabled );
5145  GlobalSettings::self()->setTheIMAPResourceFolderLanguage( mLanguageCombo->currentItem() );
5146  GlobalSettings::self()->setTheIMAPResourceFolderParent( folderId );
5147 }
5148 
5149 void MiscPage::GroupwareTab::slotStorageFormatChanged( int format )
5150 {
5151  mLanguageCombo->setEnabled( format == 0 ); // only ical/vcard needs the language hack
5152  mFolderComboStack->raiseWidget( format );
5153  if ( format == 0 ) {
5154  mFolderComboLabel->setText( i18n("&Resource folders are subfolders of:") );
5155  mFolderComboLabel->setBuddy( mFolderCombo );
5156  } else {
5157  mFolderComboLabel->setText( i18n("&Resource folders are in account:") );
5158  mFolderComboLabel->setBuddy( mAccountCombo );
5159  }
5160  slotEmitChanged();
5161 }
5162 
5163 
5164 // *************************************************************
5165 // * *
5166 // * AccountUpdater *
5167 // * *
5168 // *************************************************************
5169 AccountUpdater::AccountUpdater(ImapAccountBase *account)
5170  : TQObject()
5171 {
5172  mAccount = account;
5173 }
5174 
5175 void AccountUpdater::update()
5176 {
5177  connect( mAccount, TQ_SIGNAL( connectionResult(int, const TQString&) ),
5178  this, TQ_SLOT( namespacesFetched() ) );
5179  mAccount->makeConnection();
5180 }
5181 
5182 void AccountUpdater::namespacesFetched()
5183 {
5184  mAccount->setCheckingMail( true );
5185  mAccount->processNewMail( false );
5186  deleteLater();
5187 }
5188 
5189 #undef DIM
5190 
5191 //----------------------------
5192 #include "configuredialog.moc"
DImap accounts need to be updated after just being created to show the folders it has.
Select account from given list of account types.
Definition: kmacctseldlg.h:31
Mail folder.
Definition: kmfolder.h:69
TQString idString() const
Returns a string that can be used to identify this folder.
Definition: kmfolder.cpp:705
A readonly combobox showing the accounts, to select one.
A widget that contains a KLineEdit which shows the current folder and a button that fires a KMFolderS...
A TQListViewItem for use in IdentityListView.
A listview for KPIM::Identity.