summaryrefslogtreecommitdiffstats
path: root/kmail/configuredialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmail/configuredialog.cpp')
-rw-r--r--kmail/configuredialog.cpp5064
1 files changed, 5064 insertions, 0 deletions
diff --git a/kmail/configuredialog.cpp b/kmail/configuredialog.cpp
new file mode 100644
index 000000000..321a374c5
--- /dev/null
+++ b/kmail/configuredialog.cpp
@@ -0,0 +1,5064 @@
+/* -*- mode: C++; c-file-style: "gnu" -*-
+ * kmail: KDE mail client
+ * This file: Copyright (C) 2000 Espen Sand, espen@kde.org
+ * Copyright (C) 2001-2003 Marc Mutz, mutz@kde.org
+ * Contains code segments and ideas from earlier kmail dialog code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// This must be first
+#include <config.h>
+
+// my headers:
+#include "configuredialog.h"
+#include "configuredialog_p.h"
+
+#include "globalsettings.h"
+#include "replyphrases.h"
+#include "templatesconfiguration_kfg.h"
+
+// other KMail headers:
+#include "kmkernel.h"
+#include "simplestringlisteditor.h"
+#include "accountdialog.h"
+using KMail::AccountDialog;
+#include "colorlistbox.h"
+#include "kmacctseldlg.h"
+#include "messagesender.h"
+#include "kmtransport.h"
+#include "kmfoldermgr.h"
+#include <libkpimidentities/identitymanager.h>
+#include "identitylistview.h"
+using KMail::IdentityListView;
+using KMail::IdentityListViewItem;
+#include "kcursorsaver.h"
+#include "accountmanager.h"
+#include <composercryptoconfiguration.h>
+#include <warningconfiguration.h>
+#include <smimeconfiguration.h>
+#include "templatesconfiguration.h"
+#include "customtemplates.h"
+#include "folderrequester.h"
+using KMail::FolderRequester;
+#include "accountcombobox.h"
+#include "imapaccountbase.h"
+using KMail::ImapAccountBase;
+#include "folderstorage.h"
+#include "kmfolder.h"
+#include "kmmainwidget.h"
+#include "recentaddresses.h"
+using KRecentAddress::RecentAddresses;
+#include "completionordereditor.h"
+#include "ldapclient.h"
+#include "index.h"
+
+using KMail::IdentityListView;
+using KMail::IdentityListViewItem;
+#include "identitydialog.h"
+using KMail::IdentityDialog;
+
+// other kdenetwork headers:
+#include <libkpimidentities/identity.h>
+#include <kmime_util.h>
+using KMime::DateFormatter;
+#include <kleo/cryptoconfig.h>
+#include <kleo/cryptobackendfactory.h>
+#include <ui/backendconfigwidget.h>
+#include <ui/keyrequester.h>
+#include <ui/keyselectiondialog.h>
+
+// other KDE headers:
+#include <klocale.h>
+#include <kapplication.h>
+#include <kcharsets.h>
+#include <kasciistringtools.h>
+#include <kdebug.h>
+#include <knuminput.h>
+#include <kfontdialog.h>
+#include <kmessagebox.h>
+#include <kurlrequester.h>
+#include <kseparator.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kwin.h>
+#include <knotifydialog.h>
+#include <kconfig.h>
+#include <kactivelabel.h>
+#include <kcmultidialog.h>
+
+// Qt headers:
+#include <qvalidator.h>
+#include <qwhatsthis.h>
+#include <qvgroupbox.h>
+#include <qvbox.h>
+#include <qvbuttongroup.h>
+#include <qhbuttongroup.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+#include <qtextcodec.h>
+#include <qheader.h>
+#include <qpopupmenu.h>
+#include <qradiobutton.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qwidgetstack.h>
+
+// other headers:
+#include <assert.h>
+#include <stdlib.h>
+
+#ifndef _PATH_SENDMAIL
+#define _PATH_SENDMAIL "/usr/sbin/sendmail"
+#endif
+
+#ifdef DIM
+#undef DIM
+#endif
+#define DIM(x) sizeof(x) / sizeof(*x)
+
+namespace {
+
+ struct EnumConfigEntryItem {
+ const char * key; // config key value, as appears in config file
+ const char * desc; // description, to be i18n()ized
+ };
+ struct EnumConfigEntry {
+ const char * group;
+ const char * key;
+ const char * desc;
+ const EnumConfigEntryItem * items;
+ int numItems;
+ int defaultItem;
+ };
+ struct BoolConfigEntry {
+ const char * group;
+ const char * key;
+ const char * desc;
+ bool defaultValue;
+ };
+
+ static const char * lockedDownWarning =
+ I18N_NOOP("<qt><p>This setting has been fixed by your administrator.</p>"
+ "<p>If you think this is an error, please contact him.</p></qt>");
+
+ void checkLockDown( QWidget * w, const KConfigBase & c, const char * key ) {
+ if ( c.entryIsImmutable( key ) ) {
+ w->setEnabled( false );
+ QToolTip::add( w, i18n( lockedDownWarning ) );
+ } else {
+ QToolTip::remove( w );
+ }
+ }
+
+ void populateButtonGroup( QButtonGroup * g, const EnumConfigEntry & e ) {
+ g->setTitle( i18n( e.desc ) );
+ g->layout()->setSpacing( KDialog::spacingHint() );
+ for ( int i = 0 ; i < e.numItems ; ++i )
+ g->insert( new QRadioButton( i18n( e.items[i].desc ), g ), i );
+ }
+
+ void populateCheckBox( QCheckBox * b, const BoolConfigEntry & e ) {
+ b->setText( i18n( e.desc ) );
+ }
+
+ void loadWidget( QCheckBox * b, const KConfigBase & c, const BoolConfigEntry & e ) {
+ Q_ASSERT( c.group() == e.group );
+ checkLockDown( b, c, e.key );
+ b->setChecked( c.readBoolEntry( e.key, e.defaultValue ) );
+ }
+
+ void loadWidget( QButtonGroup * g, const KConfigBase & c, const EnumConfigEntry & e ) {
+ Q_ASSERT( c.group() == e.group );
+ Q_ASSERT( g->count() == e.numItems );
+ checkLockDown( g, c, e.key );
+ const QString s = c.readEntry( e.key, e.items[e.defaultItem].key );
+ for ( int i = 0 ; i < e.numItems ; ++i )
+ if ( s == e.items[i].key ) {
+ g->setButton( i );
+ return;
+ }
+ g->setButton( e.defaultItem );
+ }
+
+ void saveCheckBox( QCheckBox * b, KConfigBase & c, const BoolConfigEntry & e ) {
+ Q_ASSERT( c.group() == e.group );
+ c.writeEntry( e.key, b->isChecked() );
+ }
+
+ void saveButtonGroup( QButtonGroup * g, KConfigBase & c, const EnumConfigEntry & e ) {
+ Q_ASSERT( c.group() == e.group );
+ Q_ASSERT( g->count() == e.numItems );
+ c.writeEntry( e.key, e.items[ g->id( g->selected() ) ].key );
+ }
+
+ template <typename T_Widget, typename T_Entry>
+ inline void loadProfile( T_Widget * g, const KConfigBase & c, const T_Entry & e ) {
+ if ( c.hasKey( e.key ) )
+ loadWidget( g, c, e );
+ }
+}
+
+
+ConfigureDialog::ConfigureDialog( QWidget *parent, const char *name, bool modal )
+ : KCMultiDialog( KDialogBase::IconList, KGuiItem( i18n( "&Load Profile..." ) ),
+ KGuiItem(), User2, i18n( "Configure" ), parent, name, modal )
+ , mProfileDialog( 0 )
+{
+ KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
+ showButton( User1, true );
+
+ addModule ( "kmail_config_identity", false );
+ addModule ( "kmail_config_accounts", false );
+ addModule ( "kmail_config_appearance", false );
+ addModule ( "kmail_config_composer", false );
+ addModule ( "kmail_config_security", false );
+ addModule ( "kmail_config_misc", false );
+
+ // We store the size of the dialog on hide, because otherwise
+ // the KCMultiDialog starts with the size of the first kcm, not
+ // the largest one. This way at least after the first showing of
+ // the largest kcm the size is kept.
+ KConfigGroup geometry( KMKernel::config(), "Geometry" );
+ int width = geometry.readNumEntry( "ConfigureDialogWidth" );
+ int height = geometry.readNumEntry( "ConfigureDialogHeight" );
+ if ( width != 0 && height != 0 ) {
+ setMinimumSize( width, height );
+ }
+
+}
+
+void ConfigureDialog::hideEvent( QHideEvent *ev ) {
+ KConfigGroup geometry( KMKernel::config(), "Geometry" );
+ geometry.writeEntry( "ConfigureDialogWidth", width() );
+ geometry.writeEntry( "ConfigureDialogHeight",height() );
+ KDialogBase::hideEvent( ev );
+}
+
+ConfigureDialog::~ConfigureDialog() {
+}
+
+void ConfigureDialog::slotApply() {
+ GlobalSettings::self()->writeConfig();
+ KCMultiDialog::slotApply();
+}
+
+void ConfigureDialog::slotOk() {
+ GlobalSettings::self()->writeConfig();
+ KCMultiDialog::slotOk();
+}
+
+void ConfigureDialog::slotUser2() {
+ if ( mProfileDialog ) {
+ mProfileDialog->raise();
+ return;
+ }
+ mProfileDialog = new ProfileDialog( this, "mProfileDialog" );
+ connect( mProfileDialog, SIGNAL(profileSelected(KConfig*)),
+ this, SIGNAL(installProfile(KConfig*)) );
+ mProfileDialog->show();
+}
+
+// *************************************************************
+// * *
+// * IdentityPage *
+// * *
+// *************************************************************
+QString IdentityPage::helpAnchor() const {
+ return QString::fromLatin1("configure-identity");
+}
+
+IdentityPage::IdentityPage( QWidget * parent, const char * name )
+ : ConfigModule( parent, name ),
+ mIdentityDialog( 0 )
+{
+ QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() );
+
+ mIdentityList = new IdentityListView( this );
+ connect( mIdentityList, SIGNAL(selectionChanged()),
+ SLOT(slotIdentitySelectionChanged()) );
+ connect( mIdentityList, SIGNAL(itemRenamed(QListViewItem*,const QString&,int)),
+ SLOT(slotRenameIdentity(QListViewItem*,const QString&,int)) );
+ connect( mIdentityList, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)),
+ SLOT(slotModifyIdentity()) );
+ connect( mIdentityList, SIGNAL(contextMenu(KListView*,QListViewItem*,const QPoint&)),
+ SLOT(slotContextMenu(KListView*,QListViewItem*,const QPoint&)) );
+ // ### connect dragged(...), ...
+
+ hlay->addWidget( mIdentityList, 1 );
+
+ QVBoxLayout * vlay = new QVBoxLayout( hlay ); // inherits spacing
+
+ QPushButton * button = new QPushButton( i18n("&Add..."), this );
+ mModifyButton = new QPushButton( i18n("&Modify..."), this );
+ mRenameButton = new QPushButton( i18n("&Rename"), this );
+ mRemoveButton = new QPushButton( i18n("Remo&ve"), this );
+ mSetAsDefaultButton = new QPushButton( i18n("Set as &Default"), this );
+ button->setAutoDefault( false );
+ mModifyButton->setAutoDefault( false );
+ mModifyButton->setEnabled( false );
+ mRenameButton->setAutoDefault( false );
+ mRenameButton->setEnabled( false );
+ mRemoveButton->setAutoDefault( false );
+ mRemoveButton->setEnabled( false );
+ mSetAsDefaultButton->setAutoDefault( false );
+ mSetAsDefaultButton->setEnabled( false );
+ connect( button, SIGNAL(clicked()),
+ this, SLOT(slotNewIdentity()) );
+ connect( mModifyButton, SIGNAL(clicked()),
+ this, SLOT(slotModifyIdentity()) );
+ connect( mRenameButton, SIGNAL(clicked()),
+ this, SLOT(slotRenameIdentity()) );
+ connect( mRemoveButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveIdentity()) );
+ connect( mSetAsDefaultButton, SIGNAL(clicked()),
+ this, SLOT(slotSetAsDefault()) );
+ vlay->addWidget( button );
+ vlay->addWidget( mModifyButton );
+ vlay->addWidget( mRenameButton );
+ vlay->addWidget( mRemoveButton );
+ vlay->addWidget( mSetAsDefaultButton );
+ vlay->addStretch( 1 );
+ load();
+}
+
+void IdentityPage::load()
+{
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ mOldNumberOfIdentities = im->shadowIdentities().count();
+ // Fill the list:
+ mIdentityList->clear();
+ QListViewItem * item = 0;
+ for ( KPIM::IdentityManager::Iterator it = im->modifyBegin() ; it != im->modifyEnd() ; ++it )
+ item = new IdentityListViewItem( mIdentityList, item, *it );
+ mIdentityList->setSelected( mIdentityList->currentItem(), true );
+}
+
+void IdentityPage::save() {
+ assert( !mIdentityDialog );
+
+ kmkernel->identityManager()->sort();
+ kmkernel->identityManager()->commit();
+
+ if( mOldNumberOfIdentities < 2 && mIdentityList->childCount() > 1 ) {
+ // have more than one identity, so better show the combo in the
+ // composer now:
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+ int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
+ showHeaders |= HDR_IDENTITY;
+ composer.writeEntry( "headers", showHeaders );
+ }
+ // and now the reverse
+ if( mOldNumberOfIdentities > 1 && mIdentityList->childCount() < 2 ) {
+ // have only one identity, so remove the combo in the composer:
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+ int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD );
+ showHeaders &= ~HDR_IDENTITY;
+ composer.writeEntry( "headers", showHeaders );
+ }
+}
+
+void IdentityPage::slotNewIdentity()
+{
+ assert( !mIdentityDialog );
+
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ NewIdentityDialog dialog( im->shadowIdentities(), this, "new", true );
+
+ if( dialog.exec() == QDialog::Accepted ) {
+ QString identityName = dialog.identityName().stripWhiteSpace();
+ assert( !identityName.isEmpty() );
+
+ //
+ // Construct a new Identity:
+ //
+ switch ( dialog.duplicateMode() ) {
+ case NewIdentityDialog::ExistingEntry:
+ {
+ KPIM::Identity & dupThis = im->modifyIdentityForName( dialog.duplicateIdentity() );
+ im->newFromExisting( dupThis, identityName );
+ break;
+ }
+ case NewIdentityDialog::ControlCenter:
+ im->newFromControlCenter( identityName );
+ break;
+ case NewIdentityDialog::Empty:
+ im->newFromScratch( identityName );
+ default: ;
+ }
+
+ //
+ // Insert into listview:
+ //
+ KPIM::Identity & newIdent = im->modifyIdentityForName( identityName );
+ QListViewItem * item = mIdentityList->selectedItem();
+ if ( item )
+ item = item->itemAbove();
+ mIdentityList->setSelected( new IdentityListViewItem( mIdentityList,
+ /*after*/ item,
+ newIdent ), true );
+ slotModifyIdentity();
+ }
+}
+
+void IdentityPage::slotModifyIdentity() {
+ assert( !mIdentityDialog );
+
+ IdentityListViewItem * item =
+ dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
+ if ( !item ) return;
+
+ mIdentityDialog = new IdentityDialog( this );
+ mIdentityDialog->setIdentity( item->identity() );
+
+ // Hmm, an unmodal dialog would be nicer, but a modal one is easier ;-)
+ if ( mIdentityDialog->exec() == QDialog::Accepted ) {
+ mIdentityDialog->updateIdentity( item->identity() );
+ item->redisplay();
+ emit changed(true);
+ }
+
+ delete mIdentityDialog;
+ mIdentityDialog = 0;
+}
+
+void IdentityPage::slotRemoveIdentity()
+{
+ assert( !mIdentityDialog );
+
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ kdFatal( im->shadowIdentities().count() < 2 )
+ << "Attempted to remove the last identity!" << endl;
+
+ IdentityListViewItem * item =
+ dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
+ if ( !item ) return;
+
+ QString msg = i18n("<qt>Do you really want to remove the identity named "
+ "<b>%1</b>?</qt>").arg( item->identity().identityName() );
+ if( KMessageBox::warningContinueCancel( this, msg, i18n("Remove Identity"),
+ KGuiItem(i18n("&Remove"),"editdelete") ) == KMessageBox::Continue )
+ if ( im->removeIdentity( item->identity().identityName() ) ) {
+ delete item;
+ mIdentityList->setSelected( mIdentityList->currentItem(), true );
+ refreshList();
+ }
+}
+
+void IdentityPage::slotRenameIdentity() {
+ assert( !mIdentityDialog );
+
+ QListViewItem * item = mIdentityList->selectedItem();
+ if ( !item ) return;
+
+ mIdentityList->rename( item, 0 );
+}
+
+void IdentityPage::slotRenameIdentity( QListViewItem * i,
+ const QString & s, int col ) {
+ assert( col == 0 );
+ Q_UNUSED( col );
+
+ IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
+ if ( !item ) return;
+
+ QString newName = s.stripWhiteSpace();
+ if ( !newName.isEmpty() &&
+ !kmkernel->identityManager()->shadowIdentities().contains( newName ) ) {
+ KPIM::Identity & ident = item->identity();
+ ident.setIdentityName( newName );
+ emit changed(true);
+ }
+ item->redisplay();
+}
+
+void IdentityPage::slotContextMenu( KListView *, QListViewItem * i,
+ const QPoint & pos ) {
+ IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i );
+
+ QPopupMenu * menu = new QPopupMenu( this );
+ menu->insertItem( i18n("Add..."), this, SLOT(slotNewIdentity()) );
+ if ( item ) {
+ menu->insertItem( i18n("Modify..."), this, SLOT(slotModifyIdentity()) );
+ if ( mIdentityList->childCount() > 1 )
+ menu->insertItem( i18n("Remove"), this, SLOT(slotRemoveIdentity()) );
+ if ( !item->identity().isDefault() )
+ menu->insertItem( i18n("Set as Default"), this, SLOT(slotSetAsDefault()) );
+ }
+ menu->exec( pos );
+ delete menu;
+}
+
+
+void IdentityPage::slotSetAsDefault() {
+ assert( !mIdentityDialog );
+
+ IdentityListViewItem * item =
+ dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
+ if ( !item ) return;
+
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ im->setAsDefault( item->identity().identityName() );
+ refreshList();
+}
+
+void IdentityPage::refreshList() {
+ for ( QListViewItemIterator it( mIdentityList ) ; it.current() ; ++it ) {
+ IdentityListViewItem * item =
+ dynamic_cast<IdentityListViewItem*>(it.current());
+ if ( item )
+ item->redisplay();
+ }
+ emit changed(true);
+}
+
+void IdentityPage::slotIdentitySelectionChanged()
+{
+ IdentityListViewItem *item =
+ dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() );
+
+ mRemoveButton->setEnabled( item && mIdentityList->childCount() > 1 );
+ mModifyButton->setEnabled( item );
+ mRenameButton->setEnabled( item );
+ mSetAsDefaultButton->setEnabled( item && !item->identity().isDefault() );
+}
+
+void IdentityPage::slotUpdateTransportCombo( const QStringList & sl )
+{
+ if ( mIdentityDialog ) mIdentityDialog->slotUpdateTransportCombo( sl );
+}
+
+
+
+// *************************************************************
+// * *
+// * AccountsPage *
+// * *
+// *************************************************************
+QString AccountsPage::helpAnchor() const {
+ return QString::fromLatin1("configure-accounts");
+}
+
+AccountsPage::AccountsPage( QWidget * parent, const char * name )
+ : ConfigModuleWithTabs( parent, name )
+{
+ //
+ // "Receiving" tab:
+ //
+ mReceivingTab = new ReceivingTab();
+ addTab( mReceivingTab, i18n( "&Receiving" ) );
+ connect( mReceivingTab, SIGNAL(accountListChanged(const QStringList &)),
+ this, SIGNAL(accountListChanged(const QStringList &)) );
+
+ //
+ // "Sending" tab:
+ //
+ mSendingTab = new SendingTab();
+ addTab( mSendingTab, i18n( "&Sending" ) );
+ connect( mSendingTab, SIGNAL(transportListChanged(const QStringList&)),
+ this, SIGNAL(transportListChanged(const QStringList&)) );
+
+ load();
+}
+
+QString AccountsPage::SendingTab::helpAnchor() const {
+ return QString::fromLatin1("configure-accounts-sending");
+}
+
+AccountsPageSendingTab::AccountsPageSendingTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ mTransportInfoList.setAutoDelete( true );
+ // temp. vars:
+ QVBoxLayout *vlay;
+ QVBoxLayout *btn_vlay;
+ QHBoxLayout *hlay;
+ QGridLayout *glay;
+ QPushButton *button;
+ QGroupBox *group;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+ // label: zero stretch ### FIXME more
+ vlay->addWidget( new QLabel( i18n("Outgoing accounts (add at least one):"), this ) );
+
+ // hbox layout: stretch 10, spacing inherited from vlay
+ hlay = new QHBoxLayout();
+ vlay->addLayout( hlay, 10 ); // high stretch b/c of the groupbox's sizeHint
+
+ // transport list: left widget in hlay; stretch 1
+ // ### FIXME: allow inline renaming of the account:
+ mTransportList = new ListView( this, "transportList", 5 );
+ mTransportList->addColumn( i18n("Name") );
+ mTransportList->addColumn( i18n("Type") );
+ mTransportList->setAllColumnsShowFocus( true );
+ mTransportList->setSorting( -1 );
+ connect( mTransportList, SIGNAL(selectionChanged()),
+ this, SLOT(slotTransportSelected()) );
+ connect( mTransportList, SIGNAL(doubleClicked( QListViewItem *)),
+ this, SLOT(slotModifySelectedTransport()) );
+ hlay->addWidget( mTransportList, 1 );
+
+ // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
+ btn_vlay = new QVBoxLayout( hlay );
+
+ // "add..." button: stretch 0
+ button = new QPushButton( i18n("A&dd..."), this );
+ button->setAutoDefault( false );
+ connect( button, SIGNAL(clicked()),
+ this, SLOT(slotAddTransport()) );
+ btn_vlay->addWidget( button );
+
+ // "modify..." button: stretch 0
+ mModifyTransportButton = new QPushButton( i18n("&Modify..."), this );
+ mModifyTransportButton->setAutoDefault( false );
+ mModifyTransportButton->setEnabled( false ); // b/c no item is selected yet
+ connect( mModifyTransportButton, SIGNAL(clicked()),
+ this, SLOT(slotModifySelectedTransport()) );
+ btn_vlay->addWidget( mModifyTransportButton );
+
+ // "remove" button: stretch 0
+ mRemoveTransportButton = new QPushButton( i18n("R&emove"), this );
+ mRemoveTransportButton->setAutoDefault( false );
+ mRemoveTransportButton->setEnabled( false ); // b/c no item is selected yet
+ connect( mRemoveTransportButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveSelectedTransport()) );
+ btn_vlay->addWidget( mRemoveTransportButton );
+
+ mSetDefaultTransportButton = new QPushButton( i18n("Set Default"), this );
+ mSetDefaultTransportButton->setAutoDefault( false );
+ mSetDefaultTransportButton->setEnabled( false );
+ connect ( mSetDefaultTransportButton, SIGNAL(clicked()),
+ this, SLOT(slotSetDefaultTransport()) );
+ btn_vlay->addWidget( mSetDefaultTransportButton );
+ btn_vlay->addStretch( 1 ); // spacer
+
+ // "Common options" groupbox:
+ group = new QGroupBox( 0, Qt::Vertical,
+ i18n("Common Options"), this );
+ vlay->addWidget(group);
+
+ // a grid layout for the contents of the "common options" group box
+ glay = new QGridLayout( group->layout(), 5, 3, KDialog::spacingHint() );
+ glay->setColStretch( 2, 10 );
+
+ // "confirm before send" check box:
+ mConfirmSendCheck = new QCheckBox( i18n("Confirm &before send"), group );
+ glay->addMultiCellWidget( mConfirmSendCheck, 0, 0, 0, 1 );
+ connect( mConfirmSendCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "send on check" combo:
+ mSendOnCheckCombo = new QComboBox( false, group );
+ mSendOnCheckCombo->insertStringList( QStringList()
+ << i18n("Never Automatically")
+ << i18n("On Manual Mail Checks")
+ << i18n("On All Mail Checks") );
+ glay->addWidget( mSendOnCheckCombo, 1, 1 );
+ connect( mSendOnCheckCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "default send method" combo:
+ mSendMethodCombo = new QComboBox( false, group );
+ mSendMethodCombo->insertStringList( QStringList()
+ << i18n("Send Now")
+ << i18n("Send Later") );
+ glay->addWidget( mSendMethodCombo, 2, 1 );
+ connect( mSendMethodCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+
+ // "message property" combo:
+ // ### FIXME: remove completely?
+ mMessagePropertyCombo = new QComboBox( false, group );
+ mMessagePropertyCombo->insertStringList( QStringList()
+ << i18n("Allow 8-bit")
+ << i18n("MIME Compliant (Quoted Printable)") );
+ glay->addWidget( mMessagePropertyCombo, 3, 1 );
+ connect( mMessagePropertyCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "default domain" input field:
+ mDefaultDomainEdit = new KLineEdit( group );
+ glay->addMultiCellWidget( mDefaultDomainEdit, 4, 4, 1, 2 );
+ connect( mDefaultDomainEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // labels:
+ QLabel *l = new QLabel( mSendOnCheckCombo, /*buddy*/
+ i18n("Send &messages in outbox folder:"), group );
+ glay->addWidget( l, 1, 0 );
+
+ QString msg = i18n( GlobalSettings::self()->sendOnCheckItem()->whatsThis().utf8() );
+ QWhatsThis::add( l, msg );
+ QWhatsThis::add( mSendOnCheckCombo, msg );
+
+ glay->addWidget( new QLabel( mSendMethodCombo, /*buddy*/
+ i18n("Defa&ult send method:"), group ), 2, 0 );
+ glay->addWidget( new QLabel( mMessagePropertyCombo, /*buddy*/
+ i18n("Message &property:"), group ), 3, 0 );
+ l = new QLabel( mDefaultDomainEdit, /*buddy*/
+ i18n("Defaul&t domain:"), group );
+ glay->addWidget( l, 4, 0 );
+
+ // and now: add QWhatsThis:
+ msg = i18n( "<qt><p>The default domain is used to complete email "
+ "addresses that only consist of the user's name."
+ "</p></qt>" );
+ QWhatsThis::add( l, msg );
+ QWhatsThis::add( mDefaultDomainEdit, msg );
+}
+
+
+void AccountsPage::SendingTab::slotTransportSelected()
+{
+ QListViewItem *cur = mTransportList->selectedItem();
+ mModifyTransportButton->setEnabled( cur );
+ mRemoveTransportButton->setEnabled( cur );
+ mSetDefaultTransportButton->setEnabled( cur );
+}
+
+// adds a number to @p name to make the name unique
+static inline QString uniqueName( const QStringList & list,
+ const QString & name )
+{
+ int suffix = 1;
+ QString result = name;
+ while ( list.find( result ) != list.end() ) {
+ result = i18n("%1: name; %2: number appended to it to make it unique "
+ "among a list of names", "%1 %2")
+ .arg( name ).arg( suffix );
+ suffix++;
+ }
+ return result;
+}
+
+void AccountsPage::SendingTab::slotSetDefaultTransport()
+{
+ QListViewItem *item = mTransportList->selectedItem();
+ if ( !item ) return;
+
+ KMTransportInfo ti;
+
+ QListViewItemIterator it( mTransportList );
+ for ( ; it.current(); ++it ) {
+ ti.readConfig( KMTransportInfo::findTransport( it.current()->text(0) ));
+ if ( ti.type != "sendmail" ) {
+ it.current()->setText( 1, "smtp" );
+ } else {
+ it.current()->setText( 1, "sendmail" );
+ }
+ }
+
+ if ( item->text(1) != "sendmail" ) {
+ item->setText( 1, i18n( "smtp (Default)" ));
+ } else {
+ item->setText( 1, i18n( "sendmail (Default)" ));
+ }
+
+ GlobalSettings::self()->setDefaultTransport( item->text(0) );
+
+}
+
+void AccountsPage::SendingTab::slotAddTransport()
+{
+ int transportType;
+
+ { // limit scope of selDialog
+ KMTransportSelDlg selDialog( this );
+ if ( selDialog.exec() != QDialog::Accepted ) return;
+ transportType = selDialog.selected();
+ }
+
+ KMTransportInfo *transportInfo = new KMTransportInfo();
+ switch ( transportType ) {
+ case 0: // smtp
+ transportInfo->type = QString::fromLatin1("smtp");
+ break;
+ case 1: // sendmail
+ transportInfo->type = QString::fromLatin1("sendmail");
+ transportInfo->name = i18n("Sendmail");
+ transportInfo->host = _PATH_SENDMAIL; // ### FIXME: use const, not #define
+ break;
+ default:
+ assert( 0 );
+ }
+
+ KMTransportDialog dialog( i18n("Add Transport"), transportInfo, this );
+
+ // create list of names:
+ // ### move behind dialog.exec()?
+ QStringList transportNames;
+ QPtrListIterator<KMTransportInfo> it( mTransportInfoList );
+ for ( it.toFirst() ; it.current() ; ++it )
+ transportNames << (*it)->name;
+
+ if( dialog.exec() != QDialog::Accepted ) {
+ delete transportInfo;
+ return;
+ }
+
+ // disambiguate the name by appending a number:
+ // ### FIXME: don't allow this error to happen in the first place!
+ transportInfo->name = uniqueName( transportNames, transportInfo->name );
+ // append to names and transportinfo lists:
+ transportNames << transportInfo->name;
+ mTransportInfoList.append( transportInfo );
+
+ // append to listview:
+ // ### FIXME: insert before the selected item, append on empty selection
+ QListViewItem *lastItem = mTransportList->firstChild();
+ QString typeDisplayName;
+ if ( lastItem ) {
+ typeDisplayName = transportInfo->type;
+ } else {
+ typeDisplayName = i18n("%1: type of transport. Result used in "
+ "Configure->Accounts->Sending listview, \"type\" "
+ "column, first row, to indicate that this is the "
+ "default transport", "%1 (Default)")
+ .arg( transportInfo->type );
+ GlobalSettings::self()->setDefaultTransport( transportInfo->name );
+ }
+ (void) new QListViewItem( mTransportList, lastItem, transportInfo->name,
+ typeDisplayName );
+
+ // notify anyone who cares:
+ emit transportListChanged( transportNames );
+ emit changed( true );
+}
+
+void AccountsPage::SendingTab::slotModifySelectedTransport()
+{
+ QListViewItem *item = mTransportList->selectedItem();
+ if ( !item ) return;
+
+ const QString& originalTransport = item->text(0);
+
+ QPtrListIterator<KMTransportInfo> it( mTransportInfoList );
+ for ( it.toFirst() ; it.current() ; ++it )
+ if ( (*it)->name == item->text(0) ) break;
+ if ( !it.current() ) return;
+
+ KMTransportDialog dialog( i18n("Modify Transport"), (*it), this );
+
+ if ( dialog.exec() != QDialog::Accepted ) return;
+
+ // create the list of names of transports, but leave out the current
+ // item:
+ QStringList transportNames;
+ QPtrListIterator<KMTransportInfo> jt( mTransportInfoList );
+ int entryLocation = -1;
+ for ( jt.toFirst() ; jt.current() ; ++jt )
+ if ( jt != it )
+ transportNames << (*jt)->name;
+ else
+ entryLocation = transportNames.count();
+ assert( entryLocation >= 0 );
+
+ // make the new name unique by appending a high enough number:
+ (*it)->name = uniqueName( transportNames, (*it)->name );
+ // change the list item to the new name
+ item->setText( 0, (*it)->name );
+ // and insert the new name at the position of the old in the list of
+ // strings; then broadcast the new list:
+ transportNames.insert( transportNames.at( entryLocation ), (*it)->name );
+ const QString& newTransportName = (*it)->name;
+
+ QStringList changedIdents;
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
+ if ( originalTransport == (*it).transport() ) {
+ (*it).setTransport( newTransportName );
+ changedIdents += (*it).identityName();
+ }
+ }
+
+ if ( !changedIdents.isEmpty() ) {
+ QString information = i18n( "This identity has been changed to use the modified transport:",
+ "These %n identities have been changed to use the modified transport:",
+ changedIdents.count() );
+ KMessageBox::informationList( this, information, changedIdents );
+ }
+
+ emit transportListChanged( transportNames );
+ emit changed( true );
+}
+
+void AccountsPage::SendingTab::slotRemoveSelectedTransport()
+{
+ QListViewItem *item = mTransportList->selectedItem();
+ if ( !item ) return;
+
+ QStringList changedIdents;
+ KPIM::IdentityManager * im = kmkernel->identityManager();
+ for ( KPIM::IdentityManager::Iterator it = im->modifyBegin(); it != im->modifyEnd(); ++it ) {
+ if ( item->text( 0 ) == (*it).transport() ) {
+ (*it).setTransport( QString::null );
+ changedIdents += (*it).identityName();
+ }
+ }
+
+ // if the deleted transport is the currently used transport reset it to default
+ const QString& currentTransport = GlobalSettings::self()->currentTransport();
+ if ( item->text( 0 ) == currentTransport ) {
+ GlobalSettings::self()->setCurrentTransport( QString::null );
+ }
+
+ if ( !changedIdents.isEmpty() ) {
+ QString information = i18n( "This identity has been changed to use the default transport:",
+ "These %n identities have been changed to use the default transport:",
+ changedIdents.count() );
+ KMessageBox::informationList( this, information, changedIdents );
+ }
+
+ QPtrListIterator<KMTransportInfo> it( mTransportInfoList );
+ for ( it.toFirst() ; it.current() ; ++it )
+ if ( (*it)->name == item->text(0) ) break;
+ if ( !it.current() ) return;
+
+ KMTransportInfo ti;
+
+ QListViewItem *newCurrent = item->itemBelow();
+ if ( !newCurrent ) newCurrent = item->itemAbove();
+ //mTransportList->removeItem( item );
+ if ( newCurrent ) {
+ mTransportList->setCurrentItem( newCurrent );
+ mTransportList->setSelected( newCurrent, true );
+ GlobalSettings::self()->setDefaultTransport( newCurrent->text(0) );
+ ti.readConfig( KMTransportInfo::findTransport( newCurrent->text(0) ));
+ if ( item->text( 0 ) == GlobalSettings::self()->defaultTransport() ) {
+ if ( ti.type != "sendmail" ) {
+ newCurrent->setText( 1, i18n("smtp (Default)") );
+ } else {
+ newCurrent->setText( 1, i18n("sendmail (Default)" ));
+ }
+ }
+ } else {
+ GlobalSettings::self()->setDefaultTransport( QString::null );
+ }
+
+ delete item;
+ mTransportInfoList.remove( it );
+
+ QStringList transportNames;
+ for ( it.toFirst() ; it.current() ; ++it )
+ transportNames << (*it)->name;
+ emit transportListChanged( transportNames );
+ emit changed( true );
+}
+
+void AccountsPage::SendingTab::doLoadFromGlobalSettings() {
+ mSendOnCheckCombo->setCurrentItem( GlobalSettings::self()->sendOnCheck() );
+}
+
+void AccountsPage::SendingTab::doLoadOther() {
+ KConfigGroup general( KMKernel::config(), "General");
+ KConfigGroup composer( KMKernel::config(), "Composer");
+
+ int numTransports = general.readNumEntry("transports", 0);
+
+ QListViewItem *top = 0;
+ mTransportInfoList.clear();
+ mTransportList->clear();
+ QStringList transportNames;
+ for ( int i = 1 ; i <= numTransports ; i++ ) {
+ KMTransportInfo *ti = new KMTransportInfo();
+ ti->readConfig(i);
+ mTransportInfoList.append( ti );
+ transportNames << ti->name;
+ top = new QListViewItem( mTransportList, top, ti->name, ti->type );
+ }
+ emit transportListChanged( transportNames );
+
+ const QString &defaultTransport = GlobalSettings::self()->defaultTransport();
+
+ QListViewItemIterator it( mTransportList );
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->text(0) == defaultTransport ) {
+ if ( it.current()->text(1) != "sendmail" ) {
+ it.current()->setText( 1, i18n( "smtp (Default)" ));
+ } else {
+ it.current()->setText( 1, i18n( "sendmail (Default)" ));
+ }
+ } else {
+ if ( it.current()->text(1) != "sendmail" ) {
+ it.current()->setText( 1, "smtp" );
+ } else {
+ it.current()->setText( 1, "sendmail" );
+ }
+ }
+ }
+
+ mSendMethodCombo->setCurrentItem(
+ kmkernel->msgSender()->sendImmediate() ? 0 : 1 );
+ mMessagePropertyCombo->setCurrentItem(
+ kmkernel->msgSender()->sendQuotedPrintable() ? 1 : 0 );
+
+ mConfirmSendCheck->setChecked( composer.readBoolEntry( "confirm-before-send",
+ false ) );
+ QString str = general.readEntry( "Default domain" );
+ if( str.isEmpty() )
+ {
+ //### FIXME: Use the global convenience function instead of the homebrewed
+ // solution once we can rely on HEAD kdelibs.
+ //str = KGlobal::hostname(); ???????
+ char buffer[256];
+ if ( !gethostname( buffer, 255 ) )
+ // buffer need not be NUL-terminated if it has full length
+ buffer[255] = 0;
+ else
+ buffer[0] = 0;
+ str = QString::fromLatin1( *buffer ? buffer : "localhost" );
+ }
+ mDefaultDomainEdit->setText( str );
+}
+
+void AccountsPage::SendingTab::save() {
+ KConfigGroup general( KMKernel::config(), "General" );
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ // Save transports:
+ general.writeEntry( "transports", mTransportInfoList.count() );
+ QPtrListIterator<KMTransportInfo> it( mTransportInfoList );
+ for ( int i = 1 ; it.current() ; ++it, ++i )
+ (*it)->writeConfig(i);
+
+ // Save common options:
+ GlobalSettings::self()->setSendOnCheck( mSendOnCheckCombo->currentItem() );
+ kmkernel->msgSender()->setSendImmediate(
+ mSendMethodCombo->currentItem() == 0 );
+ kmkernel->msgSender()->setSendQuotedPrintable(
+ mMessagePropertyCombo->currentItem() == 1 );
+ kmkernel->msgSender()->writeConfig( false ); // don't sync
+ composer.writeEntry("confirm-before-send", mConfirmSendCheck->isChecked() );
+ general.writeEntry( "Default domain", mDefaultDomainEdit->text() );
+}
+
+QString AccountsPage::ReceivingTab::helpAnchor() const {
+ return QString::fromLatin1("configure-accounts-receiving");
+}
+
+AccountsPageReceivingTab::AccountsPageReceivingTab( QWidget * parent, const char * name )
+ : ConfigModuleTab ( parent, name )
+{
+ // temp. vars:
+ QVBoxLayout *vlay;
+ QVBoxLayout *btn_vlay;
+ QHBoxLayout *hlay;
+ QPushButton *button;
+ QGroupBox *group;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // label: zero stretch
+ vlay->addWidget( new QLabel( i18n("Incoming accounts (add at least one):"), this ) );
+
+ // hbox layout: stretch 10, spacing inherited from vlay
+ hlay = new QHBoxLayout();
+ vlay->addLayout( hlay, 10 ); // high stretch to suppress groupbox's growing
+
+ // account list: left widget in hlay; stretch 1
+ mAccountList = new ListView( this, "accountList", 5 );
+ mAccountList->addColumn( i18n("Name") );
+ mAccountList->addColumn( i18n("Type") );
+ mAccountList->addColumn( i18n("Folder") );
+ mAccountList->setAllColumnsShowFocus( true );
+ mAccountList->setSorting( -1 );
+ connect( mAccountList, SIGNAL(selectionChanged()),
+ this, SLOT(slotAccountSelected()) );
+ connect( mAccountList, SIGNAL(doubleClicked( QListViewItem *)),
+ this, SLOT(slotModifySelectedAccount()) );
+ hlay->addWidget( mAccountList, 1 );
+
+ // a vbox layout for the buttons: zero stretch, spacing inherited from hlay
+ btn_vlay = new QVBoxLayout( hlay );
+
+ // "add..." button: stretch 0
+ button = new QPushButton( i18n("A&dd..."), this );
+ button->setAutoDefault( false );
+ connect( button, SIGNAL(clicked()),
+ this, SLOT(slotAddAccount()) );
+ btn_vlay->addWidget( button );
+
+ // "modify..." button: stretch 0
+ mModifyAccountButton = new QPushButton( i18n("&Modify..."), this );
+ mModifyAccountButton->setAutoDefault( false );
+ mModifyAccountButton->setEnabled( false ); // b/c no item is selected yet
+ connect( mModifyAccountButton, SIGNAL(clicked()),
+ this, SLOT(slotModifySelectedAccount()) );
+ btn_vlay->addWidget( mModifyAccountButton );
+
+ // "remove..." button: stretch 0
+ mRemoveAccountButton = new QPushButton( i18n("R&emove"), this );
+ mRemoveAccountButton->setAutoDefault( false );
+ mRemoveAccountButton->setEnabled( false ); // b/c no item is selected yet
+ connect( mRemoveAccountButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveSelectedAccount()) );
+ btn_vlay->addWidget( mRemoveAccountButton );
+ btn_vlay->addStretch( 1 ); // spacer
+
+ mCheckmailStartupCheck = new QCheckBox( i18n("Chec&k mail on startup"), this );
+ vlay->addWidget( mCheckmailStartupCheck );
+ connect( mCheckmailStartupCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "New Mail Notification" group box: stretch 0
+ group = new QVGroupBox( i18n("New Mail Notification"), this );
+ vlay->addWidget( group );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ // "beep on new mail" check box:
+ mBeepNewMailCheck = new QCheckBox(i18n("&Beep"), group );
+ mBeepNewMailCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
+ QSizePolicy::Fixed ) );
+ connect( mBeepNewMailCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "Detailed new mail notification" check box
+ mVerboseNotificationCheck =
+ new QCheckBox( i18n( "Deta&iled new mail notification" ), group );
+ mVerboseNotificationCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
+ QSizePolicy::Fixed ) );
+ QToolTip::add( mVerboseNotificationCheck,
+ i18n( "Show for each folder the number of newly arrived "
+ "messages" ) );
+ QWhatsThis::add( mVerboseNotificationCheck,
+ GlobalSettings::self()->verboseNewMailNotificationItem()->whatsThis() );
+ connect( mVerboseNotificationCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "Other Actions" button:
+ mOtherNewMailActionsButton = new QPushButton( i18n("Other Actio&ns"), group );
+ mOtherNewMailActionsButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed,
+ QSizePolicy::Fixed ) );
+ connect( mOtherNewMailActionsButton, SIGNAL(clicked()),
+ this, SLOT(slotEditNotifications()) );
+}
+
+AccountsPageReceivingTab::~AccountsPageReceivingTab()
+{
+ // When hitting Cancel or closing the dialog with the window-manager-button,
+ // we have a number of things to clean up:
+
+ // The newly created accounts
+ QValueList< QGuardedPtr<KMAccount> >::Iterator it;
+ for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
+ delete (*it);
+ }
+ mNewAccounts.clear();
+
+ // The modified accounts
+ QValueList<ModifiedAccountsType*>::Iterator j;
+ for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
+ delete (*j)->newAccount;
+ delete (*j);
+ }
+ mModifiedAccounts.clear();
+
+
+}
+
+void AccountsPage::ReceivingTab::slotAccountSelected()
+{
+ QListViewItem * item = mAccountList->selectedItem();
+ mModifyAccountButton->setEnabled( item );
+ mRemoveAccountButton->setEnabled( item );
+}
+
+QStringList AccountsPage::ReceivingTab::occupiedNames()
+{
+ QStringList accountNames = kmkernel->acctMgr()->getAccounts();
+
+ QValueList<ModifiedAccountsType*>::Iterator k;
+ for (k = mModifiedAccounts.begin(); k != mModifiedAccounts.end(); ++k )
+ if ((*k)->oldAccount)
+ accountNames.remove( (*k)->oldAccount->name() );
+
+ QValueList< QGuardedPtr<KMAccount> >::Iterator l;
+ for (l = mAccountsToDelete.begin(); l != mAccountsToDelete.end(); ++l )
+ if (*l)
+ accountNames.remove( (*l)->name() );
+
+ QValueList< QGuardedPtr<KMAccount> >::Iterator it;
+ for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it )
+ if (*it)
+ accountNames += (*it)->name();
+
+ QValueList<ModifiedAccountsType*>::Iterator j;
+ for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
+ accountNames += (*j)->newAccount->name();
+
+ return accountNames;
+}
+
+void AccountsPage::ReceivingTab::slotAddAccount() {
+ KMAcctSelDlg accountSelectorDialog( this );
+ if( accountSelectorDialog.exec() != QDialog::Accepted ) return;
+
+ const char *accountType = 0;
+ switch ( accountSelectorDialog.selected() ) {
+ case 0: accountType = "local"; break;
+ case 1: accountType = "pop"; break;
+ case 2: accountType = "imap"; break;
+ case 3: accountType = "cachedimap"; break;
+ case 4: accountType = "maildir"; break;
+
+ default:
+ // ### FIXME: How should this happen???
+ // replace with assert.
+ KMessageBox::sorry( this, i18n("Unknown account type selected") );
+ return;
+ }
+
+ KMAccount *account
+ = kmkernel->acctMgr()->create( QString::fromLatin1( accountType ) );
+ if ( !account ) {
+ // ### FIXME: Give the user more information. Is this error
+ // recoverable?
+ KMessageBox::sorry( this, i18n("Unable to create account") );
+ return;
+ }
+
+ account->init(); // fill the account fields with good default values
+
+ AccountDialog dialog( i18n("Add Account"), account, this );
+
+ QStringList accountNames = occupiedNames();
+
+ if( dialog.exec() != QDialog::Accepted ) {
+ delete account;
+ return;
+ }
+
+ account->deinstallTimer();
+ account->setName( uniqueName( accountNames, account->name() ) );
+
+ QListViewItem *after = mAccountList->firstChild();
+ while ( after && after->nextSibling() )
+ after = after->nextSibling();
+
+ QListViewItem *listItem =
+ new QListViewItem( mAccountList, after, account->name(), account->type() );
+ if( account->folder() )
+ listItem->setText( 2, account->folder()->label() );
+
+ mNewAccounts.append( account );
+ emit changed( true );
+}
+
+
+
+void AccountsPage::ReceivingTab::slotModifySelectedAccount()
+{
+ QListViewItem *listItem = mAccountList->selectedItem();
+ if( !listItem ) return;
+
+ KMAccount *account = 0;
+ QValueList<ModifiedAccountsType*>::Iterator j;
+ for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j )
+ if ( (*j)->newAccount->name() == listItem->text(0) ) {
+ account = (*j)->newAccount;
+ break;
+ }
+
+ if ( !account ) {
+ QValueList< QGuardedPtr<KMAccount> >::Iterator it;
+ for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
+ if ( (*it)->name() == listItem->text(0) ) {
+ account = *it;
+ break;
+ }
+
+ if ( !account ) {
+ account = kmkernel->acctMgr()->findByName( listItem->text(0) );
+ if( !account ) {
+ // ### FIXME: How should this happen? See above.
+ KMessageBox::sorry( this, i18n("Unable to locate account") );
+ return;
+ }
+ if ( account->type() == "imap" || account->type() == "cachedimap" )
+ {
+ ImapAccountBase* ai = static_cast<ImapAccountBase*>( account );
+ if ( ai->namespaces().isEmpty() || ai->namespaceToDelimiter().isEmpty() )
+ {
+ // connect to server - the namespaces are fetched automatically
+ kdDebug(5006) << "slotModifySelectedAccount - connect" << endl;
+ ai->makeConnection();
+ }
+ }
+
+ ModifiedAccountsType *mod = new ModifiedAccountsType;
+ mod->oldAccount = account;
+ mod->newAccount = kmkernel->acctMgr()->create( account->type(),
+ account->name() );
+ mod->newAccount->pseudoAssign( account );
+ mModifiedAccounts.append( mod );
+ account = mod->newAccount;
+ }
+ }
+
+ QStringList accountNames = occupiedNames();
+ accountNames.remove( account->name() );
+
+ AccountDialog dialog( i18n("Modify Account"), account, this );
+
+ if( dialog.exec() != QDialog::Accepted ) return;
+
+ account->setName( uniqueName( accountNames, account->name() ) );
+
+ listItem->setText( 0, account->name() );
+ listItem->setText( 1, account->type() );
+ if( account->folder() )
+ listItem->setText( 2, account->folder()->label() );
+
+ emit changed( true );
+}
+
+
+
+void AccountsPage::ReceivingTab::slotRemoveSelectedAccount() {
+ QListViewItem *listItem = mAccountList->selectedItem();
+ if( !listItem ) return;
+
+ KMAccount *acct = 0;
+ QValueList<ModifiedAccountsType*>::Iterator j;
+ for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j )
+ if ( (*j)->newAccount->name() == listItem->text(0) ) {
+ acct = (*j)->oldAccount;
+ mAccountsToDelete.append( acct );
+ mModifiedAccounts.remove( j );
+ break;
+ }
+ if ( !acct ) {
+ QValueList< QGuardedPtr<KMAccount> >::Iterator it;
+ for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it )
+ if ( (*it)->name() == listItem->text(0) ) {
+ acct = *it;
+ mNewAccounts.remove( it );
+ break;
+ }
+ }
+ if ( !acct ) {
+ acct = kmkernel->acctMgr()->findByName( listItem->text(0) );
+ if ( acct )
+ mAccountsToDelete.append( acct );
+ }
+ if ( !acct ) {
+ // ### FIXME: see above
+ KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
+ .arg(listItem->text(0)) );
+ return;
+ }
+
+ QListViewItem * item = listItem->itemBelow();
+ if ( !item ) item = listItem->itemAbove();
+ delete listItem;
+
+ if ( item )
+ mAccountList->setSelected( item, true );
+
+ emit changed( true );
+}
+
+void AccountsPage::ReceivingTab::slotEditNotifications()
+{
+ if(kmkernel->xmlGuiInstance())
+ KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData());
+ else
+ KNotifyDialog::configure(this);
+}
+
+void AccountsPage::ReceivingTab::doLoadFromGlobalSettings() {
+ mVerboseNotificationCheck->setChecked( GlobalSettings::self()->verboseNewMailNotification() );
+}
+
+void AccountsPage::ReceivingTab::doLoadOther() {
+ KConfigGroup general( KMKernel::config(), "General" );
+
+ mAccountList->clear();
+ QListViewItem *top = 0;
+
+ for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
+ a = kmkernel->acctMgr()->next() ) {
+ QListViewItem *listItem =
+ new QListViewItem( mAccountList, top, a->name(), a->type() );
+ if( a->folder() )
+ listItem->setText( 2, a->folder()->label() );
+ top = listItem;
+ }
+ QListViewItem *listItem = mAccountList->firstChild();
+ if ( listItem ) {
+ mAccountList->setCurrentItem( listItem );
+ mAccountList->setSelected( listItem, true );
+ }
+
+ mBeepNewMailCheck->setChecked( general.readBoolEntry("beep-on-mail", false ) );
+ mCheckmailStartupCheck->setChecked( general.readBoolEntry("checkmail-startup", false) );
+ QTimer::singleShot( 0, this, SLOT( slotTweakAccountList() ) );
+}
+
+void AccountsPage::ReceivingTab::slotTweakAccountList()
+{
+ // Force the contentsWidth of mAccountList to be recalculated so that items can be
+ // selected in the normal way. It would be best if this were not necessary.
+ mAccountList->resizeContents( mAccountList->visibleWidth(), mAccountList->contentsHeight() );
+}
+
+void AccountsPage::ReceivingTab::save() {
+ // Add accounts marked as new
+ QValueList< QGuardedPtr<KMAccount> >::Iterator it;
+ for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
+ kmkernel->acctMgr()->add( *it ); // calls installTimer too
+ }
+
+ // Update accounts that have been modified
+ QValueList<ModifiedAccountsType*>::Iterator j;
+ for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) {
+ (*j)->oldAccount->pseudoAssign( (*j)->newAccount );
+ delete (*j)->newAccount;
+ delete (*j);
+ }
+ mModifiedAccounts.clear();
+
+ // Delete accounts marked for deletion
+ for ( it = mAccountsToDelete.begin() ;
+ it != mAccountsToDelete.end() ; ++it ) {
+ kmkernel->acctMgr()->writeConfig( true );
+ if ( (*it) && !kmkernel->acctMgr()->remove(*it) )
+ KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>")
+ .arg( (*it)->name() ) );
+ }
+ mAccountsToDelete.clear();
+
+ // Incoming mail
+ kmkernel->acctMgr()->writeConfig( false );
+ kmkernel->cleanupImapFolders();
+
+ // Save Mail notification settings
+ KConfigGroup general( KMKernel::config(), "General" );
+ general.writeEntry( "beep-on-mail", mBeepNewMailCheck->isChecked() );
+ GlobalSettings::self()->setVerboseNewMailNotification( mVerboseNotificationCheck->isChecked() );
+
+ general.writeEntry( "checkmail-startup", mCheckmailStartupCheck->isChecked() );
+
+ // Sync new IMAP accounts ASAP:
+ for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) {
+ KMAccount *macc = (*it);
+ ImapAccountBase *acc = dynamic_cast<ImapAccountBase*> (macc);
+ if ( acc ) {
+ AccountUpdater *au = new AccountUpdater( acc );
+ au->update();
+ }
+ }
+ mNewAccounts.clear();
+
+}
+
+// *************************************************************
+// * *
+// * AppearancePage *
+// * *
+// *************************************************************
+QString AppearancePage::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance");
+}
+
+AppearancePage::AppearancePage( QWidget * parent, const char * name )
+ : ConfigModuleWithTabs( parent, name )
+{
+ //
+ // "Fonts" tab:
+ //
+ mFontsTab = new FontsTab();
+ addTab( mFontsTab, i18n("&Fonts") );
+
+ //
+ // "Colors" tab:
+ //
+ mColorsTab = new ColorsTab();
+ addTab( mColorsTab, i18n("Color&s") );
+
+ //
+ // "Layout" tab:
+ //
+ mLayoutTab = new LayoutTab();
+ addTab( mLayoutTab, i18n("La&yout") );
+
+ //
+ // "Headers" tab:
+ //
+ mHeadersTab = new HeadersTab();
+ addTab( mHeadersTab, i18n("M&essage List") );
+
+ //
+ // "Reader window" tab:
+ //
+ mReaderTab = new ReaderTab();
+ addTab( mReaderTab, i18n("Message W&indow") );
+
+ //
+ // "System Tray" tab:
+ //
+ mSystemTrayTab = new SystemTrayTab();
+ addTab( mSystemTrayTab, i18n("System &Tray") );
+
+ load();
+}
+
+
+QString AppearancePage::FontsTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-fonts");
+}
+
+static const struct {
+ const char * configName;
+ const char * displayName;
+ bool enableFamilyAndSize;
+ bool onlyFixed;
+} fontNames[] = {
+ { "body-font", I18N_NOOP("Message Body"), true, false },
+ { "list-font", I18N_NOOP("Message List"), true, false },
+ { "list-new-font", I18N_NOOP("Message List - New Messages"), true, false },
+ { "list-unread-font", I18N_NOOP("Message List - Unread Messages"), true, false },
+ { "list-important-font", I18N_NOOP("Message List - Important Messages"), true, false },
+ { "list-todo-font", I18N_NOOP("Message List - Todo Messages"), true, false },
+ { "list-date-font", I18N_NOOP("Message List - Date Field"), true, false },
+ { "folder-font", I18N_NOOP("Folder List"), true, false },
+ { "quote1-font", I18N_NOOP("Quoted Text - First Level"), false, false },
+ { "quote2-font", I18N_NOOP("Quoted Text - Second Level"), false, false },
+ { "quote3-font", I18N_NOOP("Quoted Text - Third Level"), false, false },
+ { "fixed-font", I18N_NOOP("Fixed Width Font"), true, true },
+ { "composer-font", I18N_NOOP("Composer"), true, false },
+ { "print-font", I18N_NOOP("Printing Output"), true, false },
+};
+static const int numFontNames = sizeof fontNames / sizeof *fontNames;
+
+AppearancePageFontsTab::AppearancePageFontsTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name ), mActiveFontIndex( -1 )
+{
+ assert( numFontNames == sizeof mFont / sizeof *mFont );
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QHBoxLayout *hlay;
+ QLabel *label;
+
+ // "Use custom fonts" checkbox, followed by <hr>
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+ mCustomFontCheck = new QCheckBox( i18n("&Use custom fonts"), this );
+ vlay->addWidget( mCustomFontCheck );
+ vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
+ connect ( mCustomFontCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "font location" combo box and label:
+ hlay = new QHBoxLayout( vlay ); // inherites spacing
+ mFontLocationCombo = new QComboBox( false, this );
+ mFontLocationCombo->setEnabled( false ); // !mCustomFontCheck->isChecked()
+
+ QStringList fontDescriptions;
+ for ( int i = 0 ; i < numFontNames ; i++ )
+ fontDescriptions << i18n( fontNames[i].displayName );
+ mFontLocationCombo->insertStringList( fontDescriptions );
+
+ label = new QLabel( mFontLocationCombo, i18n("Apply &to:"), this );
+ label->setEnabled( false ); // since !mCustomFontCheck->isChecked()
+ hlay->addWidget( label );
+
+ hlay->addWidget( mFontLocationCombo );
+ hlay->addStretch( 10 );
+ vlay->addSpacing( KDialog::spacingHint() );
+ mFontChooser = new KFontChooser( this, "font", false, QStringList(),
+ false, 4 );
+ mFontChooser->setEnabled( false ); // since !mCustomFontCheck->isChecked()
+ vlay->addWidget( mFontChooser );
+ connect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+
+ // {en,dis}able widgets depending on the state of mCustomFontCheck:
+ connect( mCustomFontCheck, SIGNAL(toggled(bool)),
+ label, SLOT(setEnabled(bool)) );
+ connect( mCustomFontCheck, SIGNAL(toggled(bool)),
+ mFontLocationCombo, SLOT(setEnabled(bool)) );
+ connect( mCustomFontCheck, SIGNAL(toggled(bool)),
+ mFontChooser, SLOT(setEnabled(bool)) );
+ // load the right font settings into mFontChooser:
+ connect( mFontLocationCombo, SIGNAL(activated(int) ),
+ this, SLOT(slotFontSelectorChanged(int)) );
+}
+
+
+void AppearancePage::FontsTab::slotFontSelectorChanged( int index )
+{
+ kdDebug(5006) << "slotFontSelectorChanged() called" << endl;
+ if( index < 0 || index >= mFontLocationCombo->count() )
+ return; // Should never happen, but it is better to check.
+
+ // Save current fontselector setting before we install the new:
+ if( mActiveFontIndex == 0 ) {
+ mFont[0] = mFontChooser->font();
+ // hardcode the family and size of "message body" dependant fonts:
+ for ( int i = 0 ; i < numFontNames ; i++ )
+ if ( !fontNames[i].enableFamilyAndSize ) {
+ // ### shall we copy the font and set the save and re-set
+ // {regular,italic,bold,bold italic} property or should we
+ // copy only family and pointSize?
+ mFont[i].setFamily( mFont[0].family() );
+ mFont[i].setPointSize/*Float?*/( mFont[0].pointSize/*Float?*/() );
+ }
+ } else if ( mActiveFontIndex > 0 )
+ mFont[ mActiveFontIndex ] = mFontChooser->font();
+ mActiveFontIndex = index;
+
+ // Disonnect so the "Apply" button is not activated by the change
+ disconnect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // Display the new setting:
+ mFontChooser->setFont( mFont[index], fontNames[index].onlyFixed );
+
+ connect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // Disable Family and Size list if we have selected a quote font:
+ mFontChooser->enableColumn( KFontChooser::FamilyList|KFontChooser::SizeList,
+ fontNames[ index ].enableFamilyAndSize );
+}
+
+void AppearancePage::FontsTab::doLoadOther() {
+ KConfigGroup fonts( KMKernel::config(), "Fonts" );
+
+ mFont[0] = KGlobalSettings::generalFont();
+ QFont fixedFont = KGlobalSettings::fixedFont();
+ for ( int i = 0 ; i < numFontNames ; i++ )
+ mFont[i] = fonts.readFontEntry( fontNames[i].configName,
+ (fontNames[i].onlyFixed) ? &fixedFont : &mFont[0] );
+
+ mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts", true ) );
+ mFontLocationCombo->setCurrentItem( 0 );
+ slotFontSelectorChanged( 0 );
+}
+
+void AppearancePage::FontsTab::installProfile( KConfig * profile ) {
+ KConfigGroup fonts( profile, "Fonts" );
+
+ // read fonts that are defined in the profile:
+ bool needChange = false;
+ for ( int i = 0 ; i < numFontNames ; i++ )
+ if ( fonts.hasKey( fontNames[i].configName ) ) {
+ needChange = true;
+ mFont[i] = fonts.readFontEntry( fontNames[i].configName );
+ kdDebug(5006) << "got font \"" << fontNames[i].configName
+ << "\" thusly: \"" << mFont[i].toString() << "\"" << endl;
+ }
+ if ( needChange && mFontLocationCombo->currentItem() > 0 )
+ mFontChooser->setFont( mFont[ mFontLocationCombo->currentItem() ],
+ fontNames[ mFontLocationCombo->currentItem() ].onlyFixed );
+
+ if ( fonts.hasKey( "defaultFonts" ) )
+ mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts" ) );
+}
+
+void AppearancePage::FontsTab::save() {
+ KConfigGroup fonts( KMKernel::config(), "Fonts" );
+
+ // read the current font (might have been modified)
+ if ( mActiveFontIndex >= 0 )
+ mFont[ mActiveFontIndex ] = mFontChooser->font();
+
+ bool customFonts = mCustomFontCheck->isChecked();
+ fonts.writeEntry( "defaultFonts", !customFonts );
+ for ( int i = 0 ; i < numFontNames ; i++ )
+ if ( customFonts || fonts.hasKey( fontNames[i].configName ) )
+ // Don't write font info when we use default fonts, but write
+ // if it's already there:
+ fonts.writeEntry( fontNames[i].configName, mFont[i] );
+}
+
+QString AppearancePage::ColorsTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-colors");
+}
+
+
+static const struct {
+ const char * configName;
+ const char * displayName;
+} colorNames[] = { // adjust setup() if you change this:
+ { "BackgroundColor", I18N_NOOP("Composer Background") },
+ { "AltBackgroundColor", I18N_NOOP("Alternative Background Color") },
+ { "ForegroundColor", I18N_NOOP("Normal Text") },
+ { "QuotedText1", I18N_NOOP("Quoted Text - First Level") },
+ { "QuotedText2", I18N_NOOP("Quoted Text - Second Level") },
+ { "QuotedText3", I18N_NOOP("Quoted Text - Third Level") },
+ { "LinkColor", I18N_NOOP("Link") },
+ { "FollowedColor", I18N_NOOP("Followed Link") },
+ { "MisspelledColor", I18N_NOOP("Misspelled Words") },
+ { "NewMessage", I18N_NOOP("New Message") },
+ { "UnreadMessage", I18N_NOOP("Unread Message") },
+ { "FlagMessage", I18N_NOOP("Important Message") },
+ { "TodoMessage", I18N_NOOP("Todo Message") },
+ { "PGPMessageEncr", I18N_NOOP("OpenPGP Message - Encrypted") },
+ { "PGPMessageOkKeyOk", I18N_NOOP("OpenPGP Message - Valid Signature with Trusted Key") },
+ { "PGPMessageOkKeyBad", I18N_NOOP("OpenPGP Message - Valid Signature with Untrusted Key") },
+ { "PGPMessageWarn", I18N_NOOP("OpenPGP Message - Unchecked Signature") },
+ { "PGPMessageErr", I18N_NOOP("OpenPGP Message - Bad Signature") },
+ { "HTMLWarningColor", I18N_NOOP("Border Around Warning Prepending HTML Messages") },
+ { "CloseToQuotaColor", I18N_NOOP("Folder Name and Size When Close to Quota") },
+ { "ColorbarBackgroundPlain", I18N_NOOP("HTML Status Bar Background - No HTML Message") },
+ { "ColorbarForegroundPlain", I18N_NOOP("HTML Status Bar Foreground - No HTML Message") },
+ { "ColorbarBackgroundHTML", I18N_NOOP("HTML Status Bar Background - HTML Message") },
+ { "ColorbarForegroundHTML", I18N_NOOP("HTML Status Bar Foreground - HTML Message") },
+};
+static const int numColorNames = sizeof colorNames / sizeof *colorNames;
+
+AppearancePageColorsTab::AppearancePageColorsTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+
+ // "use custom colors" check box
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+ mCustomColorCheck = new QCheckBox( i18n("&Use custom colors"), this );
+ vlay->addWidget( mCustomColorCheck );
+ connect( mCustomColorCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // color list box:
+ mColorList = new ColorListBox( this );
+ mColorList->setEnabled( false ); // since !mCustomColorCheck->isChecked()
+ QStringList modeList;
+ for ( int i = 0 ; i < numColorNames ; i++ )
+ mColorList->insertItem( new ColorListItem( i18n( colorNames[i].displayName ) ) );
+ vlay->addWidget( mColorList, 1 );
+
+ // "recycle colors" check box:
+ mRecycleColorCheck =
+ new QCheckBox( i18n("Recycle colors on deep &quoting"), this );
+ mRecycleColorCheck->setEnabled( false );
+ vlay->addWidget( mRecycleColorCheck );
+ connect( mRecycleColorCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // close to quota threshold
+ QHBoxLayout *hbox = new QHBoxLayout(vlay);
+ QLabel *l = new QLabel( i18n("Close to quota threshold"), this );
+ hbox->addWidget( l );
+ l->setEnabled( false );
+ mCloseToQuotaThreshold = new QSpinBox( 0, 100, 1, this );
+ connect( mCloseToQuotaThreshold, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ mCloseToQuotaThreshold->setSuffix( i18n("%"));
+ hbox->addWidget( mCloseToQuotaThreshold );
+ hbox->addWidget( new QWidget(this), 2 );
+
+ // {en,dir}able widgets depending on the state of mCustomColorCheck:
+ connect( mCustomColorCheck, SIGNAL(toggled(bool)),
+ mColorList, SLOT(setEnabled(bool)) );
+ connect( mCustomColorCheck, SIGNAL(toggled(bool)),
+ mRecycleColorCheck, SLOT(setEnabled(bool)) );
+ connect( mCustomColorCheck, SIGNAL(toggled(bool)),
+ l, SLOT(setEnabled(bool)) );
+
+ connect( mCustomColorCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+}
+
+void AppearancePage::ColorsTab::doLoadOther() {
+ KConfigGroup reader( KMKernel::config(), "Reader" );
+
+ mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors", true ) );
+ mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors", false ) );
+ mCloseToQuotaThreshold->setValue( GlobalSettings::closeToQuotaThreshold() );
+
+ static const QColor defaultColor[ numColorNames ] = {
+ kapp->palette().active().base(), // bg
+ KGlobalSettings::alternateBackgroundColor(), // alt bg
+ kapp->palette().active().text(), // fg
+ QColor( 0x00, 0x80, 0x00 ), // quoted l1
+ QColor( 0x00, 0x70, 0x00 ), // quoted l2
+ QColor( 0x00, 0x60, 0x00 ), // quoted l3
+ KGlobalSettings::linkColor(), // link
+ KGlobalSettings::visitedLinkColor(), // visited link
+ Qt::red, // misspelled words
+ Qt::red, // new msg
+ Qt::blue, // unread mgs
+ QColor( 0x00, 0x7F, 0x00 ), // important msg
+ Qt::blue, // todo mgs
+ QColor( 0x00, 0x80, 0xFF ), // light blue // pgp encrypted
+ QColor( 0x40, 0xFF, 0x40 ), // light green // pgp ok, trusted key
+ QColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp ok, untrusted key
+ QColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp unchk
+ Qt::red, // pgp bad
+ QColor( 0xFF, 0x40, 0x40 ), // warning text color: light red
+ Qt::red, // close to quota
+ Qt::lightGray, // colorbar plain bg
+ Qt::black, // colorbar plain fg
+ Qt::black, // colorbar html bg
+ Qt::white, // colorbar html fg
+ };
+
+ for ( int i = 0 ; i < numColorNames ; i++ ) {
+ mColorList->setColor( i,
+ reader.readColorEntry( colorNames[i].configName, &defaultColor[i] ) );
+ }
+ connect( mColorList, SIGNAL( changed( ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+}
+
+void AppearancePage::ColorsTab::installProfile( KConfig * profile ) {
+ KConfigGroup reader( profile, "Reader" );
+
+ if ( reader.hasKey( "defaultColors" ) )
+ mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors" ) );
+ if ( reader.hasKey( "RecycleQuoteColors" ) )
+ mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors" ) );
+
+ for ( int i = 0 ; i < numColorNames ; i++ )
+ if ( reader.hasKey( colorNames[i].configName ) )
+ mColorList->setColor( i, reader.readColorEntry( colorNames[i].configName ) );
+}
+
+void AppearancePage::ColorsTab::save() {
+ KConfigGroup reader( KMKernel::config(), "Reader" );
+
+ bool customColors = mCustomColorCheck->isChecked();
+ reader.writeEntry( "defaultColors", !customColors );
+
+ for ( int i = 0 ; i < numColorNames ; i++ )
+ // Don't write color info when we use default colors, but write
+ // if it's already there:
+ if ( customColors || reader.hasKey( colorNames[i].configName ) )
+ reader.writeEntry( colorNames[i].configName, mColorList->color(i) );
+
+ reader.writeEntry( "RecycleQuoteColors", mRecycleColorCheck->isChecked() );
+ GlobalSettings::setCloseToQuotaThreshold( mCloseToQuotaThreshold->value() );
+}
+
+QString AppearancePage::LayoutTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-layout");
+}
+
+static const EnumConfigEntryItem folderListModes[] = {
+ { "long", I18N_NOOP("Lon&g folder list") },
+ { "short", I18N_NOOP("Shor&t folder list" ) }
+};
+static const EnumConfigEntry folderListMode = {
+ "Geometry", "FolderList", I18N_NOOP("Folder List"),
+ folderListModes, DIM(folderListModes), 0
+};
+
+
+static const EnumConfigEntryItem mimeTreeLocations[] = {
+ { "top", I18N_NOOP("Abo&ve the message pane") },
+ { "bottom", I18N_NOOP("&Below the message pane") }
+};
+static const EnumConfigEntry mimeTreeLocation = {
+ "Reader", "MimeTreeLocation", I18N_NOOP("Message Structure Viewer Placement"),
+ mimeTreeLocations, DIM(mimeTreeLocations), 1
+};
+
+static const EnumConfigEntryItem mimeTreeModes[] = {
+ { "never", I18N_NOOP("Show &never") },
+ { "smart", I18N_NOOP("Show only for non-plaintext &messages") },
+ { "always", I18N_NOOP("Show alway&s") }
+};
+static const EnumConfigEntry mimeTreeMode = {
+ "Reader", "MimeTreeMode", I18N_NOOP("Message Structure Viewer"),
+ mimeTreeModes, DIM(mimeTreeModes), 1
+};
+
+
+static const EnumConfigEntryItem readerWindowModes[] = {
+ { "hide", I18N_NOOP("&Do not show a message preview pane") },
+ { "below", I18N_NOOP("Show the message preview pane belo&w the message list") },
+ { "right", I18N_NOOP("Show the message preview pane ne&xt to the message list") }
+};
+static const EnumConfigEntry readerWindowMode = {
+ "Geometry", "readerWindowMode", I18N_NOOP("Message Preview Pane"),
+ readerWindowModes, DIM(readerWindowModes), 1
+};
+
+AppearancePageLayoutTab::AppearancePageLayoutTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout * vlay;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "folder list" radio buttons:
+ populateButtonGroup( mFolderListGroup = new QHButtonGroup( this ), folderListMode );
+ vlay->addWidget( mFolderListGroup );
+ connect( mFolderListGroup, SIGNAL ( clicked( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ mFavoriteFolderViewCB = new QCheckBox( i18n("Show favorite folder view"), this );
+ connect( mFavoriteFolderViewCB, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ vlay->addWidget( mFavoriteFolderViewCB );
+
+ mFolderQuickSearchCB = new QCheckBox( i18n("Show folder quick search field"), this );
+ connect( mFolderQuickSearchCB, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ vlay->addWidget( mFolderQuickSearchCB );
+
+ // "show reader window" radio buttons:
+ populateButtonGroup( mReaderWindowModeGroup = new QVButtonGroup( this ), readerWindowMode );
+ vlay->addWidget( mReaderWindowModeGroup );
+ connect( mReaderWindowModeGroup, SIGNAL ( clicked( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "Show MIME Tree" radio buttons:
+ populateButtonGroup( mMIMETreeModeGroup = new QVButtonGroup( this ), mimeTreeMode );
+ vlay->addWidget( mMIMETreeModeGroup );
+ connect( mMIMETreeModeGroup, SIGNAL ( clicked( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "MIME Tree Location" radio buttons:
+ populateButtonGroup( mMIMETreeLocationGroup = new QHButtonGroup( this ), mimeTreeLocation );
+ vlay->addWidget( mMIMETreeLocationGroup );
+ connect( mMIMETreeLocationGroup, SIGNAL ( clicked( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ vlay->addStretch( 10 ); // spacer
+}
+
+void AppearancePage::LayoutTab::doLoadOther() {
+ const KConfigGroup reader( KMKernel::config(), "Reader" );
+ const KConfigGroup geometry( KMKernel::config(), "Geometry" );
+
+ loadWidget( mFolderListGroup, geometry, folderListMode );
+ loadWidget( mMIMETreeLocationGroup, reader, mimeTreeLocation );
+ loadWidget( mMIMETreeModeGroup, reader, mimeTreeMode );
+ loadWidget( mReaderWindowModeGroup, geometry, readerWindowMode );
+ mFavoriteFolderViewCB->setChecked( GlobalSettings::self()->enableFavoriteFolderView() );
+ mFolderQuickSearchCB->setChecked( GlobalSettings::self()->enableFolderQuickSearch() );
+}
+
+void AppearancePage::LayoutTab::installProfile( KConfig * profile ) {
+ const KConfigGroup reader( profile, "Reader" );
+ const KConfigGroup geometry( profile, "Geometry" );
+
+ loadProfile( mFolderListGroup, geometry, folderListMode );
+ loadProfile( mMIMETreeLocationGroup, reader, mimeTreeLocation );
+ loadProfile( mMIMETreeModeGroup, reader, mimeTreeMode );
+ loadProfile( mReaderWindowModeGroup, geometry, readerWindowMode );
+}
+
+void AppearancePage::LayoutTab::save() {
+ KConfigGroup reader( KMKernel::config(), "Reader" );
+ KConfigGroup geometry( KMKernel::config(), "Geometry" );
+
+ saveButtonGroup( mFolderListGroup, geometry, folderListMode );
+ saveButtonGroup( mMIMETreeLocationGroup, reader, mimeTreeLocation );
+ saveButtonGroup( mMIMETreeModeGroup, reader, mimeTreeMode );
+ saveButtonGroup( mReaderWindowModeGroup, geometry, readerWindowMode );
+ GlobalSettings::self()->setEnableFavoriteFolderView( mFavoriteFolderViewCB->isChecked() );
+ GlobalSettings::self()->setEnableFolderQuickSearch( mFolderQuickSearchCB->isChecked() );
+}
+
+//
+// Appearance Message List
+//
+
+QString AppearancePage::HeadersTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-headers");
+}
+
+static const struct {
+ const char * displayName;
+ DateFormatter::FormatType dateDisplay;
+} dateDisplayConfig[] = {
+ { I18N_NOOP("Sta&ndard format (%1)"), KMime::DateFormatter::CTime },
+ { I18N_NOOP("Locali&zed format (%1)"), KMime::DateFormatter::Localized },
+ { I18N_NOOP("Fancy for&mat (%1)"), KMime::DateFormatter::Fancy },
+ { I18N_NOOP("C&ustom format (Shift+F1 for help):"),
+ KMime::DateFormatter::Custom }
+};
+static const int numDateDisplayConfig =
+ sizeof dateDisplayConfig / sizeof *dateDisplayConfig;
+
+AppearancePageHeadersTab::AppearancePageHeadersTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name ),
+ mCustomDateFormatEdit( 0 )
+{
+ // tmp. vars:
+ QButtonGroup * group;
+ QRadioButton * radio;
+
+ QVBoxLayout * vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "General Options" group:
+ group = new QVButtonGroup( i18n( "General Options" ), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ mShowQuickSearch = new QCheckBox( i18n("Show Quick Search"), group );
+
+ mMessageSizeCheck = new QCheckBox( i18n("Display messa&ge sizes"), group );
+
+ mCryptoIconsCheck = new QCheckBox( i18n( "Show crypto &icons" ), group );
+
+ mAttachmentCheck = new QCheckBox( i18n("Show attachment icon"), group );
+
+ mNestedMessagesCheck =
+ new QCheckBox( i18n("&Threaded message list"), group );
+
+ connect( mShowQuickSearch, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mMessageSizeCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mAttachmentCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mCryptoIconsCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mNestedMessagesCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+
+ vlay->addWidget( group );
+
+ // "Message Header Threading Options" group:
+ mNestingPolicy =
+ new QVButtonGroup( i18n("Threaded Message List Options"), this );
+ mNestingPolicy->layout()->setSpacing( KDialog::spacingHint() );
+
+ mNestingPolicy->insert(
+ new QRadioButton( i18n("Always &keep threads open"),
+ mNestingPolicy ), 0 );
+ mNestingPolicy->insert(
+ new QRadioButton( i18n("Threads default to o&pen"),
+ mNestingPolicy ), 1 );
+ mNestingPolicy->insert(
+ new QRadioButton( i18n("Threads default to closed"),
+ mNestingPolicy ), 2 );
+ mNestingPolicy->insert(
+ new QRadioButton( i18n("Open threads that contain ne&w, unread "
+ "or important messages and open watched threads."),
+ mNestingPolicy ), 3 );
+
+ vlay->addWidget( mNestingPolicy );
+
+ connect( mNestingPolicy, SIGNAL( clicked( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "Date Display" group:
+ mDateDisplay = new QVButtonGroup( i18n("Date Display"), this );
+ mDateDisplay->layout()->setSpacing( KDialog::spacingHint() );
+
+ for ( int i = 0 ; i < numDateDisplayConfig ; i++ ) {
+ QString buttonLabel = i18n(dateDisplayConfig[i].displayName);
+ if ( buttonLabel.contains("%1") )
+ buttonLabel = buttonLabel.arg( DateFormatter::formatCurrentDate( dateDisplayConfig[i].dateDisplay ) );
+ radio = new QRadioButton( buttonLabel, mDateDisplay );
+ mDateDisplay->insert( radio, i );
+ if ( dateDisplayConfig[i].dateDisplay == DateFormatter::Custom ) {
+ mCustomDateFormatEdit = new KLineEdit( mDateDisplay );
+ mCustomDateFormatEdit->setEnabled( false );
+ connect( radio, SIGNAL(toggled(bool)),
+ mCustomDateFormatEdit, SLOT(setEnabled(bool)) );
+ connect( mCustomDateFormatEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotEmitChanged(void)) );
+ QString customDateWhatsThis =
+ i18n("<qt><p><strong>These expressions may be used for the date:"
+ "</strong></p>"
+ "<ul>"
+ "<li>d - the day as a number without a leading zero (1-31)</li>"
+ "<li>dd - the day as a number with a leading zero (01-31)</li>"
+ "<li>ddd - the abbreviated day name (Mon - Sun)</li>"
+ "<li>dddd - the long day name (Monday - Sunday)</li>"
+ "<li>M - the month as a number without a leading zero (1-12)</li>"
+ "<li>MM - the month as a number with a leading zero (01-12)</li>"
+ "<li>MMM - the abbreviated month name (Jan - Dec)</li>"
+ "<li>MMMM - the long month name (January - December)</li>"
+ "<li>yy - the year as a two digit number (00-99)</li>"
+ "<li>yyyy - the year as a four digit number (0000-9999)</li>"
+ "</ul>"
+ "<p><strong>These expressions may be used for the time:"
+ "</string></p> "
+ "<ul>"
+ "<li>h - the hour without a leading zero (0-23 or 1-12 if AM/PM display)</li>"
+ "<li>hh - the hour with a leading zero (00-23 or 01-12 if AM/PM display)</li>"
+ "<li>m - the minutes without a leading zero (0-59)</li>"
+ "<li>mm - the minutes with a leading zero (00-59)</li>"
+ "<li>s - the seconds without a leading zero (0-59)</li>"
+ "<li>ss - the seconds with a leading zero (00-59)</li>"
+ "<li>z - the milliseconds without leading zeroes (0-999)</li>"
+ "<li>zzz - the milliseconds with leading zeroes (000-999)</li>"
+ "<li>AP - switch to AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</li>"
+ "<li>ap - switch to AM/PM display. ap will be replaced by either \"am\" or \"pm\".</li>"
+ "<li>Z - time zone in numeric form (-0500)</li>"
+ "</ul>"
+ "<p><strong>All other input characters will be ignored."
+ "</strong></p></qt>");
+ QWhatsThis::add( mCustomDateFormatEdit, customDateWhatsThis );
+ QWhatsThis::add( radio, customDateWhatsThis );
+ }
+ } // end for loop populating mDateDisplay
+
+ vlay->addWidget( mDateDisplay );
+ connect( mDateDisplay, SIGNAL( clicked( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+
+ vlay->addStretch( 10 ); // spacer
+}
+
+void AppearancePage::HeadersTab::doLoadOther() {
+ KConfigGroup general( KMKernel::config(), "General" );
+ KConfigGroup geometry( KMKernel::config(), "Geometry" );
+
+ // "General Options":
+ mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages", false ) );
+ mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize", false ) );
+ mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons", false ) );
+ mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon", true ) );
+ mShowQuickSearch->setChecked( GlobalSettings::self()->quickSearchActive() );
+
+ // "Message Header Threading Options":
+ int num = geometry.readNumEntry( "nestingPolicy", 3 );
+ if ( num < 0 || num > 3 ) num = 3;
+ mNestingPolicy->setButton( num );
+
+ // "Date Display":
+ setDateDisplay( general.readNumEntry( "dateFormat", DateFormatter::Fancy ),
+ general.readEntry( "customDateFormat" ) );
+}
+
+void AppearancePage::HeadersTab::setDateDisplay( int num, const QString & format ) {
+ DateFormatter::FormatType dateDisplay =
+ static_cast<DateFormatter::FormatType>( num );
+
+ // special case: needs text for the line edit:
+ if ( dateDisplay == DateFormatter::Custom )
+ mCustomDateFormatEdit->setText( format );
+
+ for ( int i = 0 ; i < numDateDisplayConfig ; i++ )
+ if ( dateDisplay == dateDisplayConfig[i].dateDisplay ) {
+ mDateDisplay->setButton( i );
+ return;
+ }
+ // fell through since none found:
+ mDateDisplay->setButton( numDateDisplayConfig - 2 ); // default
+}
+
+void AppearancePage::HeadersTab::installProfile( KConfig * profile ) {
+ KConfigGroup general( profile, "General" );
+ KConfigGroup geometry( profile, "Geometry" );
+
+ if ( geometry.hasKey( "nestedMessages" ) )
+ mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages" ) );
+ if ( general.hasKey( "showMessageSize" ) )
+ mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize" ) );
+
+ if( general.hasKey( "showCryptoIcons" ) )
+ mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons" ) );
+ if ( general.hasKey( "showAttachmentIcon" ) )
+ mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon" ) );
+
+ if ( geometry.hasKey( "nestingPolicy" ) ) {
+ int num = geometry.readNumEntry( "nestingPolicy" );
+ if ( num < 0 || num > 3 ) num = 3;
+ mNestingPolicy->setButton( num );
+ }
+
+ if ( general.hasKey( "dateFormat" ) )
+ setDateDisplay( general.readNumEntry( "dateFormat" ),
+ general.readEntry( "customDateFormat" ) );
+}
+
+void AppearancePage::HeadersTab::save() {
+ KConfigGroup general( KMKernel::config(), "General" );
+ KConfigGroup geometry( KMKernel::config(), "Geometry" );
+
+ if ( geometry.readBoolEntry( "nestedMessages", false )
+ != mNestedMessagesCheck->isChecked() ) {
+ int result = KMessageBox::warningContinueCancel( this,
+ i18n("Changing the global threading setting will override "
+ "all folder specific values."),
+ QString::null, KStdGuiItem::cont(), "threadOverride" );
+ if ( result == KMessageBox::Continue ) {
+ geometry.writeEntry( "nestedMessages", mNestedMessagesCheck->isChecked() );
+ // remove all threadMessagesOverride keys from all [Folder-*] groups:
+ QStringList groups = KMKernel::config()->groupList().grep( QRegExp("^Folder-") );
+ kdDebug(5006) << "groups.count() == " << groups.count() << endl;
+ for ( QStringList::const_iterator it = groups.begin() ; it != groups.end() ; ++it ) {
+ KConfigGroup group( KMKernel::config(), *it );
+ group.deleteEntry( "threadMessagesOverride" );
+ }
+ }
+ }
+
+ geometry.writeEntry( "nestingPolicy",
+ mNestingPolicy->id( mNestingPolicy->selected() ) );
+ general.writeEntry( "showMessageSize", mMessageSizeCheck->isChecked() );
+ general.writeEntry( "showCryptoIcons", mCryptoIconsCheck->isChecked() );
+ general.writeEntry( "showAttachmentIcon", mAttachmentCheck->isChecked() );
+ GlobalSettings::self()->setQuickSearchActive( mShowQuickSearch->isChecked() );
+
+ int dateDisplayID = mDateDisplay->id( mDateDisplay->selected() );
+ // check bounds:
+ assert( dateDisplayID >= 0 ); assert( dateDisplayID < numDateDisplayConfig );
+ general.writeEntry( "dateFormat",
+ dateDisplayConfig[ dateDisplayID ].dateDisplay );
+ general.writeEntry( "customDateFormat", mCustomDateFormatEdit->text() );
+}
+
+
+//
+// Message Window
+//
+
+
+static const BoolConfigEntry showColorbarMode = {
+ "Reader", "showColorbar", I18N_NOOP("Show HTML stat&us bar"), false
+};
+
+static const BoolConfigEntry showSpamStatusMode = {
+ "Reader", "showSpamStatus", I18N_NOOP("Show s&pam status in fancy headers"), true
+};
+
+static const BoolConfigEntry showEmoticons = {
+ "Reader", "ShowEmoticons", I18N_NOOP("Replace smileys by emoticons"), true
+};
+
+static const BoolConfigEntry shrinkQuotes = {
+ "Reader", "ShrinkQuotes", I18N_NOOP("Use smaller font for quoted text"), false
+};
+
+static const BoolConfigEntry showExpandQuotesMark= {
+ "Reader", "ShowExpandQuotesMark", I18N_NOOP("Show expand/collapse quote marks"), false
+};
+
+
+QString AppearancePage::ReaderTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-reader");
+}
+
+AppearancePageReaderTab::AppearancePageReaderTab( QWidget * parent,
+ const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ QVBoxLayout *vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "show colorbar" check box:
+ populateCheckBox( mShowColorbarCheck = new QCheckBox( this ), showColorbarMode );
+ vlay->addWidget( mShowColorbarCheck );
+ connect( mShowColorbarCheck, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "show spam status" check box;
+ populateCheckBox( mShowSpamStatusCheck = new QCheckBox( this ), showSpamStatusMode );
+ vlay->addWidget( mShowSpamStatusCheck );
+ connect( mShowSpamStatusCheck, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "replace smileys by emoticons" check box;
+ populateCheckBox( mShowEmoticonsCheck = new QCheckBox( this ), showEmoticons );
+ vlay->addWidget( mShowEmoticonsCheck );
+ connect( mShowEmoticonsCheck, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "Use smaller font for quoted text" check box
+ mShrinkQuotesCheck = new QCheckBox( i18n( shrinkQuotes.desc ), this,
+ "kcfg_ShrinkQuotes" );
+ vlay->addWidget( mShrinkQuotesCheck );
+ connect( mShrinkQuotesCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // "Show expand/collaps quote marks" check box;
+ QHBoxLayout *hlay= new QHBoxLayout( vlay ); // inherits spacing
+ populateCheckBox( mShowExpandQuotesMark= new QCheckBox( this ), showExpandQuotesMark);
+ hlay->addWidget( mShowExpandQuotesMark);
+ connect( mShowExpandQuotesMark, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ hlay->addStretch( 1 );
+ mCollapseQuoteLevelSpin = new KIntSpinBox( 0/*min*/,10/*max*/,1/*step*/,
+ 3/*init*/,10/*base*/,this );
+
+ QLabel *label = new QLabel( mCollapseQuoteLevelSpin,
+ GlobalSettings::self()->collapseQuoteLevelSpinItem()->label(), this );
+
+ hlay->addWidget( label );
+
+ mCollapseQuoteLevelSpin->setEnabled( false ); //since !mShowExpandQuotesMark->isCheckec()
+ connect( mCollapseQuoteLevelSpin, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ hlay->addWidget( mCollapseQuoteLevelSpin);
+
+ connect( mShowExpandQuotesMark, SIGNAL( toggled( bool ) ),
+ mCollapseQuoteLevelSpin, SLOT( setEnabled( bool ) ) );
+
+ // Fallback Character Encoding
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mCharsetCombo = new QComboBox( this );
+ mCharsetCombo->insertStringList( KMMsgBase::supportedEncodings( false ) );
+
+ connect( mCharsetCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ QString fallbackCharsetWhatsThis =
+ i18n( GlobalSettings::self()->fallbackCharacterEncodingItem()->whatsThis().utf8() );
+ QWhatsThis::add( mCharsetCombo, fallbackCharsetWhatsThis );
+
+ label = new QLabel( i18n("Fallback ch&aracter encoding:"), this );
+ label->setBuddy( mCharsetCombo );
+
+ hlay->addWidget( label );
+ hlay->addWidget( mCharsetCombo );
+
+ // Override Character Encoding
+ QHBoxLayout *hlay2 = new QHBoxLayout( vlay ); // inherits spacing
+ mOverrideCharsetCombo = new QComboBox( this );
+ QStringList encodings = KMMsgBase::supportedEncodings( false );
+ encodings.prepend( i18n( "Auto" ) );
+ mOverrideCharsetCombo->insertStringList( encodings );
+ mOverrideCharsetCombo->setCurrentItem(0);
+
+ connect( mOverrideCharsetCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ QString overrideCharsetWhatsThis =
+ i18n( GlobalSettings::self()->overrideCharacterEncodingItem()->whatsThis().utf8() );
+ QWhatsThis::add( mOverrideCharsetCombo, overrideCharsetWhatsThis );
+
+ label = new QLabel( i18n("&Override character encoding:"), this );
+ label->setBuddy( mOverrideCharsetCombo );
+
+ hlay2->addWidget( label );
+ hlay2->addWidget( mOverrideCharsetCombo );
+
+ vlay->addStretch( 100 ); // spacer
+}
+
+
+void AppearancePage::ReaderTab::readCurrentFallbackCodec()
+{
+ QStringList encodings = KMMsgBase::supportedEncodings( false );
+ QStringList::ConstIterator it( encodings.begin() );
+ QStringList::ConstIterator end( encodings.end() );
+ QString currentEncoding = GlobalSettings::self()->fallbackCharacterEncoding();
+ currentEncoding = currentEncoding.replace( "iso ", "iso-", false );
+ ///kdDebug(5006) << "Looking for encoding: " << currentEncoding << endl;
+ int i = 0;
+ int indexOfLatin9 = 0;
+ bool found = false;
+ for( ; it != end; ++it)
+ {
+ const QString encoding = KGlobal::charsets()->encodingForName(*it);
+ if ( encoding == "iso-8859-15" )
+ indexOfLatin9 = i;
+ if( encoding == currentEncoding )
+ {
+ mCharsetCombo->setCurrentItem( i );
+ found = true;
+ break;
+ }
+ i++;
+ }
+ if ( !found ) // nothing matched, use latin9
+ mCharsetCombo->setCurrentItem( indexOfLatin9 );
+}
+
+void AppearancePage::ReaderTab::readCurrentOverrideCodec()
+{
+ const QString &currentOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
+ if ( currentOverrideEncoding.isEmpty() ) {
+ mOverrideCharsetCombo->setCurrentItem( 0 );
+ return;
+ }
+ QStringList encodings = KMMsgBase::supportedEncodings( false );
+ encodings.prepend( i18n( "Auto" ) );
+ QStringList::Iterator it( encodings.begin() );
+ QStringList::Iterator end( encodings.end() );
+ uint i = 0;
+ for( ; it != end; ++it)
+ {
+ if( KGlobal::charsets()->encodingForName(*it) == currentOverrideEncoding )
+ {
+ mOverrideCharsetCombo->setCurrentItem( i );
+ break;
+ }
+ i++;
+ }
+ if ( i == encodings.size() ) {
+ // the current value of overrideCharacterEncoding is an unknown encoding => reset to Auto
+ kdWarning(5006) << "Unknown override character encoding \"" << currentOverrideEncoding
+ << "\". Resetting to Auto." << endl;
+ mOverrideCharsetCombo->setCurrentItem( 0 );
+ GlobalSettings::self()->setOverrideCharacterEncoding( QString::null );
+ }
+}
+
+void AppearancePage::ReaderTab::doLoadFromGlobalSettings()
+{
+ mShowEmoticonsCheck->setChecked( GlobalSettings::self()->showEmoticons() );
+ mShrinkQuotesCheck->setChecked( GlobalSettings::self()->shrinkQuotes() );
+ mShowExpandQuotesMark->setChecked( GlobalSettings::self()->showExpandQuotesMark() );
+ mCollapseQuoteLevelSpin->setValue( GlobalSettings::self()->collapseQuoteLevelSpin() );
+ readCurrentFallbackCodec();
+ readCurrentOverrideCodec();
+}
+
+void AppearancePage::ReaderTab::doLoadOther()
+{
+ const KConfigGroup reader( KMKernel::config(), "Reader" );
+ loadWidget( mShowColorbarCheck, reader, showColorbarMode );
+ loadWidget( mShowSpamStatusCheck, reader, showSpamStatusMode );
+}
+
+
+void AppearancePage::ReaderTab::save() {
+ KConfigGroup reader( KMKernel::config(), "Reader" );
+ saveCheckBox( mShowColorbarCheck, reader, showColorbarMode );
+ saveCheckBox( mShowSpamStatusCheck, reader, showSpamStatusMode );
+ GlobalSettings::self()->setShowEmoticons( mShowEmoticonsCheck->isChecked() );
+ GlobalSettings::self()->setShrinkQuotes( mShrinkQuotesCheck->isChecked() );
+ GlobalSettings::self()->setShowExpandQuotesMark( mShowExpandQuotesMark->isChecked() );
+
+ GlobalSettings::self()->setCollapseQuoteLevelSpin( mCollapseQuoteLevelSpin->value() );
+ GlobalSettings::self()->setFallbackCharacterEncoding(
+ KGlobal::charsets()->encodingForName( mCharsetCombo->currentText() ) );
+ GlobalSettings::self()->setOverrideCharacterEncoding(
+ mOverrideCharsetCombo->currentItem() == 0 ?
+ QString() :
+ KGlobal::charsets()->encodingForName( mOverrideCharsetCombo->currentText() ) );
+}
+
+
+void AppearancePage::ReaderTab::installProfile( KConfig * /* profile */ ) {
+ const KConfigGroup reader( KMKernel::config(), "Reader" );
+ loadProfile( mShowColorbarCheck, reader, showColorbarMode );
+ loadProfile( mShowSpamStatusCheck, reader, showSpamStatusMode );
+ loadProfile( mShowEmoticonsCheck, reader, showEmoticons );
+ loadProfile( mShrinkQuotesCheck, reader, shrinkQuotes );
+ loadProfile( mShowExpandQuotesMark, reader, showExpandQuotesMark);
+}
+
+
+QString AppearancePage::SystemTrayTab::helpAnchor() const {
+ return QString::fromLatin1("configure-appearance-systemtray");
+}
+
+AppearancePageSystemTrayTab::AppearancePageSystemTrayTab( QWidget * parent,
+ const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ QVBoxLayout * vlay = new QVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint() );
+
+ // "Enable system tray applet" check box
+ mSystemTrayCheck = new QCheckBox( i18n("Enable system tray icon"), this );
+ vlay->addWidget( mSystemTrayCheck );
+ connect( mSystemTrayCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // System tray modes
+ mSystemTrayGroup = new QVButtonGroup( i18n("System Tray Mode"), this );
+ mSystemTrayGroup->layout()->setSpacing( KDialog::spacingHint() );
+ vlay->addWidget( mSystemTrayGroup );
+ connect( mSystemTrayGroup, SIGNAL( clicked( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mSystemTrayCheck, SIGNAL( toggled( bool ) ),
+ mSystemTrayGroup, SLOT( setEnabled( bool ) ) );
+
+ mSystemTrayGroup->insert( new QRadioButton( i18n("Always show KMail in system tray"), mSystemTrayGroup ),
+ GlobalSettings::EnumSystemTrayPolicy::ShowAlways );
+
+ mSystemTrayGroup->insert( new QRadioButton( i18n("Only show KMail in system tray if there are unread messages"), mSystemTrayGroup ),
+ GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread );
+
+ vlay->addStretch( 10 ); // spacer
+}
+
+void AppearancePage::SystemTrayTab::doLoadFromGlobalSettings() {
+ mSystemTrayCheck->setChecked( GlobalSettings::self()->systemTrayEnabled() );
+ mSystemTrayGroup->setButton( GlobalSettings::self()->systemTrayPolicy() );
+ mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
+}
+
+void AppearancePage::SystemTrayTab::installProfile( KConfig * profile ) {
+ KConfigGroup general( profile, "General" );
+
+ if ( general.hasKey( "SystemTrayEnabled" ) ) {
+ mSystemTrayCheck->setChecked( general.readBoolEntry( "SystemTrayEnabled" ) );
+ }
+ if ( general.hasKey( "SystemTrayPolicy" ) ) {
+ mSystemTrayGroup->setButton( general.readNumEntry( "SystemTrayPolicy" ) );
+ }
+ mSystemTrayGroup->setEnabled( mSystemTrayCheck->isChecked() );
+}
+
+void AppearancePage::SystemTrayTab::save() {
+ GlobalSettings::self()->setSystemTrayEnabled( mSystemTrayCheck->isChecked() );
+ GlobalSettings::self()->setSystemTrayPolicy( mSystemTrayGroup->id( mSystemTrayGroup->selected() ) );
+}
+
+
+// *************************************************************
+// * *
+// * ComposerPage *
+// * *
+// *************************************************************
+
+QString ComposerPage::helpAnchor() const {
+ return QString::fromLatin1("configure-composer");
+}
+
+ComposerPage::ComposerPage( QWidget * parent, const char * name )
+ : ConfigModuleWithTabs( parent, name )
+{
+ //
+ // "General" tab:
+ //
+ mGeneralTab = new GeneralTab();
+ addTab( mGeneralTab, i18n("&General") );
+ addConfig( GlobalSettings::self(), mGeneralTab );
+
+ //
+ // "Phrases" tab:
+ //
+ // mPhrasesTab = new PhrasesTab();
+ // addTab( mPhrasesTab, i18n("&Phrases") );
+
+ //
+ // "Templates" tab:
+ //
+ mTemplatesTab = new TemplatesTab();
+ addTab( mTemplatesTab, i18n("&Templates") );
+
+ //
+ // "Custom Templates" tab:
+ //
+ mCustomTemplatesTab = new CustomTemplatesTab();
+ addTab( mCustomTemplatesTab, i18n("&Custom Templates") );
+
+ //
+ // "Subject" tab:
+ //
+ mSubjectTab = new SubjectTab();
+ addTab( mSubjectTab, i18n("&Subject") );
+ addConfig( GlobalSettings::self(), mSubjectTab );
+
+ //
+ // "Charset" tab:
+ //
+ mCharsetTab = new CharsetTab();
+ addTab( mCharsetTab, i18n("Cha&rset") );
+
+ //
+ // "Headers" tab:
+ //
+ mHeadersTab = new HeadersTab();
+ addTab( mHeadersTab, i18n("H&eaders") );
+
+ //
+ // "Attachments" tab:
+ //
+ mAttachmentsTab = new AttachmentsTab();
+ addTab( mAttachmentsTab, i18n("Config->Composer->Attachments", "A&ttachments") );
+ load();
+}
+
+QString ComposerPage::GeneralTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-general");
+}
+
+ComposerPageGeneralTab::ComposerPageGeneralTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QHBoxLayout *hlay;
+ QGroupBox *group;
+ QLabel *label;
+ QHBox *hbox;
+ QString msg;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // some check buttons...
+ mAutoAppSignFileCheck = new QCheckBox(
+ GlobalSettings::self()->autoTextSignatureItem()->label(),
+ this );
+ vlay->addWidget( mAutoAppSignFileCheck );
+ connect( mAutoAppSignFileCheck, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mTopQuoteCheck =
+ new QCheckBox( GlobalSettings::self()->prependSignatureItem()->label(), this );
+ vlay->addWidget( mTopQuoteCheck);
+ connect( mTopQuoteCheck, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mSmartQuoteCheck = new QCheckBox(
+ GlobalSettings::self()->smartQuoteItem()->label(),
+ this, "kcfg_SmartQuote" );
+ vlay->addWidget( mSmartQuoteCheck );
+ connect( mSmartQuoteCheck, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mAutoRequestMDNCheck = new QCheckBox(
+ GlobalSettings::self()->requestMDNItem()->label(),
+ this, "kcfg_RequestMDN" );
+ vlay->addWidget( mAutoRequestMDNCheck );
+ connect( mAutoRequestMDNCheck, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mShowRecentAddressesInComposer = new QCheckBox(
+ GlobalSettings::self()->showRecentAddressesInComposerItem()->label(),
+ this, "kcfg_ShowRecentAddressesInComposer" );
+ vlay->addWidget( mShowRecentAddressesInComposer );
+ connect( mShowRecentAddressesInComposer, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // a checkbox for "word wrap" and a spinbox for the column in
+ // which to wrap:
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mWordWrapCheck = new QCheckBox(
+ GlobalSettings::self()->wordWrapItem()->label(),
+ this, "kcfg_WordWrap" );
+ hlay->addWidget( mWordWrapCheck );
+ connect( mWordWrapCheck, SIGNAL( stateChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mWrapColumnSpin = new KIntSpinBox( 30/*min*/, 78/*max*/, 1/*step*/,
+ 78/*init*/, 10 /*base*/, this, "kcfg_LineWrapWidth" );
+ mWrapColumnSpin->setEnabled( false ); // since !mWordWrapCheck->isChecked()
+ connect( mWrapColumnSpin, SIGNAL( valueChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hlay->addWidget( mWrapColumnSpin );
+ hlay->addStretch( 1 );
+ // only enable the spinbox if the checkbox is checked:
+ connect( mWordWrapCheck, SIGNAL(toggled(bool)),
+ mWrapColumnSpin, SLOT(setEnabled(bool)) );
+
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mAutoSave = new KIntSpinBox( 0, 60, 1, 1, 10, this, "kcfg_AutosaveInterval" );
+ label = new QLabel( mAutoSave,
+ GlobalSettings::self()->autosaveIntervalItem()->label(), this );
+ hlay->addWidget( label );
+ hlay->addWidget( mAutoSave );
+ mAutoSave->setSpecialValueText( i18n("No autosave") );
+ mAutoSave->setSuffix( i18n(" min") );
+ hlay->addStretch( 1 );
+ connect( mAutoSave, SIGNAL( valueChanged(int) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ QPushButton *completionOrderBtn = new QPushButton( i18n( "Configure Completion Order" ), this );
+ connect( completionOrderBtn, SIGNAL( clicked() ),
+ this, SLOT( slotConfigureCompletionOrder() ) );
+ hlay->addWidget( completionOrderBtn );
+ hlay->addItem( new QSpacerItem(0, 0) );
+
+ // recent addresses
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ QPushButton *recentAddressesBtn = new QPushButton( i18n( "Edit Recent Addresses..." ), this );
+ connect( recentAddressesBtn, SIGNAL( clicked() ),
+ this, SLOT( slotConfigureRecentAddresses() ) );
+ hlay->addWidget( recentAddressesBtn );
+ hlay->addItem( new QSpacerItem(0, 0) );
+
+ // The "external editor" group:
+ group = new QVGroupBox( i18n("External Editor"), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ mExternalEditorCheck = new QCheckBox(
+ GlobalSettings::self()->useExternalEditorItem()->label(),
+ group, "kcfg_UseExternalEditor" );
+ connect( mExternalEditorCheck, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hbox = new QHBox( group );
+ label = new QLabel( GlobalSettings::self()->externalEditorItem()->label(),
+ hbox );
+ mEditorRequester = new KURLRequester( hbox, "kcfg_ExternalEditor" );
+ connect( mEditorRequester, SIGNAL( urlSelected(const QString&) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mEditorRequester, SIGNAL( textChanged(const QString&) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hbox->setStretchFactor( mEditorRequester, 1 );
+ label->setBuddy( mEditorRequester );
+ label->setEnabled( false ); // since !mExternalEditorCheck->isChecked()
+ // ### FIXME: allow only executables (x-bit when available..)
+ mEditorRequester->setFilter( "application/x-executable "
+ "application/x-shellscript "
+ "application/x-desktop" );
+ mEditorRequester->setEnabled( false ); // !mExternalEditorCheck->isChecked()
+ connect( mExternalEditorCheck, SIGNAL(toggled(bool)),
+ label, SLOT(setEnabled(bool)) );
+ connect( mExternalEditorCheck, SIGNAL(toggled(bool)),
+ mEditorRequester, SLOT(setEnabled(bool)) );
+
+ label = new QLabel( i18n("<b>%f</b> will be replaced with the "
+ "filename to edit."), group );
+ label->setEnabled( false ); // see above
+ connect( mExternalEditorCheck, SIGNAL(toggled(bool)),
+ label, SLOT(setEnabled(bool)) );
+
+ vlay->addWidget( group );
+ vlay->addStretch( 100 );
+}
+
+void ComposerPage::GeneralTab::doLoadFromGlobalSettings() {
+ // various check boxes:
+
+ mAutoAppSignFileCheck->setChecked(
+ GlobalSettings::self()->autoTextSignature()=="auto" );
+ mTopQuoteCheck->setChecked( GlobalSettings::self()->prependSignature() );
+ mSmartQuoteCheck->setChecked( GlobalSettings::self()->smartQuote() );
+ mAutoRequestMDNCheck->setChecked( GlobalSettings::self()->requestMDN() );
+ mWordWrapCheck->setChecked( GlobalSettings::self()->wordWrap() );
+
+ mWrapColumnSpin->setValue( GlobalSettings::self()->lineWrapWidth() );
+ mAutoSave->setValue( GlobalSettings::self()->autosaveInterval() );
+
+ // editor group:
+ mExternalEditorCheck->setChecked( GlobalSettings::self()->useExternalEditor() );
+ mEditorRequester->setURL( GlobalSettings::self()->externalEditor() );
+}
+
+void ComposerPage::GeneralTab::installProfile( KConfig * profile ) {
+ KConfigGroup composer( profile, "Composer" );
+ KConfigGroup general( profile, "General" );
+
+ if ( composer.hasKey( "signature" ) ) {
+ bool state = composer.readBoolEntry("signature");
+ mAutoAppSignFileCheck->setChecked( state );
+ }
+ if ( composer.hasKey( "prepend-signature" ) )
+ mTopQuoteCheck->setChecked( composer.readBoolEntry( "prepend-signature" ) );
+ if ( composer.hasKey( "smart-quote" ) )
+ mSmartQuoteCheck->setChecked( composer.readBoolEntry( "smart-quote" ) );
+ if ( composer.hasKey( "request-mdn" ) )
+ mAutoRequestMDNCheck->setChecked( composer.readBoolEntry( "request-mdn" ) );
+ if ( composer.hasKey( "word-wrap" ) )
+ mWordWrapCheck->setChecked( composer.readBoolEntry( "word-wrap" ) );
+ if ( composer.hasKey( "break-at" ) )
+ mWrapColumnSpin->setValue( composer.readNumEntry( "break-at" ) );
+ if ( composer.hasKey( "autosave" ) )
+ mAutoSave->setValue( composer.readNumEntry( "autosave" ) );
+
+ if ( general.hasKey( "use-external-editor" )
+ && general.hasKey( "external-editor" ) ) {
+ mExternalEditorCheck->setChecked( general.readBoolEntry( "use-external-editor" ) );
+ mEditorRequester->setURL( general.readPathEntry( "external-editor" ) );
+ }
+}
+
+void ComposerPage::GeneralTab::save() {
+ GlobalSettings::self()->setAutoTextSignature(
+ mAutoAppSignFileCheck->isChecked() ? "auto" : "manual" );
+ GlobalSettings::self()->setPrependSignature( mTopQuoteCheck->isChecked());
+ GlobalSettings::self()->setSmartQuote( mSmartQuoteCheck->isChecked() );
+ GlobalSettings::self()->setRequestMDN( mAutoRequestMDNCheck->isChecked() );
+ GlobalSettings::self()->setWordWrap( mWordWrapCheck->isChecked() );
+
+ GlobalSettings::self()->setLineWrapWidth( mWrapColumnSpin->value() );
+ GlobalSettings::self()->setAutosaveInterval( mAutoSave->value() );
+
+ // editor group:
+ GlobalSettings::self()->setUseExternalEditor( mExternalEditorCheck->isChecked() );
+ GlobalSettings::self()->setExternalEditor( mEditorRequester->url() );
+}
+
+void ComposerPage::GeneralTab::slotConfigureRecentAddresses( )
+{
+ KRecentAddress::RecentAddressDialog dlg( this );
+ dlg.setAddresses( RecentAddresses::self( KMKernel::config() )->addresses() );
+ if ( dlg.exec() ) {
+ RecentAddresses::self( KMKernel::config() )->clear();
+ const QStringList &addrList = dlg.addresses();
+ QStringList::ConstIterator it;
+ for ( it = addrList.constBegin(); it != addrList.constEnd(); ++it )
+ RecentAddresses::self( KMKernel::config() )->add( *it );
+ }
+}
+
+void ComposerPage::GeneralTab::slotConfigureCompletionOrder( )
+{
+ KPIM::LdapSearch search;
+ KPIM::CompletionOrderEditor editor( &search, this );
+ editor.exec();
+}
+
+QString ComposerPage::PhrasesTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-phrases");
+}
+
+ComposerPagePhrasesTab::ComposerPagePhrasesTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QGridLayout *glay;
+ QPushButton *button;
+
+ glay = new QGridLayout( this, 7, 3, KDialog::spacingHint() );
+ glay->setMargin( KDialog::marginHint() );
+ glay->setColStretch( 1, 1 );
+ glay->setColStretch( 2, 1 );
+ glay->setRowStretch( 7, 1 );
+
+ // row 0: help text
+ glay->addMultiCellWidget( new QLabel( i18n("<qt>The following placeholders are "
+ "supported in the reply phrases:<br>"
+ "<b>%D</b>: date, <b>%S</b>: subject,<br>"
+ "<b>%e</b>: sender's address, <b>%F</b>: sender's name, <b>%f</b>: sender's initials,<br>"
+ "<b>%T</b>: recipient's name, <b>%t</b>: recipient's name and address,<br>"
+ "<b>%C</b>: carbon copy names, <b>%c</b>: carbon copy names and addresses,<br>"
+ "<b>%%</b>: percent sign, <b>%_</b>: space, "
+ "<b>%L</b>: linebreak</qt>"), this ),
+ 0, 0, 0, 2 ); // row 0; cols 0..2
+
+ // row 1: label and language combo box:
+ mPhraseLanguageCombo = new LanguageComboBox( false, this );
+ glay->addWidget( new QLabel( mPhraseLanguageCombo,
+ i18n("Lang&uage:"), this ), 1, 0 );
+ glay->addMultiCellWidget( mPhraseLanguageCombo, 1, 1, 1, 2 );
+ connect( mPhraseLanguageCombo, SIGNAL(activated(const QString&)),
+ this, SLOT(slotLanguageChanged(const QString&)) );
+
+ // row 2: "add..." and "remove" push buttons:
+ button = new QPushButton( i18n("A&dd..."), this );
+ button->setAutoDefault( false );
+ glay->addWidget( button, 2, 1 );
+ mRemoveButton = new QPushButton( i18n("Re&move"), this );
+ mRemoveButton->setAutoDefault( false );
+ mRemoveButton->setEnabled( false ); // combo doesn't contain anything...
+ glay->addWidget( mRemoveButton, 2, 2 );
+ connect( button, SIGNAL(clicked()),
+ this, SLOT(slotNewLanguage()) );
+ connect( mRemoveButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveLanguage()) );
+
+ // row 3: "reply to sender" line edit and label:
+ mPhraseReplyEdit = new KLineEdit( this );
+ connect( mPhraseReplyEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ glay->addWidget( new QLabel( mPhraseReplyEdit,
+ i18n("Reply to se&nder:"), this ), 3, 0 );
+ glay->addMultiCellWidget( mPhraseReplyEdit, 3, 3, 1, 2 ); // cols 1..2
+
+ // row 4: "reply to all" line edit and label:
+ mPhraseReplyAllEdit = new KLineEdit( this );
+ connect( mPhraseReplyAllEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ glay->addWidget( new QLabel( mPhraseReplyAllEdit,
+ i18n("Repl&y to all:"), this ), 4, 0 );
+ glay->addMultiCellWidget( mPhraseReplyAllEdit, 4, 4, 1, 2 ); // cols 1..2
+
+ // row 5: "forward" line edit and label:
+ mPhraseForwardEdit = new KLineEdit( this );
+ connect( mPhraseForwardEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ glay->addWidget( new QLabel( mPhraseForwardEdit,
+ i18n("&Forward:"), this ), 5, 0 );
+ glay->addMultiCellWidget( mPhraseForwardEdit, 5, 5, 1, 2 ); // cols 1..2
+
+ // row 6: "quote indicator" line edit and label:
+ mPhraseIndentPrefixEdit = new KLineEdit( this );
+ connect( mPhraseIndentPrefixEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ glay->addWidget( new QLabel( mPhraseIndentPrefixEdit,
+ i18n("&Quote indicator:"), this ), 6, 0 );
+ glay->addMultiCellWidget( mPhraseIndentPrefixEdit, 6, 6, 1, 2 );
+
+ // row 7: spacer
+}
+
+
+void ComposerPage::PhrasesTab::setLanguageItemInformation( int index ) {
+ assert( 0 <= index && index < (int)mLanguageList.count() );
+
+ LanguageItem &l = *mLanguageList.at( index );
+
+ mPhraseReplyEdit->setText( l.mReply );
+ mPhraseReplyAllEdit->setText( l.mReplyAll );
+ mPhraseForwardEdit->setText( l.mForward );
+ mPhraseIndentPrefixEdit->setText( l.mIndentPrefix );
+}
+
+void ComposerPage::PhrasesTab::saveActiveLanguageItem() {
+ int index = mActiveLanguageItem;
+ if (index == -1) return;
+ assert( 0 <= index && index < (int)mLanguageList.count() );
+
+ LanguageItem &l = *mLanguageList.at( index );
+
+ l.mReply = mPhraseReplyEdit->text();
+ l.mReplyAll = mPhraseReplyAllEdit->text();
+ l.mForward = mPhraseForwardEdit->text();
+ l.mIndentPrefix = mPhraseIndentPrefixEdit->text();
+}
+
+void ComposerPage::PhrasesTab::slotNewLanguage()
+{
+ NewLanguageDialog dialog( mLanguageList, parentWidget(), "New", true );
+ if ( dialog.exec() == QDialog::Accepted ) slotAddNewLanguage( dialog.language() );
+}
+
+void ComposerPage::PhrasesTab::slotAddNewLanguage( const QString& lang )
+{
+ mPhraseLanguageCombo->setCurrentItem(
+ mPhraseLanguageCombo->insertLanguage( lang ) );
+ KLocale locale("kmail");
+ locale.setLanguage( lang );
+ mLanguageList.append(
+ LanguageItem( lang,
+ locale.translate("On %D, you wrote:"),
+ locale.translate("On %D, %F wrote:"),
+ locale.translate("Forwarded Message"),
+ locale.translate(">%_") ) );
+ mRemoveButton->setEnabled( true );
+ slotLanguageChanged( QString::null );
+}
+
+void ComposerPage::PhrasesTab::slotRemoveLanguage()
+{
+ assert( mPhraseLanguageCombo->count() > 1 );
+ int index = mPhraseLanguageCombo->currentItem();
+ assert( 0 <= index && index < (int)mLanguageList.count() );
+
+ // remove current item from internal list and combobox:
+ mLanguageList.remove( mLanguageList.at( index ) );
+ mPhraseLanguageCombo->removeItem( index );
+
+ if ( index >= (int)mLanguageList.count() ) index--;
+
+ mActiveLanguageItem = index;
+ setLanguageItemInformation( index );
+ mRemoveButton->setEnabled( mLanguageList.count() > 1 );
+ emit changed( true );
+}
+
+void ComposerPage::PhrasesTab::slotLanguageChanged( const QString& )
+{
+ int index = mPhraseLanguageCombo->currentItem();
+ assert( index < (int)mLanguageList.count() );
+ saveActiveLanguageItem();
+ mActiveLanguageItem = index;
+ setLanguageItemInformation( index );
+ emit changed( true );
+}
+
+
+void ComposerPage::PhrasesTab::doLoadFromGlobalSettings() {
+ mLanguageList.clear();
+ mPhraseLanguageCombo->clear();
+ mActiveLanguageItem = -1;
+
+ int numLang = GlobalSettings::self()->replyLanguagesCount();
+ int currentNr = GlobalSettings::self()->replyCurrentLanguage();
+
+ // build mLanguageList and mPhraseLanguageCombo:
+ for ( int i = 0 ; i < numLang ; i++ ) {
+ ReplyPhrases replyPhrases( QString::number(i) );
+ replyPhrases.readConfig();
+ QString lang = replyPhrases.language();
+ mLanguageList.append(
+ LanguageItem( lang,
+ replyPhrases.phraseReplySender(),
+ replyPhrases.phraseReplyAll(),
+ replyPhrases.phraseForward(),
+ replyPhrases.indentPrefix() ) );
+ mPhraseLanguageCombo->insertLanguage( lang );
+ }
+
+ if ( currentNr >= numLang || currentNr < 0 )
+ currentNr = 0;
+
+ if ( numLang == 0 ) {
+ slotAddNewLanguage( KGlobal::locale()->language() );
+ }
+
+ mPhraseLanguageCombo->setCurrentItem( currentNr );
+ mActiveLanguageItem = currentNr;
+ setLanguageItemInformation( currentNr );
+ mRemoveButton->setEnabled( mLanguageList.count() > 1 );
+}
+
+void ComposerPage::PhrasesTab::save() {
+ GlobalSettings::self()->setReplyLanguagesCount( mLanguageList.count() );
+ GlobalSettings::self()->setReplyCurrentLanguage( mPhraseLanguageCombo->currentItem() );
+
+ saveActiveLanguageItem();
+ LanguageItemList::Iterator it = mLanguageList.begin();
+ for ( int i = 0 ; it != mLanguageList.end() ; ++it, ++i ) {
+ ReplyPhrases replyPhrases( QString::number(i) );
+ replyPhrases.setLanguage( (*it).mLanguage );
+ replyPhrases.setPhraseReplySender( (*it).mReply );
+ replyPhrases.setPhraseReplyAll( (*it).mReplyAll );
+ replyPhrases.setPhraseForward( (*it).mForward );
+ replyPhrases.setIndentPrefix( (*it).mIndentPrefix );
+ replyPhrases.writeConfig();
+ }
+}
+
+QString ComposerPage::TemplatesTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-templates");
+}
+
+ComposerPageTemplatesTab::ComposerPageTemplatesTab( QWidget * parent, const char * name )
+ : ConfigModuleTab ( parent, name )
+{
+ QVBoxLayout* vlay = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ mWidget = new TemplatesConfiguration( this );
+ vlay->addWidget( mWidget );
+
+ connect( mWidget, SIGNAL( changed() ),
+ this, SLOT( slotEmitChanged( void ) ) );
+}
+
+void ComposerPage::TemplatesTab::doLoadFromGlobalSettings() {
+ mWidget->loadFromGlobal();
+}
+
+void ComposerPage::TemplatesTab::save() {
+ mWidget->saveToGlobal();
+}
+
+QString ComposerPage::CustomTemplatesTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-custom-templates");
+}
+
+ComposerPageCustomTemplatesTab::ComposerPageCustomTemplatesTab( QWidget * parent, const char * name )
+ : ConfigModuleTab ( parent, name )
+{
+ QVBoxLayout* vlay = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ mWidget = new CustomTemplates( this );
+ vlay->addWidget( mWidget );
+
+ connect( mWidget, SIGNAL( changed() ),
+ this, SLOT( slotEmitChanged( void ) ) );
+}
+
+void ComposerPage::CustomTemplatesTab::doLoadFromGlobalSettings() {
+ mWidget->load();
+}
+
+void ComposerPage::CustomTemplatesTab::save() {
+ mWidget->save();
+}
+
+QString ComposerPage::SubjectTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-subject");
+}
+
+ComposerPageSubjectTab::ComposerPageSubjectTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QGroupBox *group;
+ QLabel *label;
+
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ group = new QVGroupBox( i18n("Repl&y Subject Prefixes"), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ // row 0: help text:
+ label = new QLabel( i18n("Recognize any sequence of the following prefixes\n"
+ "(entries are case-insensitive regular expressions):"), group );
+ label->setAlignment( AlignLeft|WordBreak );
+
+ // row 1, string list editor:
+ SimpleStringListEditor::ButtonCode buttonCode =
+ static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
+ mReplyListEditor =
+ new SimpleStringListEditor( group, 0, buttonCode,
+ i18n("A&dd..."), i18n("Re&move"),
+ i18n("Mod&ify..."),
+ i18n("Enter new reply prefix:") );
+ connect( mReplyListEditor, SIGNAL( changed( void ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // row 2: "replace [...]" check box:
+ mReplaceReplyPrefixCheck = new QCheckBox(
+ GlobalSettings::self()->replaceReplyPrefixItem()->label(),
+ group, "kcfg_ReplaceReplyPrefix" );
+ connect( mReplaceReplyPrefixCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ vlay->addWidget( group );
+
+
+ group = new QVGroupBox( i18n("For&ward Subject Prefixes"), this );
+ group->layout()->setSpacing( KDialog::marginHint() );
+
+ // row 0: help text:
+ label= new QLabel( i18n("Recognize any sequence of the following prefixes\n"
+ "(entries are case-insensitive regular expressions):"), group );
+ label->setAlignment( AlignLeft|WordBreak );
+
+ // row 1: string list editor
+ mForwardListEditor =
+ new SimpleStringListEditor( group, 0, buttonCode,
+ i18n("Add..."),
+ i18n("Remo&ve"),
+ i18n("Modify..."),
+ i18n("Enter new forward prefix:") );
+ connect( mForwardListEditor, SIGNAL( changed( void ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // row 3: "replace [...]" check box:
+ mReplaceForwardPrefixCheck = new QCheckBox(
+ GlobalSettings::self()->replaceForwardPrefixItem()->label(),
+ group, "kcfg_ReplaceForwardPrefix" );
+ connect( mReplaceForwardPrefixCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ vlay->addWidget( group );
+}
+
+void ComposerPage::SubjectTab::doLoadFromGlobalSettings() {
+ mReplyListEditor->setStringList( GlobalSettings::self()->replyPrefixes() );
+ mReplaceReplyPrefixCheck->setChecked( GlobalSettings::self()->replaceReplyPrefix() );
+ mForwardListEditor->setStringList( GlobalSettings::self()->forwardPrefixes() );
+ mReplaceForwardPrefixCheck->setChecked( GlobalSettings::self()->replaceForwardPrefix() );
+}
+
+void ComposerPage::SubjectTab::save() {
+ GlobalSettings::self()->setReplyPrefixes( mReplyListEditor->stringList() );
+ GlobalSettings::self()->setForwardPrefixes( mForwardListEditor->stringList() );
+}
+
+QString ComposerPage::CharsetTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-charset");
+}
+
+ComposerPageCharsetTab::ComposerPageCharsetTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QLabel *label;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ label = new QLabel( i18n("This list is checked for every outgoing message "
+ "from the top to the bottom for a charset that "
+ "contains all required characters."), this );
+ label->setAlignment( WordBreak);
+ vlay->addWidget( label );
+
+ mCharsetListEditor =
+ new SimpleStringListEditor( this, 0, SimpleStringListEditor::All,
+ i18n("A&dd..."), i18n("Remo&ve"),
+ i18n("&Modify..."), i18n("Enter charset:") );
+ connect( mCharsetListEditor, SIGNAL( changed( void ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ vlay->addWidget( mCharsetListEditor, 1 );
+
+ mKeepReplyCharsetCheck = new QCheckBox( i18n("&Keep original charset when "
+ "replying or forwarding (if "
+ "possible)"), this );
+ connect( mKeepReplyCharsetCheck, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ vlay->addWidget( mKeepReplyCharsetCheck );
+
+ connect( mCharsetListEditor, SIGNAL(aboutToAdd(QString&)),
+ this, SLOT(slotVerifyCharset(QString&)) );
+}
+
+void ComposerPage::CharsetTab::slotVerifyCharset( QString & charset ) {
+ if ( charset.isEmpty() ) return;
+
+ // KCharsets::codecForName("us-ascii") returns "iso-8859-1" (cf. Bug #49812)
+ // therefore we have to treat this case specially
+ if ( charset.lower() == QString::fromLatin1("us-ascii") ) {
+ charset = QString::fromLatin1("us-ascii");
+ return;
+ }
+
+ if ( charset.lower() == QString::fromLatin1("locale") ) {
+ charset = QString::fromLatin1("%1 (locale)")
+ .arg( QCString( kmkernel->networkCodec()->mimeName() ).lower() );
+ return;
+ }
+
+ bool ok = false;
+ QTextCodec *codec = KGlobal::charsets()->codecForName( charset, ok );
+ if ( ok && codec ) {
+ charset = QString::fromLatin1( codec->mimeName() ).lower();
+ return;
+ }
+
+ KMessageBox::sorry( this, i18n("This charset is not supported.") );
+ charset = QString::null;
+}
+
+void ComposerPage::CharsetTab::doLoadOther() {
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ QStringList charsets = composer.readListEntry( "pref-charsets" );
+ for ( QStringList::Iterator it = charsets.begin() ;
+ it != charsets.end() ; ++it )
+ if ( (*it) == QString::fromLatin1("locale") ) {
+ QCString cset = kmkernel->networkCodec()->mimeName();
+ KPIM::kAsciiToLower( cset.data() );
+ (*it) = QString("%1 (locale)").arg( cset );
+ }
+
+ mCharsetListEditor->setStringList( charsets );
+ mKeepReplyCharsetCheck->setChecked( !composer.readBoolEntry( "force-reply-charset", false ) );
+}
+
+void ComposerPage::CharsetTab::save() {
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ QStringList charsetList = mCharsetListEditor->stringList();
+ QStringList::Iterator it = charsetList.begin();
+ for ( ; it != charsetList.end() ; ++it )
+ if ( (*it).endsWith("(locale)") )
+ (*it) = "locale";
+ composer.writeEntry( "pref-charsets", charsetList );
+ composer.writeEntry( "force-reply-charset",
+ !mKeepReplyCharsetCheck->isChecked() );
+}
+
+QString ComposerPage::HeadersTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-headers");
+}
+
+ComposerPageHeadersTab::ComposerPageHeadersTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QHBoxLayout *hlay;
+ QGridLayout *glay;
+ QLabel *label;
+ QPushButton *button;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "Use custom Message-Id suffix" checkbox:
+ mCreateOwnMessageIdCheck =
+ new QCheckBox( i18n("&Use custom message-id suffix"), this );
+ connect( mCreateOwnMessageIdCheck, SIGNAL ( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ vlay->addWidget( mCreateOwnMessageIdCheck );
+
+ // "Message-Id suffix" line edit and label:
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mMessageIdSuffixEdit = new KLineEdit( this );
+ // only ASCII letters, digits, plus, minus and dots are allowed
+ mMessageIdSuffixValidator =
+ new QRegExpValidator( QRegExp( "[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*" ), this );
+ mMessageIdSuffixEdit->setValidator( mMessageIdSuffixValidator );
+ label = new QLabel( mMessageIdSuffixEdit,
+ i18n("Custom message-&id suffix:"), this );
+ label->setEnabled( false ); // since !mCreateOwnMessageIdCheck->isChecked()
+ mMessageIdSuffixEdit->setEnabled( false );
+ hlay->addWidget( label );
+ hlay->addWidget( mMessageIdSuffixEdit, 1 );
+ connect( mCreateOwnMessageIdCheck, SIGNAL(toggled(bool) ),
+ label, SLOT(setEnabled(bool)) );
+ connect( mCreateOwnMessageIdCheck, SIGNAL(toggled(bool) ),
+ mMessageIdSuffixEdit, SLOT(setEnabled(bool)) );
+ connect( mMessageIdSuffixEdit, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // horizontal rule and "custom header fields" label:
+ vlay->addWidget( new KSeparator( KSeparator::HLine, this ) );
+ vlay->addWidget( new QLabel( i18n("Define custom mime header fields:"), this) );
+
+ // "custom header fields" listbox:
+ glay = new QGridLayout( vlay, 5, 3 ); // inherits spacing
+ glay->setRowStretch( 2, 1 );
+ glay->setColStretch( 1, 1 );
+ mTagList = new ListView( this, "tagList" );
+ mTagList->addColumn( i18n("Name") );
+ mTagList->addColumn( i18n("Value") );
+ mTagList->setAllColumnsShowFocus( true );
+ mTagList->setSorting( -1 );
+ connect( mTagList, SIGNAL(selectionChanged()),
+ this, SLOT(slotMimeHeaderSelectionChanged()) );
+ glay->addMultiCellWidget( mTagList, 0, 2, 0, 1 );
+
+ // "new" and "remove" buttons:
+ button = new QPushButton( i18n("Ne&w"), this );
+ connect( button, SIGNAL(clicked()), this, SLOT(slotNewMimeHeader()) );
+ button->setAutoDefault( false );
+ glay->addWidget( button, 0, 2 );
+ mRemoveHeaderButton = new QPushButton( i18n("Re&move"), this );
+ connect( mRemoveHeaderButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveMimeHeader()) );
+ button->setAutoDefault( false );
+ glay->addWidget( mRemoveHeaderButton, 1, 2 );
+
+ // "name" and "value" line edits and labels:
+ mTagNameEdit = new KLineEdit( this );
+ mTagNameEdit->setEnabled( false );
+ mTagNameLabel = new QLabel( mTagNameEdit, i18n("&Name:"), this );
+ mTagNameLabel->setEnabled( false );
+ glay->addWidget( mTagNameLabel, 3, 0 );
+ glay->addWidget( mTagNameEdit, 3, 1 );
+ connect( mTagNameEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotMimeHeaderNameChanged(const QString&)) );
+
+ mTagValueEdit = new KLineEdit( this );
+ mTagValueEdit->setEnabled( false );
+ mTagValueLabel = new QLabel( mTagValueEdit, i18n("&Value:"), this );
+ mTagValueLabel->setEnabled( false );
+ glay->addWidget( mTagValueLabel, 4, 0 );
+ glay->addWidget( mTagValueEdit, 4, 1 );
+ connect( mTagValueEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotMimeHeaderValueChanged(const QString&)) );
+}
+
+void ComposerPage::HeadersTab::slotMimeHeaderSelectionChanged()
+{
+ QListViewItem * item = mTagList->selectedItem();
+
+ if ( item ) {
+ mTagNameEdit->setText( item->text( 0 ) );
+ mTagValueEdit->setText( item->text( 1 ) );
+ } else {
+ mTagNameEdit->clear();
+ mTagValueEdit->clear();
+ }
+ mRemoveHeaderButton->setEnabled( item );
+ mTagNameEdit->setEnabled( item );
+ mTagValueEdit->setEnabled( item );
+ mTagNameLabel->setEnabled( item );
+ mTagValueLabel->setEnabled( item );
+}
+
+
+void ComposerPage::HeadersTab::slotMimeHeaderNameChanged( const QString & text ) {
+ // is called on ::setup(), when clearing the line edits. So be
+ // prepared to not find a selection:
+ QListViewItem * item = mTagList->selectedItem();
+ if ( item )
+ item->setText( 0, text );
+ emit changed( true );
+}
+
+
+void ComposerPage::HeadersTab::slotMimeHeaderValueChanged( const QString & text ) {
+ // is called on ::setup(), when clearing the line edits. So be
+ // prepared to not find a selection:
+ QListViewItem * item = mTagList->selectedItem();
+ if ( item )
+ item->setText( 1, text );
+ emit changed( true );
+}
+
+
+void ComposerPage::HeadersTab::slotNewMimeHeader()
+{
+ QListViewItem *listItem = new QListViewItem( mTagList );
+ mTagList->setCurrentItem( listItem );
+ mTagList->setSelected( listItem, true );
+ emit changed( true );
+}
+
+
+void ComposerPage::HeadersTab::slotRemoveMimeHeader()
+{
+ // calling this w/o selection is a programming error:
+ QListViewItem * item = mTagList->selectedItem();
+ if ( !item ) {
+ kdDebug(5006) << "==================================================\n"
+ << "Error: Remove button was pressed although no custom header was selected\n"
+ << "==================================================\n";
+ return;
+ }
+
+ QListViewItem * below = item->nextSibling();
+ delete item;
+
+ if ( below )
+ mTagList->setSelected( below, true );
+ else if ( mTagList->lastItem() )
+ mTagList->setSelected( mTagList->lastItem(), true );
+ emit changed( true );
+}
+
+void ComposerPage::HeadersTab::doLoadOther() {
+ KConfigGroup general( KMKernel::config(), "General" );
+
+ QString suffix = general.readEntry( "myMessageIdSuffix" );
+ mMessageIdSuffixEdit->setText( suffix );
+ bool state = ( !suffix.isEmpty() &&
+ general.readBoolEntry( "useCustomMessageIdSuffix", false ) );
+ mCreateOwnMessageIdCheck->setChecked( state );
+
+ mTagList->clear();
+ mTagNameEdit->clear();
+ mTagValueEdit->clear();
+
+ QListViewItem * item = 0;
+
+ int count = general.readNumEntry( "mime-header-count", 0 );
+ for( int i = 0 ; i < count ; i++ ) {
+ KConfigGroup config( KMKernel::config(),
+ QCString("Mime #") + QCString().setNum(i) );
+ QString name = config.readEntry( "name" );
+ QString value = config.readEntry( "value" );
+ if( !name.isEmpty() )
+ item = new QListViewItem( mTagList, item, name, value );
+ }
+ if ( mTagList->childCount() ) {
+ mTagList->setCurrentItem( mTagList->firstChild() );
+ mTagList->setSelected( mTagList->firstChild(), true );
+ }
+ else {
+ // disable the "Remove" button
+ mRemoveHeaderButton->setEnabled( false );
+ }
+}
+
+void ComposerPage::HeadersTab::save() {
+ KConfigGroup general( KMKernel::config(), "General" );
+
+ general.writeEntry( "useCustomMessageIdSuffix",
+ mCreateOwnMessageIdCheck->isChecked() );
+ general.writeEntry( "myMessageIdSuffix",
+ mMessageIdSuffixEdit->text() );
+
+ int numValidEntries = 0;
+ QListViewItem * item = mTagList->firstChild();
+ for ( ; item ; item = item->itemBelow() )
+ if( !item->text(0).isEmpty() ) {
+ KConfigGroup config( KMKernel::config(), QCString("Mime #")
+ + QCString().setNum( numValidEntries ) );
+ config.writeEntry( "name", item->text( 0 ) );
+ config.writeEntry( "value", item->text( 1 ) );
+ numValidEntries++;
+ }
+ general.writeEntry( "mime-header-count", numValidEntries );
+}
+
+QString ComposerPage::AttachmentsTab::helpAnchor() const {
+ return QString::fromLatin1("configure-composer-attachments");
+}
+
+ComposerPageAttachmentsTab::ComposerPageAttachmentsTab( QWidget * parent,
+ const char * name )
+ : ConfigModuleTab( parent, name ) {
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QLabel *label;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "Outlook compatible attachment naming" check box
+ mOutlookCompatibleCheck =
+ new QCheckBox( i18n( "Outlook-compatible attachment naming" ), this );
+ mOutlookCompatibleCheck->setChecked( false );
+ QToolTip::add( mOutlookCompatibleCheck, i18n(
+ "Turn this option on to make Outlook(tm) understand attachment names "
+ "containing non-English characters" ) );
+ connect( mOutlookCompatibleCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mOutlookCompatibleCheck, SIGNAL( clicked() ),
+ this, SLOT( slotOutlookCompatibleClicked() ) );
+ vlay->addWidget( mOutlookCompatibleCheck );
+ vlay->addSpacing( 5 );
+
+ // "Enable detection of missing attachments" check box
+ mMissingAttachmentDetectionCheck =
+ new QCheckBox( i18n("E&nable detection of missing attachments"), this );
+ mMissingAttachmentDetectionCheck->setChecked( true );
+ connect( mMissingAttachmentDetectionCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ vlay->addWidget( mMissingAttachmentDetectionCheck );
+
+ // "Attachment key words" label and string list editor
+ label = new QLabel( i18n("Recognize any of the following key words as "
+ "intention to attach a file:"), this );
+ label->setAlignment( AlignLeft|WordBreak );
+ vlay->addWidget( label );
+
+ SimpleStringListEditor::ButtonCode buttonCode =
+ static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify );
+ mAttachWordsListEditor =
+ new SimpleStringListEditor( this, 0, buttonCode,
+ i18n("A&dd..."), i18n("Re&move"),
+ i18n("Mod&ify..."),
+ i18n("Enter new key word:") );
+ connect( mAttachWordsListEditor, SIGNAL( changed( void ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ vlay->addWidget( mAttachWordsListEditor );
+
+ connect( mMissingAttachmentDetectionCheck, SIGNAL(toggled(bool) ),
+ label, SLOT(setEnabled(bool)) );
+ connect( mMissingAttachmentDetectionCheck, SIGNAL(toggled(bool) ),
+ mAttachWordsListEditor, SLOT(setEnabled(bool)) );
+}
+
+void ComposerPage::AttachmentsTab::doLoadFromGlobalSettings() {
+ mOutlookCompatibleCheck->setChecked(
+ GlobalSettings::self()->outlookCompatibleAttachments() );
+ mMissingAttachmentDetectionCheck->setChecked(
+ GlobalSettings::self()->showForgottenAttachmentWarning() );
+ QStringList attachWordsList = GlobalSettings::self()->attachmentKeywords();
+ if ( attachWordsList.isEmpty() ) {
+ // default value
+ attachWordsList << QString::fromLatin1("attachment")
+ << QString::fromLatin1("attached");
+ if ( QString::fromLatin1("attachment") != i18n("attachment") )
+ attachWordsList << i18n("attachment");
+ if ( QString::fromLatin1("attached") != i18n("attached") )
+ attachWordsList << i18n("attached");
+ }
+
+ mAttachWordsListEditor->setStringList( attachWordsList );
+}
+
+void ComposerPage::AttachmentsTab::save() {
+ GlobalSettings::self()->setOutlookCompatibleAttachments(
+ mOutlookCompatibleCheck->isChecked() );
+ GlobalSettings::self()->setShowForgottenAttachmentWarning(
+ mMissingAttachmentDetectionCheck->isChecked() );
+ GlobalSettings::self()->setAttachmentKeywords(
+ mAttachWordsListEditor->stringList() );
+}
+
+void ComposerPageAttachmentsTab::slotOutlookCompatibleClicked()
+{
+ if (mOutlookCompatibleCheck->isChecked()) {
+ KMessageBox::information(0,i18n("You have chosen to "
+ "encode attachment names containing non-English characters in a way that "
+ "is understood by Outlook(tm) and other mail clients that do not "
+ "support standard-compliant encoded attachment names.\n"
+ "Note that KMail may create non-standard compliant messages, "
+ "and consequently it is possible that your messages will not be "
+ "understood by standard-compliant mail clients; so, unless you have no "
+ "other choice, you should not enable this option." ) );
+ }
+}
+
+// *************************************************************
+// * *
+// * SecurityPage *
+// * *
+// *************************************************************
+QString SecurityPage::helpAnchor() const {
+ return QString::fromLatin1("configure-security");
+}
+
+SecurityPage::SecurityPage( QWidget * parent, const char * name )
+ : ConfigModuleWithTabs( parent, name )
+{
+ //
+ // "Reading" tab:
+ //
+ mGeneralTab = new GeneralTab(); // @TODO: rename
+ addTab( mGeneralTab, i18n("&Reading") );
+
+ //
+ // "Composing" tab:
+ //
+ mComposerCryptoTab = new ComposerCryptoTab();
+ addTab( mComposerCryptoTab, i18n("Composing") );
+
+ //
+ // "Warnings" tab:
+ //
+ mWarningTab = new WarningTab();
+ addTab( mWarningTab, i18n("Warnings") );
+
+ //
+ // "S/MIME Validation" tab:
+ //
+ mSMimeTab = new SMimeTab();
+ addTab( mSMimeTab, i18n("S/MIME &Validation") );
+
+ //
+ // "Crypto Backends" tab:
+ //
+ mCryptPlugTab = new CryptPlugTab();
+ addTab( mCryptPlugTab, i18n("Crypto Backe&nds") );
+ load();
+}
+
+
+void SecurityPage::installProfile( KConfig * profile ) {
+ mGeneralTab->installProfile( profile );
+ mComposerCryptoTab->installProfile( profile );
+ mWarningTab->installProfile( profile );
+ mSMimeTab->installProfile( profile );
+}
+
+QString SecurityPage::GeneralTab::helpAnchor() const {
+ return QString::fromLatin1("configure-security-reading");
+}
+
+SecurityPageGeneralTab::SecurityPageGeneralTab( QWidget * parent, const char * name )
+ : ConfigModuleTab ( parent, name )
+{
+ // tmp. vars:
+ QVBoxLayout *vlay;
+ QHBox *hbox;
+ QGroupBox *group;
+ QRadioButton *radio;
+ KActiveLabel *label;
+ QWidget *w;
+ QString msg;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // QWhat'sThis texts
+ QString htmlWhatsThis = i18n( "<qt><p>Messages sometimes come in both formats. "
+ "This option controls whether you want the HTML part or the plain "
+ "text part to be displayed.</p>"
+ "<p>Displaying the HTML part makes the message look better, "
+ "but at the same time increases the risk of security holes "
+ "being exploited.</p>"
+ "<p>Displaying the plain text part loses much of the message's "
+ "formatting, but makes it almost <em>impossible</em> "
+ "to exploit security holes in the HTML renderer (Konqueror).</p>"
+ "<p>The option below guards against one common misuse of HTML "
+ "messages, but it cannot guard against security issues that were "
+ "not known at the time this version of KMail was written.</p>"
+ "<p>It is therefore advisable to <em>not</em> prefer HTML to "
+ "plain text.</p>"
+ "<p><b>Note:</b> You can set this option on a per-folder basis "
+ "from the <i>Folder</i> menu of KMail's main window.</p></qt>" );
+
+ QString externalWhatsThis = i18n( "<qt><p>Some mail advertisements are in HTML "
+ "and contain references to, for example, images that the advertisers"
+ " employ to find out that you have read their message "
+ "(&quot;web bugs&quot;).</p>"
+ "<p>There is no valid reason to load images off the Internet like "
+ "this, since the sender can always attach the required images "
+ "directly to the message.</p>"
+ "<p>To guard from such a misuse of the HTML displaying feature "
+ "of KMail, this option is <em>disabled</em> by default.</p>"
+ "<p>However, if you wish to, for example, view images in HTML "
+ "messages that were not attached to it, you can enable this "
+ "option, but you should be aware of the possible problem.</p></qt>" );
+
+ QString receiptWhatsThis = i18n( "<qt><h3>Message Disposition "
+ "Notification Policy</h3>"
+ "<p>MDNs are a generalization of what is commonly called <b>read "
+ "receipt</b>. The message author requests a disposition "
+ "notification to be sent and the receiver's mail program "
+ "generates a reply from which the author can learn what "
+ "happened to his message. Common disposition types include "
+ "<b>displayed</b> (i.e. read), <b>deleted</b> and <b>dispatched</b> "
+ "(e.g. forwarded).</p>"
+ "<p>The following options are available to control KMail's "
+ "sending of MDNs:</p>"
+ "<ul>"
+ "<li><em>Ignore</em>: Ignores any request for disposition "
+ "notifications. No MDN will ever be sent automatically "
+ "(recommended).</li>"
+ "<li><em>Ask</em>: Answers requests only after asking the user "
+ "for permission. This way, you can send MDNs for selected "
+ "messages while denying or ignoring them for others.</li>"
+ "<li><em>Deny</em>: Always sends a <b>denied</b> notification. This "
+ "is only <em>slightly</em> better than always sending MDNs. "
+ "The author will still know that the messages has been acted "
+ "upon, he just cannot tell whether it was deleted or read etc.</li>"
+ "<li><em>Always send</em>: Always sends the requested "
+ "disposition notification. That means that the author of the "
+ "message gets to know when the message was acted upon and, "
+ "in addition, what happened to it (displayed, deleted, "
+ "etc.). This option is strongly discouraged, but since it "
+ "makes much sense e.g. for customer relationship management, "
+ "it has been made available.</li>"
+ "</ul></qt>" );
+
+
+ // "HTML Messages" group box:
+ group = new QVGroupBox( i18n( "HTML Messages" ), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ mHtmlMailCheck = new QCheckBox( i18n("Prefer H&TML to plain text"), group );
+ QWhatsThis::add( mHtmlMailCheck, htmlWhatsThis );
+ connect( mHtmlMailCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ mExternalReferences = new QCheckBox( i18n("Allow messages to load e&xternal "
+ "references from the Internet" ), group );
+ QWhatsThis::add( mExternalReferences, externalWhatsThis );
+ connect( mExternalReferences, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ label = new KActiveLabel( i18n("<b>WARNING:</b> Allowing HTML in email may "
+ "increase the risk that your system will be "
+ "compromised by present and anticipated security "
+ "exploits. <a href=\"whatsthis:%1\">More about "
+ "HTML mails...</a> <a href=\"whatsthis:%2\">More "
+ "about external references...</a>")
+ .arg(htmlWhatsThis).arg(externalWhatsThis),
+ group );
+
+ vlay->addWidget( group );
+
+ // encrypted messages group
+ group = new QVGroupBox( i18n("Encrypted Messages"), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+ mAlwaysDecrypt = new QCheckBox( i18n( "Attempt decryption of encrypted messages when viewing" ), group );
+ connect( mAlwaysDecrypt, SIGNAL(stateChanged(int)), this, SLOT(slotEmitChanged()) );
+ vlay->addWidget( group );
+
+ // "Message Disposition Notification" groupbox:
+ group = new QVGroupBox( i18n("Message Disposition Notifications"), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+
+ // "ignore", "ask", "deny", "always send" radiobutton line:
+ mMDNGroup = new QButtonGroup( group );
+ mMDNGroup->hide();
+ connect( mMDNGroup, SIGNAL( clicked( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ hbox = new QHBox( group );
+ hbox->setSpacing( KDialog::spacingHint() );
+
+ (void)new QLabel( i18n("Send policy:"), hbox );
+
+ radio = new QRadioButton( i18n("&Ignore"), hbox );
+ mMDNGroup->insert( radio );
+
+ radio = new QRadioButton( i18n("As&k"), hbox );
+ mMDNGroup->insert( radio );
+
+ radio = new QRadioButton( i18n("&Deny"), hbox );
+ mMDNGroup->insert( radio );
+
+ radio = new QRadioButton( i18n("Al&ways send"), hbox );
+ mMDNGroup->insert( radio );
+
+ for ( int i = 0 ; i < mMDNGroup->count() ; ++i )
+ QWhatsThis::add( mMDNGroup->find( i ), receiptWhatsThis );
+
+ w = new QWidget( hbox ); // spacer
+ hbox->setStretchFactor( w, 1 );
+
+ // "Original Message quote" radiobutton line:
+ mOrigQuoteGroup = new QButtonGroup( group );
+ mOrigQuoteGroup->hide();
+ connect( mOrigQuoteGroup, SIGNAL( clicked( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hbox = new QHBox( group );
+ hbox->setSpacing( KDialog::spacingHint() );
+
+ (void)new QLabel( i18n("Quote original message:"), hbox );
+
+ radio = new QRadioButton( i18n("Nothin&g"), hbox );
+ mOrigQuoteGroup->insert( radio );
+
+ radio = new QRadioButton( i18n("&Full message"), hbox );
+ mOrigQuoteGroup->insert( radio );
+
+ radio = new QRadioButton( i18n("Onl&y headers"), hbox );
+ mOrigQuoteGroup->insert( radio );
+
+ w = new QWidget( hbox );
+ hbox->setStretchFactor( w, 1 );
+
+ mNoMDNsWhenEncryptedCheck = new QCheckBox( i18n("Do not send MDNs in response to encrypted messages"), group );
+ connect( mNoMDNsWhenEncryptedCheck, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+
+ // Warning label:
+ label = new KActiveLabel( i18n("<b>WARNING:</b> Unconditionally returning "
+ "confirmations undermines your privacy. "
+ "<a href=\"whatsthis:%1\">More...</a>")
+ .arg(receiptWhatsThis),
+ group );
+
+ vlay->addWidget( group );
+
+ // "Attached keys" group box:
+ group = new QVGroupBox( i18n( "Certificate && Key Bundle Attachments" ), this );
+ group->layout()->setSpacing( KDialog::spacingHint() );
+
+ mAutomaticallyImportAttachedKeysCheck = new QCheckBox( i18n("Automatically import keys and certificates"), group );
+ connect( mAutomaticallyImportAttachedKeysCheck, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+
+ vlay->addWidget( group );
+
+
+
+ vlay->addStretch( 10 ); // spacer
+}
+
+void SecurityPage::GeneralTab::doLoadOther() {
+ const KConfigGroup reader( KMKernel::config(), "Reader" );
+
+ mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail", false ) );
+ mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal", false ) );
+ mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys", false ) );
+
+ mAlwaysDecrypt->setChecked( GlobalSettings::self()->alwaysDecrypt() );
+
+ const KConfigGroup mdn( KMKernel::config(), "MDN" );
+
+ int num = mdn.readNumEntry( "default-policy", 0 );
+ if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
+ mMDNGroup->setButton( num );
+ num = mdn.readNumEntry( "quote-message", 0 );
+ if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
+ mOrigQuoteGroup->setButton( num );
+ mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted", true ));
+}
+
+void SecurityPage::GeneralTab::installProfile( KConfig * profile ) {
+ const KConfigGroup reader( profile, "Reader" );
+ const KConfigGroup mdn( profile, "MDN" );
+
+ if ( reader.hasKey( "htmlMail" ) )
+ mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail" ) );
+ if ( reader.hasKey( "htmlLoadExternal" ) )
+ mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal" ) );
+ if ( reader.hasKey( "AutoImportKeys" ) )
+ mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys" ) );
+
+ if ( mdn.hasKey( "default-policy" ) ) {
+ int num = mdn.readNumEntry( "default-policy" );
+ if ( num < 0 || num >= mMDNGroup->count() ) num = 0;
+ mMDNGroup->setButton( num );
+ }
+ if ( mdn.hasKey( "quote-message" ) ) {
+ int num = mdn.readNumEntry( "quote-message" );
+ if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0;
+ mOrigQuoteGroup->setButton( num );
+ }
+ if ( mdn.hasKey( "not-send-when-encrypted" ) )
+ mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted" ));
+}
+
+void SecurityPage::GeneralTab::save() {
+ KConfigGroup reader( KMKernel::config(), "Reader" );
+ KConfigGroup mdn( KMKernel::config(), "MDN" );
+
+ if (reader.readBoolEntry( "htmlMail", false ) != mHtmlMailCheck->isChecked())
+ {
+ if (KMessageBox::warningContinueCancel(this, i18n("Changing the global "
+ "HTML setting will override all folder specific values."), QString::null,
+ KStdGuiItem::cont(), "htmlMailOverride") == KMessageBox::Continue)
+ {
+ reader.writeEntry( "htmlMail", mHtmlMailCheck->isChecked() );
+ QStringList names;
+ QValueList<QGuardedPtr<KMFolder> > folders;
+ kmkernel->folderMgr()->createFolderList(&names, &folders);
+ kmkernel->imapFolderMgr()->createFolderList(&names, &folders);
+ kmkernel->dimapFolderMgr()->createFolderList(&names, &folders);
+ kmkernel->searchFolderMgr()->createFolderList(&names, &folders);
+ for (QValueList<QGuardedPtr<KMFolder> >::iterator it = folders.begin();
+ it != folders.end(); ++it)
+ {
+ if (*it)
+ {
+ KConfigGroupSaver saver(KMKernel::config(),
+ "Folder-" + (*it)->idString());
+ KMKernel::config()->writeEntry("htmlMailOverride", false);
+ }
+ }
+ }
+ }
+ reader.writeEntry( "htmlLoadExternal", mExternalReferences->isChecked() );
+ reader.writeEntry( "AutoImportKeys", mAutomaticallyImportAttachedKeysCheck->isChecked() );
+ mdn.writeEntry( "default-policy", mMDNGroup->id( mMDNGroup->selected() ) );
+ mdn.writeEntry( "quote-message", mOrigQuoteGroup->id( mOrigQuoteGroup->selected() ) );
+ mdn.writeEntry( "not-send-when-encrypted", mNoMDNsWhenEncryptedCheck->isChecked() );
+ GlobalSettings::self()->setAlwaysDecrypt( mAlwaysDecrypt->isChecked() );
+}
+
+
+QString SecurityPage::ComposerCryptoTab::helpAnchor() const {
+ return QString::fromLatin1("configure-security-composing");
+}
+
+SecurityPageComposerCryptoTab::SecurityPageComposerCryptoTab( QWidget * parent, const char * name )
+ : ConfigModuleTab ( parent, name )
+{
+ // the margins are inside mWidget itself
+ QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 );
+
+ mWidget = new ComposerCryptoConfiguration( this );
+ connect( mWidget->mAutoSignature, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mEncToSelf, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mShowEncryptionResult, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mShowKeyApprovalDlg, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mAutoEncrypt, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mNeverEncryptWhenSavingInDrafts, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->mStoreEncrypted, SIGNAL( toggled(bool) ), this, SLOT( slotEmitChanged() ) );
+ vlay->addWidget( mWidget );
+}
+
+void SecurityPage::ComposerCryptoTab::doLoadOther() {
+ const KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ // If you change default values, sync messagecomposer.cpp too
+
+ mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign", false ) );
+
+ mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self", true ) );
+ mWidget->mShowEncryptionResult->setChecked( false ); //composer.readBoolEntry( "crypto-show-encryption-result", true ) );
+ mWidget->mShowEncryptionResult->hide();
+ mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval", true ) );
+
+ mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt", false ) );
+ mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts", true ) );
+
+ mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted", true ) );
+}
+
+void SecurityPage::ComposerCryptoTab::installProfile( KConfig * profile ) {
+ const KConfigGroup composer( profile, "Composer" );
+
+ if ( composer.hasKey( "pgp-auto-sign" ) )
+ mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign" ) );
+
+ if ( composer.hasKey( "crypto-encrypt-to-self" ) )
+ mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self" ) );
+ if ( composer.hasKey( "crypto-show-encryption-result" ) )
+ mWidget->mShowEncryptionResult->setChecked( composer.readBoolEntry( "crypto-show-encryption-result" ) );
+ if ( composer.hasKey( "crypto-show-keys-for-approval" ) )
+ mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval" ) );
+ if ( composer.hasKey( "pgp-auto-encrypt" ) )
+ mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt" ) );
+ if ( composer.hasKey( "never-encrypt-drafts" ) )
+ mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts" ) );
+
+ if ( composer.hasKey( "crypto-store-encrypted" ) )
+ mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted" ) );
+}
+
+void SecurityPage::ComposerCryptoTab::save() {
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ composer.writeEntry( "pgp-auto-sign", mWidget->mAutoSignature->isChecked() );
+
+ composer.writeEntry( "crypto-encrypt-to-self", mWidget->mEncToSelf->isChecked() );
+ composer.writeEntry( "crypto-show-encryption-result", mWidget->mShowEncryptionResult->isChecked() );
+ composer.writeEntry( "crypto-show-keys-for-approval", mWidget->mShowKeyApprovalDlg->isChecked() );
+
+ composer.writeEntry( "pgp-auto-encrypt", mWidget->mAutoEncrypt->isChecked() );
+ composer.writeEntry( "never-encrypt-drafts", mWidget->mNeverEncryptWhenSavingInDrafts->isChecked() );
+
+ composer.writeEntry( "crypto-store-encrypted", mWidget->mStoreEncrypted->isChecked() );
+}
+
+QString SecurityPage::WarningTab::helpAnchor() const {
+ return QString::fromLatin1("configure-security-warnings");
+}
+
+SecurityPageWarningTab::SecurityPageWarningTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // the margins are inside mWidget itself
+ QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 );
+
+ mWidget = new WarningConfiguration( this );
+ vlay->addWidget( mWidget );
+
+ connect( mWidget->warnGroupBox, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ connect( mWidget->mWarnUnsigned, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ connect( mWidget->warnUnencryptedCB, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ connect( mWidget->warnReceiverNotInCertificateCB, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ connect( mWidget->mWarnSignKeyExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+ connect( mWidget->mWarnSignChainCertExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+ connect( mWidget->mWarnSignRootCertExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+
+ connect( mWidget->mWarnEncrKeyExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+ connect( mWidget->mWarnEncrChainCertExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+ connect( mWidget->mWarnEncrRootCertExpiresSB, SIGNAL( valueChanged( int ) ), SLOT( slotEmitChanged() ) );
+
+ connect( mWidget->enableAllWarningsPB, SIGNAL(clicked()),
+ SLOT(slotReenableAllWarningsClicked()) );
+}
+
+void SecurityPage::WarningTab::doLoadOther() {
+ const KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted", false ) );
+ mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned", false ) );
+ mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert", true ) );
+
+ // The "-int" part of the key name is because there used to be a separate boolean
+ // config entry for enabling/disabling. This is done with the single bool value now.
+ mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire", true ) );
+
+ mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int", 14 ) );
+ mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int", 14 ) );
+ mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int", 14 ) );
+
+ mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int", 14 ) );
+ mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int", 14 ) );
+ mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int", 14 ) );
+
+ mWidget->enableAllWarningsPB->setEnabled( true );
+}
+
+void SecurityPage::WarningTab::installProfile( KConfig * profile ) {
+ const KConfigGroup composer( profile, "Composer" );
+
+ if ( composer.hasKey( "crypto-warning-unencrypted" ) )
+ mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted" ) );
+ if ( composer.hasKey( "crypto-warning-unsigned" ) )
+ mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned" ) );
+ if ( composer.hasKey( "crypto-warn-recv-not-in-cert" ) )
+ mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert" ) );
+
+ if ( composer.hasKey( "crypto-warn-when-near-expire" ) )
+ mWidget->warnGroupBox->setChecked( composer.readBoolEntry( "crypto-warn-when-near-expire" ) );
+
+ if ( composer.hasKey( "crypto-warn-sign-key-near-expire-int" ) )
+ mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int" ) );
+ if ( composer.hasKey( "crypto-warn-sign-chaincert-near-expire-int" ) )
+ mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int" ) );
+ if ( composer.hasKey( "crypto-warn-sign-root-near-expire-int" ) )
+ mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int" ) );
+
+ if ( composer.hasKey( "crypto-warn-encr-key-near-expire-int" ) )
+ mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int" ) );
+ if ( composer.hasKey( "crypto-warn-encr-chaincert-near-expire-int" ) )
+ mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int" ) );
+ if ( composer.hasKey( "crypto-warn-encr-root-near-expire-int" ) )
+ mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int" ) );
+}
+
+void SecurityPage::WarningTab::save() {
+ KConfigGroup composer( KMKernel::config(), "Composer" );
+
+ composer.writeEntry( "crypto-warn-recv-not-in-cert", mWidget->warnReceiverNotInCertificateCB->isChecked() );
+ composer.writeEntry( "crypto-warning-unencrypted", mWidget->warnUnencryptedCB->isChecked() );
+ composer.writeEntry( "crypto-warning-unsigned", mWidget->mWarnUnsigned->isChecked() );
+
+ composer.writeEntry( "crypto-warn-when-near-expire", mWidget->warnGroupBox->isChecked() );
+ composer.writeEntry( "crypto-warn-sign-key-near-expire-int",
+ mWidget->mWarnSignKeyExpiresSB->value() );
+ composer.writeEntry( "crypto-warn-sign-chaincert-near-expire-int",
+ mWidget->mWarnSignChainCertExpiresSB->value() );
+ composer.writeEntry( "crypto-warn-sign-root-near-expire-int",
+ mWidget->mWarnSignRootCertExpiresSB->value() );
+
+ composer.writeEntry( "crypto-warn-encr-key-near-expire-int",
+ mWidget->mWarnEncrKeyExpiresSB->value() );
+ composer.writeEntry( "crypto-warn-encr-chaincert-near-expire-int",
+ mWidget->mWarnEncrChainCertExpiresSB->value() );
+ composer.writeEntry( "crypto-warn-encr-root-near-expire-int",
+ mWidget->mWarnEncrRootCertExpiresSB->value() );
+}
+
+void SecurityPage::WarningTab::slotReenableAllWarningsClicked() {
+ KMessageBox::enableAllMessages();
+ mWidget->enableAllWarningsPB->setEnabled( false );
+}
+
+////
+
+QString SecurityPage::SMimeTab::helpAnchor() const {
+ return QString::fromLatin1("configure-security-smime-validation");
+}
+
+SecurityPageSMimeTab::SecurityPageSMimeTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // the margins are inside mWidget itself
+ QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 );
+
+ mWidget = new SMimeConfiguration( this );
+ vlay->addWidget( mWidget );
+
+ // Button-group for exclusive radiobuttons
+ QButtonGroup* bg = new QButtonGroup( mWidget );
+ bg->hide();
+ bg->insert( mWidget->CRLRB );
+ bg->insert( mWidget->OCSPRB );
+
+ // Settings for the keyrequester custom widget
+ mWidget->OCSPResponderSignature->setAllowedKeys(
+ Kleo::KeySelectionDialog::SMIMEKeys
+ | Kleo::KeySelectionDialog::TrustedKeys
+ | Kleo::KeySelectionDialog::ValidKeys
+ | Kleo::KeySelectionDialog::SigningKeys
+ | Kleo::KeySelectionDialog::PublicKeys );
+ mWidget->OCSPResponderSignature->setMultipleKeysEnabled( false );
+
+ mConfig = Kleo::CryptoBackendFactory::instance()->config();
+
+ connect( mWidget->CRLRB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->OCSPRB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->OCSPResponderURL, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->OCSPResponderSignature, SIGNAL( changed() ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->doNotCheckCertPolicyCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->neverConsultCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->fetchMissingCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+
+ connect( mWidget->ignoreServiceURLCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->ignoreHTTPDPCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->disableHTTPCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->honorHTTPProxyRB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->useCustomHTTPProxyRB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->customHTTPProxy, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->ignoreLDAPDPCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->disableLDAPCB, SIGNAL( toggled( bool ) ), this, SLOT( slotEmitChanged() ) );
+ connect( mWidget->customLDAPProxy, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotEmitChanged() ) );
+
+ connect( mWidget->disableHTTPCB, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotUpdateHTTPActions() ) );
+ connect( mWidget->ignoreHTTPDPCB, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotUpdateHTTPActions() ) );
+
+ // Button-group for exclusive radiobuttons
+ QButtonGroup* bgHTTPProxy = new QButtonGroup( mWidget );
+ bgHTTPProxy->hide();
+ bgHTTPProxy->insert( mWidget->honorHTTPProxyRB );
+ bgHTTPProxy->insert( mWidget->useCustomHTTPProxyRB );
+
+ if ( !connectDCOPSignal( 0, "KPIM::CryptoConfig", "changed()",
+ "load()", false ) )
+ kdError(5650) << "SecurityPageSMimeTab: connection to CryptoConfig's changed() failed" << endl;
+
+}
+
+SecurityPageSMimeTab::~SecurityPageSMimeTab()
+{
+}
+
+static void disableDirmngrWidget( QWidget* w ) {
+ w->setEnabled( false );
+ QWhatsThis::remove( w );
+ QWhatsThis::add( w, i18n( "This option requires dirmngr >= 0.9.0" ) );
+}
+
+static void initializeDirmngrCheckbox( QCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
+ if ( entry )
+ cb->setChecked( entry->boolValue() );
+ else
+ disableDirmngrWidget( cb );
+}
+
+struct SMIMECryptoConfigEntries {
+ SMIMECryptoConfigEntries( Kleo::CryptoConfig* config )
+ : mConfig( config ) {
+
+ // Checkboxes
+ mCheckUsingOCSPConfigEntry = configEntry( "gpgsm", "Security", "enable-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mEnableOCSPsendingConfigEntry = configEntry( "dirmngr", "OCSP", "allow-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mDoNotCheckCertPolicyConfigEntry = configEntry( "gpgsm", "Security", "disable-policy-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mNeverConsultConfigEntry = configEntry( "gpgsm", "Security", "disable-crl-checks", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mFetchMissingConfigEntry = configEntry( "gpgsm", "Security", "auto-issuer-key-retrieve", Kleo::CryptoConfigEntry::ArgType_None, false );
+ // dirmngr-0.9.0 options
+ mIgnoreServiceURLEntry = configEntry( "dirmngr", "OCSP", "ignore-ocsp-service-url", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mIgnoreHTTPDPEntry = configEntry( "dirmngr", "HTTP", "ignore-http-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mDisableHTTPEntry = configEntry( "dirmngr", "HTTP", "disable-http", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mHonorHTTPProxy = configEntry( "dirmngr", "HTTP", "honor-http-proxy", Kleo::CryptoConfigEntry::ArgType_None, false );
+
+ mIgnoreLDAPDPEntry = configEntry( "dirmngr", "LDAP", "ignore-ldap-dp", Kleo::CryptoConfigEntry::ArgType_None, false );
+ mDisableLDAPEntry = configEntry( "dirmngr", "LDAP", "disable-ldap", Kleo::CryptoConfigEntry::ArgType_None, false );
+ // Other widgets
+ mOCSPResponderURLConfigEntry = configEntry( "dirmngr", "OCSP", "ocsp-responder", Kleo::CryptoConfigEntry::ArgType_String, false );
+ mOCSPResponderSignature = configEntry( "dirmngr", "OCSP", "ocsp-signer", Kleo::CryptoConfigEntry::ArgType_String, false );
+ mCustomHTTPProxy = configEntry( "dirmngr", "HTTP", "http-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
+ mCustomLDAPProxy = configEntry( "dirmngr", "LDAP", "ldap-proxy", Kleo::CryptoConfigEntry::ArgType_String, false );
+ }
+
+ Kleo::CryptoConfigEntry* configEntry( const char* componentName,
+ const char* groupName,
+ const char* entryName,
+ int argType,
+ bool isList );
+
+ // Checkboxes
+ Kleo::CryptoConfigEntry* mCheckUsingOCSPConfigEntry;
+ Kleo::CryptoConfigEntry* mEnableOCSPsendingConfigEntry;
+ Kleo::CryptoConfigEntry* mDoNotCheckCertPolicyConfigEntry;
+ Kleo::CryptoConfigEntry* mNeverConsultConfigEntry;
+ Kleo::CryptoConfigEntry* mFetchMissingConfigEntry;
+ Kleo::CryptoConfigEntry* mIgnoreServiceURLEntry;
+ Kleo::CryptoConfigEntry* mIgnoreHTTPDPEntry;
+ Kleo::CryptoConfigEntry* mDisableHTTPEntry;
+ Kleo::CryptoConfigEntry* mHonorHTTPProxy;
+ Kleo::CryptoConfigEntry* mIgnoreLDAPDPEntry;
+ Kleo::CryptoConfigEntry* mDisableLDAPEntry;
+ // Other widgets
+ Kleo::CryptoConfigEntry* mOCSPResponderURLConfigEntry;
+ Kleo::CryptoConfigEntry* mOCSPResponderSignature;
+ Kleo::CryptoConfigEntry* mCustomHTTPProxy;
+ Kleo::CryptoConfigEntry* mCustomLDAPProxy;
+
+ Kleo::CryptoConfig* mConfig;
+};
+
+void SecurityPage::SMimeTab::doLoadOther() {
+ if ( !mConfig ) {
+ setEnabled( false );
+ return;
+ }
+
+ // Force re-parsing gpgconf data, in case e.g. kleopatra or "configure backend" was used
+ // (which ends up calling us via dcop)
+ mConfig->clear();
+
+ // Create config entries
+ // Don't keep them around, they'll get deleted by clear(), which could be
+ // done by the "configure backend" button even before we save().
+ SMIMECryptoConfigEntries e( mConfig );
+
+ // Initialize GUI items from the config entries
+
+ if ( e.mCheckUsingOCSPConfigEntry ) {
+ bool b = e.mCheckUsingOCSPConfigEntry->boolValue();
+ mWidget->OCSPRB->setChecked( b );
+ mWidget->CRLRB->setChecked( !b );
+ mWidget->OCSPGroupBox->setEnabled( b );
+ } else {
+ mWidget->OCSPGroupBox->setEnabled( false );
+ }
+ if ( e.mDoNotCheckCertPolicyConfigEntry )
+ mWidget->doNotCheckCertPolicyCB->setChecked( e.mDoNotCheckCertPolicyConfigEntry->boolValue() );
+ if ( e.mNeverConsultConfigEntry )
+ mWidget->neverConsultCB->setChecked( e.mNeverConsultConfigEntry->boolValue() );
+ if ( e.mFetchMissingConfigEntry )
+ mWidget->fetchMissingCB->setChecked( e.mFetchMissingConfigEntry->boolValue() );
+
+ if ( e.mOCSPResponderURLConfigEntry )
+ mWidget->OCSPResponderURL->setText( e.mOCSPResponderURLConfigEntry->stringValue() );
+ if ( e.mOCSPResponderSignature ) {
+ mWidget->OCSPResponderSignature->setFingerprint( e.mOCSPResponderSignature->stringValue() );
+ }
+
+ // dirmngr-0.9.0 options
+ initializeDirmngrCheckbox( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
+ initializeDirmngrCheckbox( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
+ initializeDirmngrCheckbox( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
+ initializeDirmngrCheckbox( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
+ initializeDirmngrCheckbox( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
+ if ( e.mCustomHTTPProxy ) {
+ QString systemProxy = QString::fromLocal8Bit( getenv( "http_proxy" ) );
+ if ( systemProxy.isEmpty() )
+ systemProxy = i18n( "no proxy" );
+ mWidget->systemHTTPProxy->setText( i18n( "(Current system setting: %1)" ).arg( systemProxy ) );
+ bool honor = e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue();
+ mWidget->honorHTTPProxyRB->setChecked( honor );
+ mWidget->useCustomHTTPProxyRB->setChecked( !honor );
+ mWidget->customHTTPProxy->setText( e.mCustomHTTPProxy->stringValue() );
+ } else {
+ disableDirmngrWidget( mWidget->honorHTTPProxyRB );
+ disableDirmngrWidget( mWidget->useCustomHTTPProxyRB );
+ disableDirmngrWidget( mWidget->systemHTTPProxy );
+ disableDirmngrWidget( mWidget->customHTTPProxy );
+ }
+ if ( e.mCustomLDAPProxy )
+ mWidget->customLDAPProxy->setText( e.mCustomLDAPProxy->stringValue() );
+ else {
+ disableDirmngrWidget( mWidget->customLDAPProxy );
+ disableDirmngrWidget( mWidget->customLDAPLabel );
+ }
+ slotUpdateHTTPActions();
+}
+
+void SecurityPage::SMimeTab::slotUpdateHTTPActions() {
+ mWidget->ignoreHTTPDPCB->setEnabled( !mWidget->disableHTTPCB->isChecked() );
+
+ // The proxy settings only make sense when "Ignore HTTP CRL DPs of certificate" is checked.
+ bool enableProxySettings = !mWidget->disableHTTPCB->isChecked()
+ && mWidget->ignoreHTTPDPCB->isChecked();
+ mWidget->systemHTTPProxy->setEnabled( enableProxySettings );
+ mWidget->useCustomHTTPProxyRB->setEnabled( enableProxySettings );
+ mWidget->honorHTTPProxyRB->setEnabled( enableProxySettings );
+ mWidget->customHTTPProxy->setEnabled( enableProxySettings );
+}
+
+void SecurityPage::SMimeTab::installProfile( KConfig * ) {
+}
+
+static void saveCheckBoxToKleoEntry( QCheckBox* cb, Kleo::CryptoConfigEntry* entry ) {
+ const bool b = cb->isChecked();
+ if ( entry && entry->boolValue() != b )
+ entry->setBoolValue( b );
+}
+
+void SecurityPage::SMimeTab::save() {
+ if ( !mConfig ) {
+ return;
+ }
+ // Create config entries
+ // Don't keep them around, they'll get deleted by clear(), which could be done by the
+ // "configure backend" button.
+ SMIMECryptoConfigEntries e( mConfig );
+
+ bool b = mWidget->OCSPRB->isChecked();
+ if ( e.mCheckUsingOCSPConfigEntry && e.mCheckUsingOCSPConfigEntry->boolValue() != b )
+ e.mCheckUsingOCSPConfigEntry->setBoolValue( b );
+ // Set allow-ocsp together with enable-ocsp
+ if ( e.mEnableOCSPsendingConfigEntry && e.mEnableOCSPsendingConfigEntry->boolValue() != b )
+ e.mEnableOCSPsendingConfigEntry->setBoolValue( b );
+
+ saveCheckBoxToKleoEntry( mWidget->doNotCheckCertPolicyCB, e.mDoNotCheckCertPolicyConfigEntry );
+ saveCheckBoxToKleoEntry( mWidget->neverConsultCB, e.mNeverConsultConfigEntry );
+ saveCheckBoxToKleoEntry( mWidget->fetchMissingCB, e.mFetchMissingConfigEntry );
+
+ QString txt = mWidget->OCSPResponderURL->text();
+ if ( e.mOCSPResponderURLConfigEntry && e.mOCSPResponderURLConfigEntry->stringValue() != txt )
+ e.mOCSPResponderURLConfigEntry->setStringValue( txt );
+
+ txt = mWidget->OCSPResponderSignature->fingerprint();
+ if ( e.mOCSPResponderSignature && e.mOCSPResponderSignature->stringValue() != txt ) {
+ e.mOCSPResponderSignature->setStringValue( txt );
+ }
+
+ //dirmngr-0.9.0 options
+ saveCheckBoxToKleoEntry( mWidget->ignoreServiceURLCB, e.mIgnoreServiceURLEntry );
+ saveCheckBoxToKleoEntry( mWidget->ignoreHTTPDPCB, e.mIgnoreHTTPDPEntry );
+ saveCheckBoxToKleoEntry( mWidget->disableHTTPCB, e.mDisableHTTPEntry );
+ saveCheckBoxToKleoEntry( mWidget->ignoreLDAPDPCB, e.mIgnoreLDAPDPEntry );
+ saveCheckBoxToKleoEntry( mWidget->disableLDAPCB, e.mDisableLDAPEntry );
+ if ( e.mCustomHTTPProxy ) {
+ const bool honor = mWidget->honorHTTPProxyRB->isChecked();
+ if ( e.mHonorHTTPProxy && e.mHonorHTTPProxy->boolValue() != honor )
+ e.mHonorHTTPProxy->setBoolValue( honor );
+
+ QString chosenProxy = mWidget->customHTTPProxy->text();
+ if ( chosenProxy != e.mCustomHTTPProxy->stringValue() )
+ e.mCustomHTTPProxy->setStringValue( chosenProxy );
+ }
+ txt = mWidget->customLDAPProxy->text();
+ if ( e.mCustomLDAPProxy && e.mCustomLDAPProxy->stringValue() != txt )
+ e.mCustomLDAPProxy->setStringValue( mWidget->customLDAPProxy->text() );
+
+ mConfig->sync( true );
+}
+
+bool SecurityPageSMimeTab::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
+{
+ if ( fun == "load()" ) {
+ replyType = "void";
+ load();
+ } else {
+ return DCOPObject::process( fun, data, replyType, replyData );
+ }
+ return true;
+}
+
+QCStringList SecurityPageSMimeTab::interfaces()
+{
+ QCStringList ifaces = DCOPObject::interfaces();
+ ifaces += "SecurityPageSMimeTab";
+ return ifaces;
+}
+
+QCStringList SecurityPageSMimeTab::functions()
+{
+ // Hide our slot, just because it's simpler to do so.
+ return DCOPObject::functions();
+}
+
+Kleo::CryptoConfigEntry* SMIMECryptoConfigEntries::configEntry( const char* componentName,
+ const char* groupName,
+ const char* entryName,
+ int /*Kleo::CryptoConfigEntry::ArgType*/ argType,
+ bool isList )
+{
+ Kleo::CryptoConfigEntry* entry = mConfig->entry( componentName, groupName, entryName );
+ if ( !entry ) {
+ kdWarning(5006) << QString( "Backend error: gpgconf doesn't seem to know the entry for %1/%2/%3" ).arg( componentName, groupName, entryName ) << endl;
+ return 0;
+ }
+ if( entry->argType() != argType || entry->isList() != isList ) {
+ kdWarning(5006) << QString( "Backend error: gpgconf has wrong type for %1/%2/%3: %4 %5" ).arg( componentName, groupName, entryName ).arg( entry->argType() ).arg( entry->isList() ) << endl;
+ return 0;
+ }
+ return entry;
+}
+
+////
+
+QString SecurityPage::CryptPlugTab::helpAnchor() const {
+ return QString::fromLatin1("configure-security-crypto-backends");
+}
+
+SecurityPageCryptPlugTab::SecurityPageCryptPlugTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ QVBoxLayout * vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ mBackendConfig = Kleo::CryptoBackendFactory::instance()->configWidget( this, "mBackendConfig" );
+ connect( mBackendConfig, SIGNAL( changed( bool ) ), this, SIGNAL( changed( bool ) ) );
+
+ vlay->addWidget( mBackendConfig );
+}
+
+SecurityPageCryptPlugTab::~SecurityPageCryptPlugTab()
+{
+
+}
+
+void SecurityPage::CryptPlugTab::doLoadOther() {
+ mBackendConfig->load();
+}
+
+void SecurityPage::CryptPlugTab::save() {
+ mBackendConfig->save();
+}
+
+// *************************************************************
+// * *
+// * MiscPage *
+// * *
+// *************************************************************
+QString MiscPage::helpAnchor() const {
+ return QString::fromLatin1("configure-misc");
+}
+
+MiscPage::MiscPage( QWidget * parent, const char * name )
+ : ConfigModuleWithTabs( parent, name )
+{
+ mFolderTab = new FolderTab();
+ addTab( mFolderTab, i18n("&Folders") );
+
+ mGroupwareTab = new GroupwareTab();
+ addTab( mGroupwareTab, i18n("&Groupware") );
+ load();
+}
+
+QString MiscPage::FolderTab::helpAnchor() const {
+ return QString::fromLatin1("configure-misc-folders");
+}
+
+MiscPageFolderTab::MiscPageFolderTab( QWidget * parent, const char * name )
+ : ConfigModuleTab( parent, name )
+{
+ // temp. vars:
+ QVBoxLayout *vlay;
+ QHBoxLayout *hlay;
+ QLabel *label;
+
+ vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ // "confirm before emptying folder" check box: stretch 0
+ mEmptyFolderConfirmCheck =
+ new QCheckBox( i18n("Corresponds to Folder->Move All Messages to Trash",
+ "Ask for co&nfirmation before moving all messages to "
+ "trash"),
+ this );
+ vlay->addWidget( mEmptyFolderConfirmCheck );
+ connect( mEmptyFolderConfirmCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ mExcludeImportantFromExpiry =
+ new QCheckBox( i18n("E&xclude important messages from expiry"), this );
+ vlay->addWidget( mExcludeImportantFromExpiry );
+ connect( mExcludeImportantFromExpiry, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "when trying to find unread messages" combo + label: stretch 0
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mLoopOnGotoUnread = new QComboBox( false, this );
+ label = new QLabel( mLoopOnGotoUnread,
+ i18n("to be continued with \"do not loop\", \"loop in current folder\", "
+ "and \"loop in all folders\".",
+ "When trying to find unread messages:"), this );
+ mLoopOnGotoUnread->insertStringList( QStringList()
+ << i18n("continuation of \"When trying to find unread messages:\"",
+ "Do not Loop")
+ << i18n("continuation of \"When trying to find unread messages:\"",
+ "Loop in Current Folder")
+ << i18n("continuation of \"When trying to find unread messages:\"",
+ "Loop in All Folders"));
+ hlay->addWidget( label );
+ hlay->addWidget( mLoopOnGotoUnread, 1 );
+ connect( mLoopOnGotoUnread, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // when entering a folder
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mActionEnterFolder = new QComboBox( false, this );
+ label = new QLabel( mActionEnterFolder,
+ i18n("to be continued with \"jump to first new message\", "
+ "\"jump to first unread or new message\","
+ "and \"jump to last selected message\".",
+ "When entering a folder:"), this );
+ mActionEnterFolder->insertStringList( QStringList()
+ << i18n("continuation of \"When entering a folder:\"",
+ "Jump to First New Message")
+ << i18n("continuation of \"When entering a folder:\"",
+ "Jump to First Unread or New Message")
+ << i18n("continuation of \"When entering a folder:\"",
+ "Jump to Last Selected Message"));
+ hlay->addWidget( label );
+ hlay->addWidget( mActionEnterFolder, 1 );
+ connect( mActionEnterFolder, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mDelayedMarkAsRead = new QCheckBox( i18n("Mar&k selected message as read after"), this );
+ hlay->addWidget( mDelayedMarkAsRead );
+ mDelayedMarkTime = new KIntSpinBox( 0 /*min*/, 60 /*max*/, 1/*step*/,
+ 0 /*init*/, 10 /*base*/, this);
+ mDelayedMarkTime->setSuffix( i18n(" sec") );
+ mDelayedMarkTime->setEnabled( false ); // since mDelayedMarkAsREad is off
+ hlay->addWidget( mDelayedMarkTime );
+ hlay->addStretch( 1 );
+ connect( mDelayedMarkTime, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ connect( mDelayedMarkAsRead, SIGNAL(toggled(bool)),
+ mDelayedMarkTime, SLOT(setEnabled(bool)));
+ connect( mDelayedMarkAsRead, SIGNAL(toggled(bool)),
+ this , SLOT(slotEmitChanged( void )));
+
+ // "show popup after Drag'n'Drop" checkbox: stretch 0
+ mShowPopupAfterDnD =
+ new QCheckBox( i18n("Ask for action after &dragging messages to another folder"), this );
+ vlay->addWidget( mShowPopupAfterDnD );
+ connect( mShowPopupAfterDnD, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "default mailbox format" combo + label: stretch 0
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mMailboxPrefCombo = new QComboBox( false, this );
+ label = new QLabel( mMailboxPrefCombo,
+ i18n("to be continued with \"flat files\" and "
+ "\"directories\", resp.",
+ "By default, &message folders on disk are:"), this );
+ mMailboxPrefCombo->insertStringList( QStringList()
+ << i18n("continuation of \"By default, &message folders on disk are\"",
+ "Flat Files (\"mbox\" format)")
+ << i18n("continuation of \"By default, &message folders on disk are\"",
+ "Directories (\"maildir\" format)") );
+ // and now: add QWhatsThis:
+ QString msg = i18n( "what's this help",
+ "<qt><p>This selects which mailbox format will be "
+ "the default for local folders:</p>"
+ "<p><b>mbox:</b> KMail's mail "
+ "folders are represented by a single file each. "
+ "Individual messages are separated from each other by a "
+ "line starting with \"From \". This saves space on "
+ "disk, but may be less robust, e.g. when moving messages "
+ "between folders.</p>"
+ "<p><b>maildir:</b> KMail's mail folders are "
+ "represented by real folders on disk. Individual messages "
+ "are separate files. This may waste a bit of space on "
+ "disk, but should be more robust, e.g. when moving "
+ "messages between folders.</p></qt>");
+ QWhatsThis::add( mMailboxPrefCombo, msg );
+ QWhatsThis::add( label, msg );
+ hlay->addWidget( label );
+ hlay->addWidget( mMailboxPrefCombo, 1 );
+ connect( mMailboxPrefCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "On startup..." option:
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mOnStartupOpenFolder = new FolderRequester( this,
+ kmkernel->getKMMainWidget()->folderTree() );
+ label = new QLabel( mOnStartupOpenFolder,
+ i18n("Open this folder on startup:"), this );
+ hlay->addWidget( label );
+ hlay->addWidget( mOnStartupOpenFolder, 1 );
+ connect( mOnStartupOpenFolder, SIGNAL( folderChanged( KMFolder* ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // "Empty &trash on program exit" option:
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mEmptyTrashCheck = new QCheckBox( i18n("Empty local &trash folder on program exit"),
+ this );
+ hlay->addWidget( mEmptyTrashCheck );
+ connect( mEmptyTrashCheck, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+#ifdef HAVE_INDEXLIB
+ // indexing enabled option:
+ mIndexingEnabled = new QCheckBox( i18n("Enable full text &indexing"), this );
+ vlay->addWidget( mIndexingEnabled );
+ connect( mIndexingEnabled, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+#endif
+
+ // "Quota Units"
+ hlay = new QHBoxLayout( vlay ); // inherits spacing
+ mQuotaCmbBox = new QComboBox( false, this );
+ label = new QLabel( mQuotaCmbBox,
+ i18n("Quota units: "), this );
+ mQuotaCmbBox->insertStringList( QStringList()
+ << i18n("KB")
+ << i18n("MB")
+ << i18n("GB") );
+ hlay->addWidget( label );
+ hlay->addWidget( mQuotaCmbBox, 1 );
+ connect( mQuotaCmbBox, SIGNAL( activated( int ) ), this, SLOT( slotEmitChanged( void ) ) );
+
+ vlay->addStretch( 1 );
+
+ // @TODO: Till, move into .kcgc file
+ msg = i18n( "what's this help",
+ "<qt><p>When jumping to the next unread message, it may occur "
+ "that no more unread messages are below the current message.</p>"
+ "<p><b>Do not loop:</b> The search will stop at the last message in "
+ "the current folder.</p>"
+ "<p><b>Loop in current folder:</b> The search will continue at the "
+ "top of the message list, but not go to another folder.</p>"
+ "<p><b>Loop in all folders:</b> The search will continue at the top of "
+ "the message list. If no unread messages are found it will then continue "
+ "to the next folder.</p>"
+ "<p>Similarly, when searching for the previous unread message, "
+ "the search will start from the bottom of the message list and continue to "
+ "the previous folder depending on which option is selected.</p></qt>" );
+ QWhatsThis::add( mLoopOnGotoUnread, msg );
+
+#ifdef HAVE_INDEXLIB
+ // this is probably overly pessimistic
+ msg = i18n( "what's this help",
+ "<qt><p>Full text indexing allows very fast searches on the content "
+ "of your messages. When enabled, the search dialog will work very fast. "
+ "Also, the search tool bar will select messages based on content.</p>"
+ "<p>It takes up a certain amount of disk space "
+ "(about half the disk space for the messages).</p>"
+ "<p>After enabling, the index will need to be built, but you can continue to use KMail "
+ "while this operation is running.</p>"
+ "</qt>"
+ );
+
+ QWhatsThis::add( mIndexingEnabled, msg );
+#endif
+}
+
+void MiscPage::FolderTab::doLoadFromGlobalSettings() {
+ mExcludeImportantFromExpiry->setChecked( GlobalSettings::self()->excludeImportantMailFromExpiry() );
+ // default = "Loop in current folder"
+ mLoopOnGotoUnread->setCurrentItem( GlobalSettings::self()->loopOnGotoUnread() );
+ mActionEnterFolder->setCurrentItem( GlobalSettings::self()->actionEnterFolder() );
+ mDelayedMarkAsRead->setChecked( GlobalSettings::self()->delayedMarkAsRead() );
+ mDelayedMarkTime->setValue( GlobalSettings::self()->delayedMarkTime() );
+ mShowPopupAfterDnD->setChecked( GlobalSettings::self()->showPopupAfterDnD() );
+ mQuotaCmbBox->setCurrentItem( GlobalSettings::self()->quotaUnit() );
+}
+
+void MiscPage::FolderTab::doLoadOther() {
+ KConfigGroup general( KMKernel::config(), "General" );
+
+ mEmptyTrashCheck->setChecked( general.readBoolEntry( "empty-trash-on-exit", true ) );
+ mOnStartupOpenFolder->setFolder( general.readEntry( "startupFolder",
+ kmkernel->inboxFolder()->idString() ) );
+ mEmptyFolderConfirmCheck->setChecked( general.readBoolEntry( "confirm-before-empty", true ) );
+
+ int num = general.readNumEntry("default-mailbox-format", 1 );
+ if ( num < 0 || num > 1 ) num = 1;
+ mMailboxPrefCombo->setCurrentItem( num );
+
+#ifdef HAVE_INDEXLIB
+ mIndexingEnabled->setChecked( kmkernel->msgIndex() && kmkernel->msgIndex()->isEnabled() );
+#endif
+}
+
+void MiscPage::FolderTab::save() {
+ KConfigGroup general( KMKernel::config(), "General" );
+
+ general.writeEntry( "empty-trash-on-exit", mEmptyTrashCheck->isChecked() );
+ general.writeEntry( "confirm-before-empty", mEmptyFolderConfirmCheck->isChecked() );
+ general.writeEntry( "default-mailbox-format", mMailboxPrefCombo->currentItem() );
+ general.writeEntry( "startupFolder", mOnStartupOpenFolder->folder() ?
+ mOnStartupOpenFolder->folder()->idString() : QString::null );
+
+ GlobalSettings::self()->setDelayedMarkAsRead( mDelayedMarkAsRead->isChecked() );
+ GlobalSettings::self()->setDelayedMarkTime( mDelayedMarkTime->value() );
+ GlobalSettings::self()->setActionEnterFolder( mActionEnterFolder->currentItem() );
+ GlobalSettings::self()->setLoopOnGotoUnread( mLoopOnGotoUnread->currentItem() );
+ GlobalSettings::self()->setShowPopupAfterDnD( mShowPopupAfterDnD->isChecked() );
+ GlobalSettings::self()->setExcludeImportantMailFromExpiry(
+ mExcludeImportantFromExpiry->isChecked() );
+ GlobalSettings::self()->setQuotaUnit( mQuotaCmbBox->currentItem() );
+#ifdef HAVE_INDEXLIB
+ if ( kmkernel->msgIndex() ) kmkernel->msgIndex()->setEnabled( mIndexingEnabled->isChecked() );
+#endif
+}
+
+QString MiscPage::GroupwareTab::helpAnchor() const {
+ return QString::fromLatin1("configure-misc-groupware");
+}
+
+MiscPageGroupwareTab::MiscPageGroupwareTab( QWidget* parent, const char* name )
+ : ConfigModuleTab( parent, name )
+{
+ QBoxLayout* vlay = new QVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint() );
+ vlay->setAutoAdd( true );
+
+ // IMAP resource setup
+ QVGroupBox* b1 = new QVGroupBox( i18n("&IMAP Resource Folder Options"),
+ this );
+
+ mEnableImapResCB =
+ new QCheckBox( i18n("&Enable IMAP resource functionality"), b1 );
+ QToolTip::add( mEnableImapResCB, i18n( "This enables the IMAP storage for "
+ "the Kontact applications" ) );
+ QWhatsThis::add( mEnableImapResCB,
+ i18n( GlobalSettings::self()->theIMAPResourceEnabledItem()->whatsThis().utf8() ) );
+ connect( mEnableImapResCB, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mBox = new QWidget( b1 );
+ QGridLayout* grid = new QGridLayout( mBox, 5, 2, 0, KDialog::spacingHint() );
+ grid->setColStretch( 1, 1 );
+ connect( mEnableImapResCB, SIGNAL( toggled(bool) ),
+ mBox, SLOT( setEnabled(bool) ) );
+
+ QLabel* storageFormatLA = new QLabel( i18n("&Format used for the groupware folders:"),
+ mBox );
+ QString toolTip = i18n( "Choose the format to use to store the contents of the groupware folders." );
+ QString whatsThis = i18n( GlobalSettings::self()
+ ->theIMAPResourceStorageFormatItem()->whatsThis().utf8() );
+ grid->addWidget( storageFormatLA, 0, 0 );
+ QToolTip::add( storageFormatLA, toolTip );
+ QWhatsThis::add( storageFormatLA, whatsThis );
+ mStorageFormatCombo = new QComboBox( false, mBox );
+ storageFormatLA->setBuddy( mStorageFormatCombo );
+ QStringList formatLst;
+ formatLst << i18n("Standard (Ical / Vcard)") << i18n("Kolab (XML)");
+ mStorageFormatCombo->insertStringList( formatLst );
+ grid->addWidget( mStorageFormatCombo, 0, 1 );
+ QToolTip::add( mStorageFormatCombo, toolTip );
+ QWhatsThis::add( mStorageFormatCombo, whatsThis );
+ connect( mStorageFormatCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotStorageFormatChanged( int ) ) );
+
+ QLabel* languageLA = new QLabel( i18n("&Language of the groupware folders:"),
+ mBox );
+
+ toolTip = i18n( "Set the language of the folder names" );
+ whatsThis = i18n( GlobalSettings::self()
+ ->theIMAPResourceFolderLanguageItem()->whatsThis().utf8() );
+ grid->addWidget( languageLA, 1, 0 );
+ QToolTip::add( languageLA, toolTip );
+ QWhatsThis::add( languageLA, whatsThis );
+ mLanguageCombo = new QComboBox( false, mBox );
+ languageLA->setBuddy( mLanguageCombo );
+ QStringList lst;
+ lst << i18n("English") << i18n("German") << i18n("French") << i18n("Dutch");
+ mLanguageCombo->insertStringList( lst );
+ grid->addWidget( mLanguageCombo, 1, 1 );
+ QToolTip::add( mLanguageCombo, toolTip );
+ QWhatsThis::add( mLanguageCombo, whatsThis );
+ connect( mLanguageCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mFolderComboLabel = new QLabel( mBox ); // text depends on storage format
+ toolTip = i18n( "Set the parent of the resource folders" );
+ whatsThis = i18n( GlobalSettings::self()->theIMAPResourceFolderParentItem()->whatsThis().utf8() );
+ QToolTip::add( mFolderComboLabel, toolTip );
+ QWhatsThis::add( mFolderComboLabel, whatsThis );
+ grid->addWidget( mFolderComboLabel, 2, 0 );
+
+ mFolderComboStack = new QWidgetStack( mBox );
+ grid->addWidget( mFolderComboStack, 2, 1 );
+
+ // First possibility in the widgetstack: a combo showing the list of all folders
+ // This is used with the ical/vcard storage
+ mFolderCombo = new FolderRequester( mBox,
+ kmkernel->getKMMainWidget()->folderTree() );
+ mFolderComboStack->addWidget( mFolderCombo, 0 );
+ QToolTip::add( mFolderCombo, toolTip );
+ QWhatsThis::add( mFolderCombo, whatsThis );
+ connect( mFolderCombo, SIGNAL( folderChanged( KMFolder* ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ // Second possibility in the widgetstack: a combo showing the list of accounts
+ // This is used with the kolab xml storage since the groupware folders
+ // are always under the inbox.
+ mAccountCombo = new KMail::AccountComboBox( mBox );
+ mFolderComboStack->addWidget( mAccountCombo, 1 );
+ QToolTip::add( mAccountCombo, toolTip );
+ QWhatsThis::add( mAccountCombo, whatsThis );
+ connect( mAccountCombo, SIGNAL( activated( int ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ mHideGroupwareFolders = new QCheckBox( i18n( "&Hide groupware folders" ),
+ mBox, "HideGroupwareFoldersBox" );
+ grid->addMultiCellWidget( mHideGroupwareFolders, 3, 3, 0, 0 );
+ QToolTip::add( mHideGroupwareFolders,
+ i18n( "When this is checked, you will not see the IMAP "
+ "resource folders in the folder tree." ) );
+ QWhatsThis::add( mHideGroupwareFolders, i18n( GlobalSettings::self()
+ ->hideGroupwareFoldersItem()->whatsThis().utf8() ) );
+ connect( mHideGroupwareFolders, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ mOnlyShowGroupwareFolders = new QCheckBox( i18n( "&Only show groupware folders for this account" ),
+ mBox, "OnlyGroupwareFoldersBox" );
+ grid->addMultiCellWidget( mOnlyShowGroupwareFolders, 3, 3, 1, 1 );
+ QToolTip::add( mOnlyShowGroupwareFolders,
+ i18n( "When this is checked, you will not see normal "
+ "mail folders in the folder tree for the account "
+ "configured for groupware." ) );
+ QWhatsThis::add( mOnlyShowGroupwareFolders, i18n( GlobalSettings::self()
+ ->showOnlyGroupwareFoldersForGroupwareAccountItem()->whatsThis().utf8() ) );
+ connect( mOnlyShowGroupwareFolders, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotEmitChanged() ) );
+
+ mSyncImmediately = new QCheckBox( i18n( "Synchronize groupware changes immediately" ), mBox );
+ QToolTip::add( mSyncImmediately,
+ i18n( "Synchronize groupware changes in disconnected IMAP folders immediately when being online." ) );
+ connect( mSyncImmediately, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ grid->addMultiCellWidget( mSyncImmediately, 4, 4, 0, 1 );
+
+ mDeleteInvitations = new QCheckBox(
+ i18n( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReplyItem()->label().utf8() ), mBox );
+ QWhatsThis::add( mDeleteInvitations, i18n( GlobalSettings::self()
+ ->deleteInvitationEmailsAfterSendingReplyItem()->whatsThis().utf8() ) );
+ connect( mDeleteInvitations, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) );
+ grid->addMultiCellWidget( mDeleteInvitations, 5, 5, 0, 1 );
+
+ // Groupware functionality compatibility setup
+ b1 = new QVGroupBox( i18n("Groupware Compatibility && Legacy Options"), this );
+
+ gBox = new QVBox( b1 );
+#if 0
+ // Currently believed to be disused.
+ mEnableGwCB = new QCheckBox( i18n("&Enable groupware functionality"), b1 );
+ gBox->setSpacing( KDialog::spacingHint() );
+ connect( mEnableGwCB, SIGNAL( toggled(bool) ),
+ gBox, SLOT( setEnabled(bool) ) );
+ connect( mEnableGwCB, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+#endif
+ mEnableGwCB = 0;
+ mLegacyMangleFromTo = new QCheckBox( i18n( "Mangle From:/To: headers in replies to invitations" ), gBox );
+ QToolTip::add( mLegacyMangleFromTo, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitation replies" ) );
+ QWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
+ legacyMangleFromToHeadersItem()->whatsThis().utf8() ) );
+ connect( mLegacyMangleFromTo, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+ mLegacyBodyInvites = new QCheckBox( i18n( "Send invitations in the mail body" ), gBox );
+ QToolTip::add( mLegacyBodyInvites, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitations" ) );
+ QWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()->
+ legacyBodyInvitesItem()->whatsThis().utf8() ) );
+ connect( mLegacyBodyInvites, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotLegacyBodyInvitesToggled( bool ) ) );
+ connect( mLegacyBodyInvites, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mExchangeCompatibleInvitations = new QCheckBox( i18n( "Exchange compatible invitation naming" ), gBox );
+ QToolTip::add( mExchangeCompatibleInvitations, i18n( "Microsoft Outlook, when used in combination with a Microsoft Exchange server, has a problem understanding standards-compliant groupware e-mail. Turn this option on to send groupware invitations in a way that Microsoft Exchange understands." ) );
+ QWhatsThis::add( mExchangeCompatibleInvitations, i18n( GlobalSettings::self()->
+ exchangeCompatibleInvitationsItem()->whatsThis().utf8() ) );
+ connect( mExchangeCompatibleInvitations, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ mAutomaticSending = new QCheckBox( i18n( "Automatic invitation sending" ), gBox );
+ QToolTip::add( mAutomaticSending, i18n( "When this is on, the user will not see the mail composer window. Invitation mails are sent automatically" ) );
+ QWhatsThis::add( mAutomaticSending, i18n( GlobalSettings::self()->
+ automaticSendingItem()->whatsThis().utf8() ) );
+ connect( mAutomaticSending, SIGNAL( stateChanged( int ) ),
+ this, SLOT( slotEmitChanged( void ) ) );
+
+ // Open space padding at the end
+ new QLabel( this );
+}
+
+void MiscPageGroupwareTab::slotLegacyBodyInvitesToggled( bool on )
+{
+ if ( on ) {
+ QString txt = i18n( "<qt>Invitations are normally sent as attachments to "
+ "a mail. This switch changes the invitation mails to "
+ "be sent in the text of the mail instead; this is "
+ "necessary to send invitations and replies to "
+ "Microsoft Outlook.<br>But, when you do this, you no "
+ "longer get descriptive text that mail programs "
+ "can read; so, to people who have email programs "
+ "that do not understand the invitations, the "
+ "resulting messages look very odd.<br>People that have email "
+ "programs that do understand invitations will still "
+ "be able to work with this.</qt>" );
+ KMessageBox::information( this, txt, QString::null,
+ "LegacyBodyInvitesWarning" );
+ }
+ // Invitations in the body are autosent in any case (no point in editing raw ICAL)
+ // So the autosend option is only available if invitations are sent as attachment.
+ mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
+}
+
+void MiscPage::GroupwareTab::doLoadFromGlobalSettings() {
+ if ( mEnableGwCB ) {
+ mEnableGwCB->setChecked( GlobalSettings::self()->groupwareEnabled() );
+ gBox->setEnabled( mEnableGwCB->isChecked() );
+ }
+
+ mLegacyMangleFromTo->setChecked( GlobalSettings::self()->legacyMangleFromToHeaders() );
+ mLegacyBodyInvites->blockSignals( true );
+
+ mLegacyBodyInvites->setChecked( GlobalSettings::self()->legacyBodyInvites() );
+ mLegacyBodyInvites->blockSignals( false );
+
+ mExchangeCompatibleInvitations->setChecked( GlobalSettings::self()->exchangeCompatibleInvitations() );
+
+ mAutomaticSending->setChecked( GlobalSettings::self()->automaticSending() );
+ mAutomaticSending->setEnabled( !mLegacyBodyInvites->isChecked() );
+
+ // Read the IMAP resource config
+ mEnableImapResCB->setChecked( GlobalSettings::self()->theIMAPResourceEnabled() );
+ mBox->setEnabled( mEnableImapResCB->isChecked() );
+
+ mHideGroupwareFolders->setChecked( GlobalSettings::self()->hideGroupwareFolders() );
+ int i = GlobalSettings::self()->theIMAPResourceFolderLanguage();
+ mLanguageCombo->setCurrentItem(i);
+ i = GlobalSettings::self()->theIMAPResourceStorageFormat();
+ mStorageFormatCombo->setCurrentItem(i);
+ slotStorageFormatChanged( i );
+ mOnlyShowGroupwareFolders->setChecked( GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount() );
+ mSyncImmediately->setChecked( GlobalSettings::self()->immediatlySyncDIMAPOnGroupwareChanges() );
+ mDeleteInvitations->setChecked( GlobalSettings::self()->deleteInvitationEmailsAfterSendingReply() );
+
+ QString folderId( GlobalSettings::self()->theIMAPResourceFolderParent() );
+ if( !folderId.isNull() && kmkernel->findFolderById( folderId ) ) {
+ mFolderCombo->setFolder( folderId );
+ } else {
+ // Folder was deleted, we have to choose a new one
+ mFolderCombo->setFolder( i18n( "<Choose a Folder>" ) );
+ }
+
+ KMAccount* selectedAccount = 0;
+ int accountId = GlobalSettings::self()->theIMAPResourceAccount();
+ if ( accountId )
+ selectedAccount = kmkernel->acctMgr()->find( accountId );
+ else {
+ // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
+ for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
+ a = kmkernel->acctMgr()->next() ) {
+ if( a->folder() && a->folder()->child() ) {
+ // Look inside that folder for an INBOX
+ KMFolderNode *node;
+ for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next())
+ if (!node->isDir() && node->name() == "INBOX") break;
+
+ if ( node && static_cast<KMFolder*>(node)->idString() == folderId ) {
+ selectedAccount = a;
+ break;
+ }
+ }
+ }
+ }
+ if ( selectedAccount )
+ mAccountCombo->setCurrentAccount( selectedAccount );
+ else if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == 1 )
+ kdDebug(5006) << "Folder " << folderId << " not found as an account's inbox" << endl;
+}
+
+void MiscPage::GroupwareTab::save() {
+ KConfigGroup groupware( KMKernel::config(), "Groupware" );
+
+ // Write the groupware config
+ if ( mEnableGwCB ) {
+ groupware.writeEntry( "GroupwareEnabled", mEnableGwCB->isChecked() );
+ }
+ groupware.writeEntry( "LegacyMangleFromToHeaders", mLegacyMangleFromTo->isChecked() );
+ groupware.writeEntry( "LegacyBodyInvites", mLegacyBodyInvites->isChecked() );
+ groupware.writeEntry( "ExchangeCompatibleInvitations", mExchangeCompatibleInvitations->isChecked() );
+ groupware.writeEntry( "AutomaticSending", mAutomaticSending->isChecked() );
+
+ if ( mEnableGwCB ) {
+ GlobalSettings::self()->setGroupwareEnabled( mEnableGwCB->isChecked() );
+ }
+ GlobalSettings::self()->setLegacyMangleFromToHeaders( mLegacyMangleFromTo->isChecked() );
+ GlobalSettings::self()->setLegacyBodyInvites( mLegacyBodyInvites->isChecked() );
+ GlobalSettings::self()->setExchangeCompatibleInvitations( mExchangeCompatibleInvitations->isChecked() );
+ GlobalSettings::self()->setAutomaticSending( mAutomaticSending->isChecked() );
+
+ int format = mStorageFormatCombo->currentItem();
+ GlobalSettings::self()->setTheIMAPResourceStorageFormat( format );
+
+ // Write the IMAP resource config
+ GlobalSettings::self()->setHideGroupwareFolders( mHideGroupwareFolders->isChecked() );
+ GlobalSettings::self()->setShowOnlyGroupwareFoldersForGroupwareAccount( mOnlyShowGroupwareFolders->isChecked() );
+ GlobalSettings::self()->setImmediatlySyncDIMAPOnGroupwareChanges( mSyncImmediately->isChecked() );
+ GlobalSettings::self()->setDeleteInvitationEmailsAfterSendingReply( mDeleteInvitations->isChecked() );
+
+ // If there is a leftover folder in the foldercombo, getFolder can
+ // return 0. In that case we really don't have it enabled
+ QString folderId;
+ if ( format == 0 ) {
+ KMFolder* folder = mFolderCombo->folder();
+ if ( folder )
+ folderId = folder->idString();
+ KMAccount* account = 0;
+ // Didn't find an easy way to find the account for a given folder...
+ // Fallback: iterate over accounts to select folderId if found (as an inbox folder)
+ for( KMAccount *a = kmkernel->acctMgr()->first();
+ a && !account; // stop when found
+ a = kmkernel->acctMgr()->next() ) {
+ if( a->folder() && a->folder()->child() ) {
+ KMFolderNode *node;
+ for ( node = a->folder()->child()->first(); node; node = a->folder()->child()->next() )
+ {
+ if ( static_cast<KMFolder*>(node) == folder ) {
+ account = a;
+ break;
+ }
+ }
+ }
+ }
+ GlobalSettings::self()->setTheIMAPResourceAccount( account ? account->id() : 0 );
+ } else {
+ // Inbox folder of the selected account
+ KMAccount* acct = mAccountCombo->currentAccount();
+ if ( acct ) {
+ folderId = QString( ".%1.directory/INBOX" ).arg( acct->id() );
+ GlobalSettings::self()->setTheIMAPResourceAccount( acct->id() );
+ }
+ }
+
+ bool enabled = mEnableImapResCB->isChecked() && !folderId.isEmpty();
+ GlobalSettings::self()->setTheIMAPResourceEnabled( enabled );
+ GlobalSettings::self()->setTheIMAPResourceFolderLanguage( mLanguageCombo->currentItem() );
+ GlobalSettings::self()->setTheIMAPResourceFolderParent( folderId );
+}
+
+void MiscPage::GroupwareTab::slotStorageFormatChanged( int format )
+{
+ mLanguageCombo->setEnabled( format == 0 ); // only ical/vcard needs the language hack
+ mFolderComboStack->raiseWidget( format );
+ if ( format == 0 ) {
+ mFolderComboLabel->setText( i18n("&Resource folders are subfolders of:") );
+ mFolderComboLabel->setBuddy( mFolderCombo );
+ } else {
+ mFolderComboLabel->setText( i18n("&Resource folders are in account:") );
+ mFolderComboLabel->setBuddy( mAccountCombo );
+ }
+ slotEmitChanged();
+}
+
+
+// *************************************************************
+// * *
+// * AccountUpdater *
+// * *
+// *************************************************************
+AccountUpdater::AccountUpdater(ImapAccountBase *account)
+ : QObject()
+{
+ mAccount = account;
+}
+
+void AccountUpdater::update()
+{
+ connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
+ this, SLOT( namespacesFetched() ) );
+ mAccount->makeConnection();
+}
+
+void AccountUpdater::namespacesFetched()
+{
+ mAccount->setCheckingMail( true );
+ mAccount->processNewMail( false );
+ deleteLater();
+}
+
+#undef DIM
+
+//----------------------------
+#include "configuredialog.moc"