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"
38using 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"
59using KMail::ImapAccountBase;
60#include "folderstorage.h"
61#include "kmfolder.h"
62#include "kmmainwidget.h"
63#include "recentaddresses.h"
64using TDERecentAddress::RecentAddresses;
65#include "completionordereditor.h"
66#include "ldapclient.h"
67#include "index.h"
68
71#include "identitydialog.h"
72using KMail::IdentityDialog;
73
74// other tdenetwork headers:
75#include <libkpimidentities/identity.h>
76#include <kmime_util.h>
77using 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 <tdestandarddirs.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
134namespace {
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
217ConfigureDialog::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(), tdeApp->icon(), tdeApp->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
245void 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
252ConfigureDialog::~ConfigureDialog() {
253}
254
255void ConfigureDialog::slotApply() {
256 KCMultiDialog::slotApply();
257 GlobalSettings::self()->writeConfig();
258 emit configChanged();
259}
260
261void ConfigureDialog::slotOk() {
262 KCMultiDialog::slotOk();
263 GlobalSettings::self()->writeConfig();
264 emit configChanged();
265}
266
267void 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// *************************************************************
283TQString IdentityPage::helpAnchor() const {
284 return TQString::fromLatin1("configure-identity");
285}
286
287IdentityPage::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
341void 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
353void 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
377void 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
420void 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
441void 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
464void IdentityPage::slotRenameIdentity() {
465 assert( !mIdentityDialog );
466
467 TQListViewItem * item = mIdentityList->selectedItem();
468 if ( !item ) return;
469
470 mIdentityList->rename( item, 0 );
471}
472
473void 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
491void 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
509void 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
521void 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
531void IdentityPage::slotIdentitySelectionChanged()
532{
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
542void IdentityPage::slotUpdateTransportCombo( const TQStringList & sl )
543{
544 if ( mIdentityDialog ) mIdentityDialog->slotUpdateTransportCombo( sl );
545}
546
547
548
549// *************************************************************
550// * *
551// * AccountsPage *
552// * *
553// *************************************************************
554TQString AccountsPage::helpAnchor() const {
555 return TQString::fromLatin1("configure-accounts");
556}
557
558AccountsPage::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
580TQString AccountsPage::SendingTab::helpAnchor() const {
581 return TQString::fromLatin1("configure-accounts-sending");
582}
583
584AccountsPageSendingTab::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
728void 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
737static 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
751void 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
777void 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
844void 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
901void 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
968void AccountsPage::SendingTab::doLoadFromGlobalSettings() {
969 mSendOnCheckCombo->setCurrentItem( GlobalSettings::self()->sendOnCheck() );
970}
971
972void 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
1034void 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
1055TQString AccountsPage::ReceivingTab::helpAnchor() const {
1056 return TQString::fromLatin1("configure-accounts-receiving");
1057}
1058
1059AccountsPageReceivingTab::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
1156AccountsPageReceivingTab::~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
1179void AccountsPage::ReceivingTab::slotAccountSelected()
1180{
1181 TQListViewItem * item = mAccountList->selectedItem();
1182 mModifyAccountButton->setEnabled( item );
1183 mRemoveAccountButton->setEnabled( item );
1184}
1185
1186TQStringList 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
1212void 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
1269void 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
1337void 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
1381void AccountsPage::ReceivingTab::slotEditNotifications()
1382{
1383 if(kmkernel->xmlGuiInstance())
1384 KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
1385 else
1386 KNotifyDialog::configure(this);
1387}
1388
1389void AccountsPage::ReceivingTab::doLoadFromGlobalSettings() {
1390 mVerboseNotificationCheck->setChecked( GlobalSettings::self()->verboseNewMailNotification() );
1391}
1392
1393void 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
1418void 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
1425void 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// *************************************************************
1480TQString AppearancePage::helpAnchor() const {
1481 return TQString::fromLatin1("configure-appearance");
1482}
1483
1484AppearancePage::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
1527TQString AppearancePage::FontsTab::helpAnchor() const {
1528 return TQString::fromLatin1("configure-appearance-fonts");
1529}
1530
1531static 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};
1552static const int numFontNames = sizeof fontNames / sizeof *fontNames;
1553
1554AppearancePageFontsTab::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
1609void 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
1646void 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
1660void 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
1680void 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
1696TQString AppearancePage::ColorsTab::helpAnchor() const {
1697 return TQString::fromLatin1("configure-appearance-colors");
1698}
1699
1700
1701static 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};
1730static const int numColorNames = sizeof colorNames / sizeof *colorNames;
1731
1732AppearancePageColorsTab::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
1788void 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 tdeApp->palette().active().base(), // bg
1797 TDEGlobalSettings::alternateBackgroundColor(), // alt bg
1798 tdeApp->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
1830void 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
1843void 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
1859TQString AppearancePage::LayoutTab::helpAnchor() const {
1860 return TQString::fromLatin1("configure-appearance-layout");
1861}
1862
1863static const EnumConfigEntryItem folderListModes[] = {
1864 { "long", I18N_NOOP("Lon&g folder list") },
1865 { "short", I18N_NOOP("Shor&t folder list" ) }
1866};
1867static const EnumConfigEntry folderListMode = {
1868 "Geometry", "FolderList", I18N_NOOP("Folder List"),
1869 folderListModes, DIM(folderListModes), 0
1870};
1871
1872
1873static const EnumConfigEntryItem mimeTreeLocations[] = {
1874 { "top", I18N_NOOP("Abo&ve the message pane") },
1875 { "bottom", I18N_NOOP("&Below the message pane") }
1876};
1877static const EnumConfigEntry mimeTreeLocation = {
1878 "Reader", "MimeTreeLocation", I18N_NOOP("Message Structure Viewer Placement"),
1879 mimeTreeLocations, DIM(mimeTreeLocations), 1
1880};
1881
1882static 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};
1887static const EnumConfigEntry mimeTreeMode = {
1888 "Reader", "MimeTreeMode", I18N_NOOP("Message Structure Viewer"),
1889 mimeTreeModes, DIM(mimeTreeModes), 1
1890};
1891
1892
1893static 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};
1898static const EnumConfigEntry readerWindowMode = {
1899 "Geometry", "readerWindowMode", I18N_NOOP("Message Preview Pane"),
1900 readerWindowModes, DIM(readerWindowModes), 1
1901};
1902
1903AppearancePageLayoutTab::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
1942void 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
1953void 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
1963void 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
1978TQString AppearancePage::HeadersTab::helpAnchor() const {
1979 return TQString::fromLatin1("configure-appearance-headers");
1980}
1981
1982static 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};
1992static const int numDateDisplayConfig =
1993 sizeof dateDisplayConfig / sizeof *dateDisplayConfig;
1994
1995AppearancePageHeadersTab::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
2116void 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
2136void 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
2153void 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
2178void 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
2220static const BoolConfigEntry closeAfterReplyOrForward = {
2221 "Reader", "CloseAfterReplyOrForward", I18N_NOOP("Close message window after replying or forwarding"), false
2222};
2223
2224static const BoolConfigEntry showColorbarMode = {
2225 "Reader", "showColorbar", I18N_NOOP("Show HTML stat&us bar"), false
2226};
2227
2228static const BoolConfigEntry showSpamStatusMode = {
2229 "Reader", "showSpamStatus", I18N_NOOP("Show s&pam status in fancy headers"), true
2230};
2231
2232static const BoolConfigEntry showEmoticons = {
2233 "Reader", "ShowEmoticons", I18N_NOOP("Replace smileys by emoticons"), true
2234};
2235
2236static const BoolConfigEntry shrinkQuotes = {
2237 "Reader", "ShrinkQuotes", I18N_NOOP("Use smaller font for quoted text"), false
2238};
2239
2240static const BoolConfigEntry showExpandQuotesMark= {
2241 "Reader", "ShowExpandQuotesMark", I18N_NOOP("Show expand/collapse quote marks"), false
2242};
2243
2244static const BoolConfigEntry showCurrentTime = {
2245 "Reader", "ShowCurrentTime", I18N_NOOP("Show current sender time"), true
2246};
2247
2248TQString AppearancePage::ReaderTab::helpAnchor() const {
2249 return TQString::fromLatin1("configure-appearance-reader");
2250}
2251
2252AppearancePageReaderTab::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
2364void 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
2392void 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
2422void 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
2434void AppearancePage::ReaderTab::doLoadOther()
2435{
2436 const TDEConfigGroup reader( KMKernel::config(), "Reader" );
2437 loadWidget( mShowColorbarCheck, reader, showColorbarMode );
2438 loadWidget( mShowSpamStatusCheck, reader, showSpamStatusMode );
2439}
2440
2441
2442void 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
2462void 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
2474TQString AppearancePage::SystemTrayTab::helpAnchor() const {
2475 return TQString::fromLatin1("configure-appearance-systemtray");
2476}
2477
2478AppearancePageSystemTrayTab::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
2509void AppearancePage::SystemTrayTab::doLoadFromGlobalSettings() {
2510 mSystemTrayCheck->setChecked( GlobalSettings::self()->systemTrayEnabled() );
2511 mSystemTrayGroup->setButton( GlobalSettings::self()->systemTrayPolicy() );
2512 mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
2513}
2514
2515void 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
2527void 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
2539TQString ComposerPage::helpAnchor() const {
2540 return TQString::fromLatin1("configure-composer");
2541}
2542
2543ComposerPage::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
2598TQString ComposerPage::GeneralTab::helpAnchor() const {
2599 return TQString::fromLatin1("configure-composer-general");
2600}
2601
2602ComposerPageGeneralTab::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
2809void 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
2835void 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
2871void 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
2892void 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
2905void ComposerPage::GeneralTab::slotConfigureCompletionOrder( )
2906{
2907 KPIM::LdapSearch search;
2908 KPIM::CompletionOrderEditor editor( &search, this );
2909 editor.exec();
2910}
2911
2912TQString ComposerPage::PhrasesTab::helpAnchor() const {
2913 return TQString::fromLatin1("configure-composer-phrases");
2914}
2915
2916ComposerPagePhrasesTab::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
2997void 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
3008void 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
3021void ComposerPage::PhrasesTab::slotNewLanguage()
3022{
3023 NewLanguageDialog dialog( mLanguageList, parentWidget(), "New", true );
3024 if ( dialog.exec() == TQDialog::Accepted ) slotAddNewLanguage( dialog.language() );
3025}
3026
3027void 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
3043void 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
3061void 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
3072void 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
3107void 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
3124TQString ComposerPage::TemplatesTab::helpAnchor() const {
3125 return TQString::fromLatin1("configure-composer-templates");
3126}
3127
3128ComposerPageTemplatesTab::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
3140void ComposerPage::TemplatesTab::doLoadFromGlobalSettings() {
3141 mWidget->loadFromGlobal();
3142}
3143
3144void ComposerPage::TemplatesTab::save() {
3145 mWidget->saveToGlobal();
3146}
3147
3148TQString ComposerPage::CustomTemplatesTab::helpAnchor() const {
3149 return TQString::fromLatin1("configure-composer-custom-templates");
3150}
3151
3152ComposerPageCustomTemplatesTab::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
3164void ComposerPage::CustomTemplatesTab::doLoadFromGlobalSettings() {
3165 mWidget->load();
3166}
3167
3168void ComposerPage::CustomTemplatesTab::save() {
3169 mWidget->save();
3170}
3171
3172TQString ComposerPage::SubjectTab::helpAnchor() const {
3173 return TQString::fromLatin1("configure-composer-subject");
3174}
3175
3176ComposerPageSubjectTab::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
3244void 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
3251void ComposerPage::SubjectTab::save() {
3252 GlobalSettings::self()->setReplyPrefixes( mReplyListEditor->stringList() );
3253 GlobalSettings::self()->setForwardPrefixes( mForwardListEditor->stringList() );
3254}
3255
3256TQString ComposerPage::CharsetTab::helpAnchor() const {
3257 return TQString::fromLatin1("configure-composer-charset");
3258}
3259
3260ComposerPageCharsetTab::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
3295void 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
3322void 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
3338void 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
3351TQString ComposerPage::HeadersTab::helpAnchor() const {
3352 return TQString::fromLatin1("configure-composer-headers");
3353}
3354
3355ComposerPageHeadersTab::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
3442void 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
3461void 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
3471void 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
3481void 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
3490void 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
3511void 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
3545void 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
3566TQString ComposerPage::AttachmentsTab::helpAnchor() const {
3567 return TQString::fromLatin1("configure-composer-attachments");
3568}
3569
3570ComposerPageAttachmentsTab::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
3624void 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
3643void 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
3652void 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// *************************************************************
3671TQString SecurityPage::helpAnchor() const {
3672 return TQString::fromLatin1("configure-security");
3673}
3674
3675SecurityPage::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
3711void SecurityPage::installProfile( TDEConfig * profile ) {
3712 mGeneralTab->installProfile( profile );
3713 mComposerCryptoTab->installProfile( profile );
3714 mWarningTab->installProfile( profile );
3715 mSMimeTab->installProfile( profile );
3716}
3717
3718TQString SecurityPage::GeneralTab::helpAnchor() const {
3719 return TQString::fromLatin1("configure-security-reading");
3720}
3721
3722SecurityPageGeneralTab::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
3912void 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
3932void 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
3957void 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
3995TQString SecurityPage::ComposerCryptoTab::helpAnchor() const {
3996 return TQString::fromLatin1("configure-security-composing");
3997}
3998
3999SecurityPageComposerCryptoTab::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
4016void 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
4034void 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
4055void 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
4070TQString SecurityPage::WarningTab::helpAnchor() const {
4071 return TQString::fromLatin1("configure-security-warnings");
4072}
4073
4074SecurityPageWarningTab::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
4099void 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
4121void 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
4149void 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
4172void SecurityPage::WarningTab::slotReenableAllWarningsClicked() {
4173 KMessageBox::enableAllMessages();
4174 mWidget->enableAllWarningsPB->setEnabled( false );
4175}
4176
4178
4179TQString SecurityPage::SMimeTab::helpAnchor() const {
4180 return TQString::fromLatin1("configure-security-smime-validation");
4181}
4182
4183SecurityPageSMimeTab::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
4244SecurityPageSMimeTab::~SecurityPageSMimeTab()
4245{
4246}
4247
4248static 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
4254static void initializeDirmngrCheckbox( TQCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
4255 if ( entry )
4256 cb->setChecked( entry->boolValue() );
4257 else
4258 disableDirmngrWidget( cb );
4259}
4260
4261struct 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
4313void 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
4381void 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
4393void SecurityPage::SMimeTab::installProfile( TDEConfig * ) {
4394}
4395
4396static 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
4402void 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
4453bool 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
4464QCStringList SecurityPageSMimeTab::interfaces()
4465{
4466 QCStringList ifaces = DCOPObject::interfaces();
4467 ifaces += "SecurityPageSMimeTab";
4468 return ifaces;
4469}
4470
4471QCStringList SecurityPageSMimeTab::functions()
4472{
4473 // Hide our slot, just because it's simpler to do so.
4474 return DCOPObject::functions();
4475}
4476
4477Kleo::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
4497TQString SecurityPage::CryptPlugTab::helpAnchor() const {
4498 return TQString::fromLatin1("configure-security-crypto-backends");
4499}
4500
4501SecurityPageCryptPlugTab::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
4512SecurityPageCryptPlugTab::~SecurityPageCryptPlugTab()
4513{
4514
4515}
4516
4517void SecurityPage::CryptPlugTab::doLoadOther() {
4518 mBackendConfig->load();
4519}
4520
4521void SecurityPage::CryptPlugTab::save() {
4522 mBackendConfig->save();
4523}
4524
4525// *************************************************************
4526// * *
4527// * MiscPage *
4528// * *
4529// *************************************************************
4530TQString MiscPage::helpAnchor() const {
4531 return TQString::fromLatin1("configure-misc");
4532}
4533
4534MiscPage::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
4545TQString MiscPage::FolderTab::helpAnchor() const {
4546 return TQString::fromLatin1("configure-misc-folders");
4547}
4548
4549MiscPageFolderTab::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
4749void 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
4760void 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
4777void 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
4799TQString MiscPage::GroupwareTab::helpAnchor() const {
4800 return TQString::fromLatin1("configure-misc-groupware");
4801}
4802
4803MiscPageGroupwareTab::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
4988void 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
5010void 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
5078void 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
5149void 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// *************************************************************
5169AccountUpdater::AccountUpdater(ImapAccountBase *account)
5170 : TQObject()
5171{
5172 mAccount = account;
5173}
5174
5175void AccountUpdater::update()
5176{
5177 connect( mAccount, TQ_SIGNAL( connectionResult(int, const TQString&) ),
5178 this, TQ_SLOT( namespacesFetched() ) );
5179 mAccount->makeConnection();
5180}
5181
5182void 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.