kmail

identitydialog.cpp

00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002     identitydialog.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2002 Marc Mutz <mutz@kde.org>
00006 
00007     KMail is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMail is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this program with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include "identitydialog.h"
00037 
00038 // other KMail headers:
00039 #include "signatureconfigurator.h"
00040 #include "xfaceconfigurator.h"
00041 #include "folderrequester.h"
00042 using KMail::FolderRequester;
00043 #include "kmfoldermgr.h"
00044 #include "transportmanager.h"
00045 #include "dictionarycombobox.h"
00046 #include "kleo_util.h"
00047 #include "kmmainwidget.h"
00048 #include "kmfolder.h"
00049 #include "templatesconfiguration.h"
00050 #include "templatesconfiguration_kfg.h"
00051 #include "simplestringlisteditor.h"
00052 
00053 // other kdepim headers:
00054 // libkdepim
00055 #include <libkpimidentities/identity.h>
00056 #include <libkdepim/addresseelineedit.h>
00057 // libkleopatra:
00058 #include <ui/keyrequester.h>
00059 #include <kleo/cryptobackendfactory.h>
00060 
00061 #include <libemailfunctions/email.h>
00062 
00063 // other KDE headers:
00064 #include <klocale.h>
00065 #include <kmessagebox.h>
00066 #include <kconfig.h>
00067 #include <kfileitem.h>
00068 #include <kurl.h>
00069 #include <kdebug.h>
00070 #include <kpushbutton.h>
00071 
00072 // Qt headers:
00073 #include <tqtabwidget.h>
00074 #include <tqlabel.h>
00075 #include <tqwhatsthis.h>
00076 #include <tqlayout.h>
00077 #include <tqpushbutton.h>
00078 #include <tqcheckbox.h>
00079 #include <tqcombobox.h>
00080 #include <tqgroupbox.h>
00081 #include <tqtextedit.h>
00082 
00083 // other headers:
00084 #include <gpgmepp/key.h>
00085 #include <iterator>
00086 #include <algorithm>
00087 
00088 using namespace KPIM;
00089 
00090 namespace KMail {
00091 
00092   IdentityDialog::IdentityDialog( TQWidget * parent, const char * name )
00093     : KDialogBase( Plain, i18n("Edit Identity"), Ok|Cancel|Help, Ok,
00094                    parent, name )
00095   {
00096     // tmp. vars:
00097     TQWidget * tab;
00098     TQLabel  * label;
00099     int row;
00100     TQGridLayout * glay;
00101     TQString msg;
00102 
00103     //
00104     // Tab Widget: General
00105     //
00106     row = -1;
00107     TQVBoxLayout * vlay = new TQVBoxLayout( plainPage(), 0, spacingHint() );
00108     TQTabWidget *tabWidget = new TQTabWidget( plainPage(), "config-identity-tab" );
00109     vlay->addWidget( tabWidget );
00110 
00111     tab = new TQWidget( tabWidget );
00112     tabWidget->addTab( tab, i18n("&General") );
00113     glay = new TQGridLayout( tab, 5, 2, marginHint(), spacingHint() );
00114     glay->setRowStretch( 3, 1 );
00115     glay->setColStretch( 1, 1 );
00116 
00117     // "Name" line edit and label:
00118     ++row;
00119     mNameEdit = new KLineEdit( tab );
00120     glay->addWidget( mNameEdit, row, 1 );
00121     label = new TQLabel( mNameEdit, i18n("&Your name:"), tab );
00122     glay->addWidget( label, row, 0 );
00123     msg = i18n("<qt><h3>Your name</h3>"
00124                "<p>This field should contain your name as you would like "
00125                "it to appear in the email header that is sent out;</p>"
00126                "<p>if you leave this blank your real name will not "
00127                "appear, only the email address.</p></qt>");
00128     TQWhatsThis::add( label, msg );
00129     TQWhatsThis::add( mNameEdit, msg );
00130 
00131     // "Organization" line edit and label:
00132     ++row;
00133     mOrganizationEdit = new KLineEdit( tab );
00134     glay->addWidget( mOrganizationEdit, row, 1 );
00135     label =  new TQLabel( mOrganizationEdit, i18n("Organi&zation:"), tab );
00136     glay->addWidget( label, row, 0 );
00137     msg = i18n("<qt><h3>Organization</h3>"
00138                "<p>This field should have the name of your organization "
00139                "if you'd like it to be shown in the email header that "
00140                "is sent out.</p>"
00141                "<p>It is safe (and normal) to leave this blank.</p></qt>");
00142     TQWhatsThis::add( label, msg );
00143     TQWhatsThis::add( mOrganizationEdit, msg );
00144 
00145     // "Email Address" line edit and label:
00146     ++row;
00147     mEmailEdit = new KLineEdit( tab );
00148     glay->addWidget( mEmailEdit, row, 1 );
00149     label = new TQLabel( mEmailEdit, i18n("&Email address:"), tab );
00150     glay->addWidget( label, row, 0 );
00151     msg = i18n("<qt><h3>Email address</h3>"
00152                "<p>This field should have your full email address</p>"
00153                "<p>This address is the primary one, used for all outgoing mail. "
00154                "If you have more than one address, either create a new identity, "
00155                "or add additional alias addresses in the field below.</p>"
00156                "<p>If you leave this blank, or get it wrong, people "
00157                "will have trouble replying to you.</p></qt>");
00158     TQWhatsThis::add( label, msg );
00159     TQWhatsThis::add( mEmailEdit, msg );
00160 
00161     // "Email Aliases" string list edit and label:
00162     ++row;
00163     mAliasEdit = new SimpleStringListEditor( tab );
00164     glay->addMultiCellWidget( mAliasEdit, row, row+1, 1, 1 );
00165     label = new TQLabel( mAliasEdit, i18n("Email a&liases:"), tab );
00166     glay->addWidget( label, row, 0, TQt::AlignTop );
00167     msg = i18n("<qt><h3>Email aliases</h3>"
00168                "<p>This field contains alias addresses that should also "
00169                "be considered as belonging to this identity (as opposed "
00170                "to representing a different identity).</p>"
00171                "<p>Example:</p>"
00172                "<table>"
00173                "<tr><th>Primary address:</th><td>first.last@example.org</td></tr>"
00174                "<tr><th>Aliases:</th><td>first@example.org<br>last@example.org</td></tr>"
00175                "</table>"
00176                "<p>Type one alias address per line.</p></qt>");
00177     TQWhatsThis::add( label, msg );
00178     TQWhatsThis::add( mAliasEdit, msg );
00179 
00180     //
00181     // Tab Widget: Cryptography
00182     //
00183     row = -1;
00184     mCryptographyTab = tab = new TQWidget( tabWidget );
00185     tabWidget->addTab( tab, i18n("Cryptograph&y") );
00186     glay = new TQGridLayout( tab, 6, 2, marginHint(), spacingHint() );
00187     glay->setColStretch( 1, 1 );
00188 
00189     // "OpenPGP Signature Key" requester and label:
00190     ++row;
00191     mPGPSigningKeyRequester = new Kleo::SigningKeyRequester( false, Kleo::SigningKeyRequester::OpenPGP, tab );
00192     mPGPSigningKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
00193     mPGPSigningKeyRequester->setDialogCaption( i18n("Your OpenPGP Signature Key") );
00194     msg = i18n("Select the OpenPGP key which should be used to "
00195            "digitally sign your messages.");
00196     mPGPSigningKeyRequester->setDialogMessage( msg );
00197 
00198     msg = i18n("<qt><p>The OpenPGP key you choose here will be used "
00199                "to digitally sign messages. You can also use GnuPG keys.</p>"
00200                "<p>You can leave this blank, but KMail will not be able "
00201                "to digitally sign emails using OpenPGP; "
00202            "normal mail functions will not be affected.</p>"
00203                "<p>You can find out more about keys at <a>http://www.gnupg.org</a></p></qt>");
00204 
00205     label = new TQLabel( mPGPSigningKeyRequester, i18n("OpenPGP signing key:"), tab );
00206     TQWhatsThis::add( mPGPSigningKeyRequester, msg );
00207     TQWhatsThis::add( label, msg );
00208 
00209     glay->addWidget( label, row, 0 );
00210     glay->addWidget( mPGPSigningKeyRequester, row, 1 );
00211 
00212 
00213     // "OpenPGP Encryption Key" requester and label:
00214     ++row;
00215     mPGPEncryptionKeyRequester = new Kleo::EncryptionKeyRequester( false, Kleo::EncryptionKeyRequester::OpenPGP, tab );
00216     mPGPEncryptionKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
00217     mPGPEncryptionKeyRequester->setDialogCaption( i18n("Your OpenPGP Encryption Key") );
00218     msg = i18n("Select the OpenPGP key which should be used when encrypting "
00219            "to yourself and for the \"Attach My Public Key\" "
00220            "feature in the composer.");
00221     mPGPEncryptionKeyRequester->setDialogMessage( msg );
00222 
00223     msg = i18n("<qt><p>The OpenPGP key you choose here will be used "
00224                "to encrypt messages to yourself and for the \"Attach My Public Key\" "
00225            "feature in the composer. You can also use GnuPG keys.</p>"
00226                "<p>You can leave this blank, but KMail will not be able "
00227                "to encrypt copies of outgoing messages to you using OpenPGP; "
00228            "normal mail functions will not be affected.</p>"
00229                "<p>You can find out more about keys at <a>http://www.gnupg.org</a></qt>");
00230     label = new TQLabel( mPGPEncryptionKeyRequester, i18n("OpenPGP encryption key:"), tab );
00231     TQWhatsThis::add( mPGPEncryptionKeyRequester, msg );
00232     TQWhatsThis::add( label, msg );
00233 
00234     glay->addWidget( label, row, 0 );
00235     glay->addWidget( mPGPEncryptionKeyRequester, row, 1 );
00236 
00237 
00238     // "S/MIME Signature Key" requester and label:
00239     ++row;
00240     mSMIMESigningKeyRequester = new Kleo::SigningKeyRequester( false, Kleo::SigningKeyRequester::SMIME, tab );
00241     mSMIMESigningKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
00242     mSMIMESigningKeyRequester->setDialogCaption( i18n("Your S/MIME Signature Certificate") );
00243     msg = i18n("Select the S/MIME certificate which should be used to "
00244            "digitally sign your messages.");
00245     mSMIMESigningKeyRequester->setDialogMessage( msg );
00246 
00247     msg = i18n("<qt><p>The S/MIME (X.509) certificate you choose here will be used "
00248                "to digitally sign messages.</p>"
00249                "<p>You can leave this blank, but KMail will not be able "
00250                "to digitally sign emails using S/MIME; "
00251            "normal mail functions will not be affected.</p></qt>");
00252     label = new TQLabel( mSMIMESigningKeyRequester, i18n("S/MIME signing certificate:"), tab );
00253     TQWhatsThis::add( mSMIMESigningKeyRequester, msg );
00254     TQWhatsThis::add( label, msg );
00255     glay->addWidget( label, row, 0 );
00256     glay->addWidget( mSMIMESigningKeyRequester, row, 1 );
00257 
00258     const Kleo::CryptoBackend::Protocol * smimeProtocol
00259       = Kleo::CryptoBackendFactory::instance()->smime();
00260 
00261     label->setEnabled( smimeProtocol );
00262     mSMIMESigningKeyRequester->setEnabled( smimeProtocol );
00263 
00264     // "S/MIME Encryption Key" requester and label:
00265     ++row;
00266     mSMIMEEncryptionKeyRequester = new Kleo::EncryptionKeyRequester( false, Kleo::EncryptionKeyRequester::SMIME, tab );
00267     mSMIMEEncryptionKeyRequester->dialogButton()->setText( i18n("Chang&e...") );
00268     mSMIMEEncryptionKeyRequester->setDialogCaption( i18n("Your S/MIME Encryption Certificate") );
00269     msg = i18n("Select the S/MIME certificate which should be used when encrypting "
00270            "to yourself and for the \"Attach My Certificate\" "
00271            "feature in the composer.");
00272     mSMIMEEncryptionKeyRequester->setDialogMessage( msg );
00273 
00274     msg = i18n("<qt><p>The S/MIME certificate you choose here will be used "
00275                "to encrypt messages to yourself and for the \"Attach My Certificate\" "
00276            "feature in the composer.</p>"
00277                "<p>You can leave this blank, but KMail will not be able "
00278                "to encrypt copies of outgoing messages to you using S/MIME; "
00279            "normal mail functions will not be affected.</p></qt>");
00280     label = new TQLabel( mSMIMEEncryptionKeyRequester, i18n("S/MIME encryption certificate:"), tab );
00281     TQWhatsThis::add( mSMIMEEncryptionKeyRequester, msg );
00282     TQWhatsThis::add( label, msg );
00283 
00284     glay->addWidget( label, row, 0 );
00285     glay->addWidget( mSMIMEEncryptionKeyRequester, row, 1 );
00286 
00287     label->setEnabled( smimeProtocol );
00288     mSMIMEEncryptionKeyRequester->setEnabled( smimeProtocol );
00289 
00290     // "Preferred Crypto Message Format" combobox and label:
00291     ++row;
00292     mPreferredCryptoMessageFormat = new TQComboBox( false, tab );
00293     TQStringList l;
00294     l << Kleo::cryptoMessageFormatToLabel( Kleo::AutoFormat )
00295       << Kleo::cryptoMessageFormatToLabel( Kleo::InlineOpenPGPFormat )
00296       << Kleo::cryptoMessageFormatToLabel( Kleo::OpenPGPMIMEFormat )
00297       << Kleo::cryptoMessageFormatToLabel( Kleo::SMIMEFormat )
00298       << Kleo::cryptoMessageFormatToLabel( Kleo::SMIMEOpaqueFormat );
00299     mPreferredCryptoMessageFormat->insertStringList( l );
00300     label = new TQLabel( mPreferredCryptoMessageFormat,
00301             i18n("Preferred crypto message format:"), tab );
00302 
00303     glay->addWidget( label, row, 0 );
00304     glay->addWidget( mPreferredCryptoMessageFormat, row, 1 );
00305 
00306     ++row;
00307     glay->setRowStretch( row, 1 );
00308 
00309     //
00310     // Tab Widget: Advanced
00311     //
00312     row = -1;
00313     tab = new TQWidget( tabWidget );
00314     tabWidget->addTab( tab, i18n("&Advanced") );
00315     glay = new TQGridLayout( tab, 8, 2, marginHint(), spacingHint() );
00316     // the last (empty) row takes all the remaining space
00317     glay->setRowStretch( 8-1, 1 );
00318     glay->setColStretch( 1, 1 );
00319 
00320     // "Reply-To Address" line edit and label:
00321     ++row;
00322     mReplyToEdit = new KPIM::AddresseeLineEdit( tab, true, "mReplyToEdit" );
00323     glay->addWidget( mReplyToEdit, row, 1 );
00324     label = new TQLabel ( mReplyToEdit, i18n("&Reply-To address:"), tab);
00325     glay->addWidget( label , row, 0 );
00326     msg = i18n("<qt><h3>Reply-To addresses</h3>"
00327                "<p>This sets the <tt>Reply-to:</tt> header to contain a "
00328                "different email address to the normal <tt>From:</tt> "
00329                "address.</p>"
00330                "<p>This can be useful when you have a group of people "
00331                "working together in similar roles. For example, you "
00332                "might want any emails sent to have your email in the "
00333                "<tt>From:</tt> field, but any responses to go to "
00334                "a group address.</p>"
00335                "<p>If in doubt, leave this field blank.</p></qt>");
00336     TQWhatsThis::add( label, msg );
00337     TQWhatsThis::add( mReplyToEdit, msg );
00338 
00339     // "BCC addresses" line edit and label:
00340     ++row;
00341     mBccEdit = new KPIM::AddresseeLineEdit( tab, true, "mBccEdit" );
00342     glay->addWidget( mBccEdit, row, 1 );
00343     label = new TQLabel( mBccEdit, i18n("&BCC addresses:"), tab );
00344     glay->addWidget( label, row, 0 );
00345     msg = i18n("<qt><h3>BCC (Blind Carbon Copy) addresses</h3>"
00346                "<p>The addresses that you enter here will be added to each "
00347                "outgoing mail that is sent with this identity. They will not "
00348                "be visible to other recipients.</p>"
00349                "<p>This is commonly used to send a copy of each sent message to "
00350                "another account of yours.</p>"
00351                "<p>To specify more than one address, use commas to separate "
00352                "the list of BCC recipients.</p>"
00353                "<p>If in doubt, leave this field blank.</p></qt>");
00354     TQWhatsThis::add( label, msg );
00355     TQWhatsThis::add( mBccEdit, msg );
00356 
00357     // "Dictionary" combo box and label:
00358     ++row;
00359     mDictionaryCombo = new DictionaryComboBox( tab );
00360     glay->addWidget( mDictionaryCombo, row, 1 );
00361     glay->addWidget( new TQLabel( mDictionaryCombo, i18n("D&ictionary:"), tab ),
00362                      row, 0 );
00363 
00364     // "Sent-mail Folder" combo box and label:
00365     ++row;
00366     mFccCombo = new FolderRequester( tab, 
00367         kmkernel->getKMMainWidget()->folderTree() );
00368     mFccCombo->setShowOutbox( false );
00369     glay->addWidget( mFccCombo, row, 1 );
00370     glay->addWidget( new TQLabel( mFccCombo, i18n("Sent-mail &folder:"), tab ),
00371                      row, 0 );
00372 
00373     // "Drafts Folder" combo box and label:
00374     ++row;
00375     mDraftsCombo = new FolderRequester( tab,
00376         kmkernel->getKMMainWidget()->folderTree() );
00377     mDraftsCombo->setShowOutbox( false );
00378     glay->addWidget( mDraftsCombo, row, 1 );
00379     glay->addWidget( new TQLabel( mDraftsCombo, i18n("&Drafts folder:"), tab ),
00380                      row, 0 );
00381 
00382     // "Templates Folder" combo box and label:
00383     ++row;
00384     mTemplatesCombo = new FolderRequester( tab,
00385         kmkernel->getKMMainWidget()->folderTree() );
00386     mTemplatesCombo->setShowOutbox( false );
00387     glay->addWidget( mTemplatesCombo, row, 1 );
00388     glay->addWidget( new TQLabel( mTemplatesCombo, i18n("&Templates folder:"), tab ),
00389                      row, 0 );
00390 
00391     // "Special transport" combobox and label:
00392     ++row;
00393     mTransportCheck = new TQCheckBox( i18n("Special &transport:"), tab );
00394     glay->addWidget( mTransportCheck, row, 0 );
00395     mTransportCombo = new TQComboBox( true, tab );
00396     mTransportCombo->setEnabled( false ); // since !mTransportCheck->isChecked()
00397     mTransportCombo->insertStringList( KMail::TransportManager::transportNames() );
00398     glay->addWidget( mTransportCombo, row, 1 );
00399     connect( mTransportCheck, TQT_SIGNAL(toggled(bool)),
00400              mTransportCombo, TQT_SLOT(setEnabled(bool)) );
00401 
00402     // the last row is a spacer
00403     
00404     // 
00405     // Tab Widget: Templates
00406     // 
00407         tab = new TQWidget( tabWidget );
00408     tabWidget->addTab( tab, i18n("&Templates") );
00409     vlay = new TQVBoxLayout( tab, marginHint(), spacingHint() );
00410         mCustom = new TQCheckBox( i18n("&Use custom message templates"), tab );
00411         vlay->addWidget( mCustom );
00412         mWidget = new TemplatesConfiguration( tab , "identity-templates" );
00413         mWidget->setEnabled( false );
00414         vlay->addWidget( mWidget );
00415         TQHBoxLayout *btns = new TQHBoxLayout( vlay, spacingHint() );
00416         mCopyGlobal = new KPushButton( i18n("&Copy global templates"), tab );
00417         mCopyGlobal->setEnabled( false );
00418         btns->addWidget( mCopyGlobal );
00419         connect( mCustom, TQT_SIGNAL( toggled( bool ) ),
00420                     mWidget, TQT_SLOT( setEnabled( bool ) ) );
00421         connect( mCustom, TQT_SIGNAL( toggled( bool ) ),
00422                     mCopyGlobal, TQT_SLOT( setEnabled( bool ) ) );
00423         connect( mCopyGlobal, TQT_SIGNAL(clicked()),
00424                     this, TQT_SLOT(slotCopyGlobal()) );
00425         
00426     //
00427     // Tab Widget: Signature
00428     //
00429     mSignatureConfigurator = new SignatureConfigurator( tabWidget );
00430     mSignatureConfigurator->layout()->setMargin( KDialog::marginHint() );
00431     tabWidget->addTab( mSignatureConfigurator, i18n("&Signature") );
00432 
00433     mXFaceConfigurator = new XFaceConfigurator( tabWidget );
00434     mXFaceConfigurator->layout()->setMargin( KDialog::marginHint() );
00435     tabWidget->addTab( mXFaceConfigurator, i18n("&Picture") );
00436 
00437     KConfigGroup geometry( KMKernel::config(), "Geometry" );
00438     if ( geometry.hasKey( "Identity Dialog size" ) )
00439       resize( geometry.readSizeEntry( "Identity Dialog size" ) );
00440     mNameEdit->setFocus();
00441 
00442     connect( tabWidget, TQT_SIGNAL(currentChanged(TQWidget*)),
00443          TQT_SLOT(slotAboutToShow(TQWidget*)) );
00444   }
00445 
00446   IdentityDialog::~IdentityDialog() {
00447     KConfigGroup geometry( KMKernel::config(), "Geometry" );
00448     geometry.writeEntry( "Identity Dialog size", size() );
00449   }
00450 
00451   void IdentityDialog::slotAboutToShow( TQWidget * w ) {
00452     if ( w == mCryptographyTab ) {
00453       // set the configured email address as inital query of the key
00454       // requesters:
00455       const TQString email = mEmailEdit->text().stripWhiteSpace();
00456       mPGPEncryptionKeyRequester->setInitialQuery( email );
00457       mPGPSigningKeyRequester->setInitialQuery( email );
00458       mSMIMEEncryptionKeyRequester->setInitialQuery( email );
00459       mSMIMESigningKeyRequester->setInitialQuery( email );
00460     }
00461   }
00462   
00463   void IdentityDialog::slotCopyGlobal() {
00464     mWidget->loadFromGlobal();
00465   }
00466 
00467   namespace {
00468     struct DoesntMatchEMailAddress {
00469       explicit DoesntMatchEMailAddress( const TQString & s )
00470     : email( s.stripWhiteSpace().lower() ) {}
00471       bool operator()( const GpgME::Key & key ) const;
00472     private:
00473       bool checkForEmail( const char * email ) const;
00474       static TQString extractEmail( const char * email );
00475       const TQString email;
00476     };
00477 
00478     bool DoesntMatchEMailAddress::operator()( const GpgME::Key & key ) const {
00479       const std::vector<GpgME::UserID> uids = key.userIDs();
00480       for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it )
00481     if ( checkForEmail( it->email() ? it->email() : it->id() ) )
00482       return false;
00483       return true; // note the negation!
00484     }
00485 
00486     bool DoesntMatchEMailAddress::checkForEmail( const char * e ) const {
00487       const TQString em = extractEmail( e );
00488       return !em.isEmpty() && email == em;
00489     }
00490 
00491     TQString DoesntMatchEMailAddress::extractEmail( const char * e ) {
00492       if ( !e || !*e )
00493     return TQString::null;
00494       const TQString em = TQString::fromUtf8( e );
00495       if ( e[0] == '<' )
00496     return em.mid( 1, em.length() - 2 );
00497       else
00498     return em;
00499     }
00500   }
00501 
00502 bool IdentityDialog::validateAddresses( const TQString & addresses )
00503 {
00504   TQString brokenAddress;
00505   KPIM::EmailParseResult errorCode = KMMessage::isValidEmailAddressList( KMMessage::expandAliases( addresses ), brokenAddress );
00506   if ( !( errorCode == KPIM::AddressOk || errorCode == KPIM::AddressEmpty ) ) {
00507     TQString errorMsg( "<qt><p><b>" + brokenAddress +
00508                       "</b></p><p>" + KPIM::emailParseResultToString( errorCode ) +
00509                       "</p></qt>" );
00510     KMessageBox::sorry( this, errorMsg, i18n("Invalid Email Address") );
00511     return false;
00512   } 
00513   return true;
00514 }
00515 
00516 void IdentityDialog::slotOk() {
00517     const TQString email = mEmailEdit->text().stripWhiteSpace();
00518  
00519     // Validate email addresses
00520     if ( !isValidSimpleEmailAddress( email )) {
00521       TQString errorMsg( simpleEmailAddressErrorMsg());
00522       KMessageBox::sorry( this, errorMsg, i18n("Invalid Email Address") );
00523       return;
00524     }
00525 
00526     const TQStringList aliases = mAliasEdit->stringList();
00527     for ( TQStringList::const_iterator it = aliases.begin(), end = aliases.end() ; it != end ; ++it ) {
00528       if ( !isValidSimpleEmailAddress( *it ) ) {
00529         TQString errorMsg( simpleEmailAddressErrorMsg());
00530         KMessageBox::sorry( this, errorMsg, i18n("Invalid Email Alias \"%1\"").arg( *it ) );
00531         return;
00532       }
00533     }
00534 
00535     if ( !validateAddresses( mReplyToEdit->text().stripWhiteSpace() ) ) {
00536       return;
00537     }
00538  
00539     if ( !validateAddresses( mBccEdit->text().stripWhiteSpace() ) ) {
00540       return;
00541     }
00542 
00543     const std::vector<GpgME::Key> & pgpSigningKeys = mPGPSigningKeyRequester->keys();
00544     const std::vector<GpgME::Key> & pgpEncryptionKeys = mPGPEncryptionKeyRequester->keys();
00545     const std::vector<GpgME::Key> & smimeSigningKeys = mSMIMESigningKeyRequester->keys();
00546     const std::vector<GpgME::Key> & smimeEncryptionKeys = mSMIMEEncryptionKeyRequester->keys();
00547     TQString msg;
00548     bool err = false;
00549     if ( std::find_if( pgpSigningKeys.begin(), pgpSigningKeys.end(),
00550                DoesntMatchEMailAddress( email ) ) != pgpSigningKeys.end() ) {
00551       msg = i18n("One of the configured OpenPGP signing keys does not contain "
00552          "any user ID with the configured email address for this "
00553          "identity (%1).\n"
00554          "This might result in warning messages on the receiving side "
00555          "when trying to verify signatures made with this configuration.");
00556       err = true;
00557     }
00558     else if ( std::find_if( pgpEncryptionKeys.begin(), pgpEncryptionKeys.end(),
00559                 DoesntMatchEMailAddress( email ) ) != pgpEncryptionKeys.end() ) {
00560       msg = i18n("One of the configured OpenPGP encryption keys does not contain "
00561          "any user ID with the configured email address for this "
00562          "identity (%1).");
00563       err = true;
00564     }
00565     else if ( std::find_if( smimeSigningKeys.begin(), smimeSigningKeys.end(),
00566                 DoesntMatchEMailAddress( email ) ) != smimeSigningKeys.end() ) {
00567       msg = i18n("One of the configured S/MIME signing certificates does not contain "
00568          "the configured email address for this "
00569          "identity (%1).\n"
00570          "This might result in warning messages on the receiving side "
00571          "when trying to verify signatures made with this configuration.");
00572       err = true;
00573     }
00574     else if ( std::find_if( smimeEncryptionKeys.begin(), smimeEncryptionKeys.end(),
00575                 DoesntMatchEMailAddress( email ) ) != smimeEncryptionKeys.end() ) {
00576       msg = i18n("One of the configured S/MIME encryption certificates does not contain "
00577          "the configured email address for this "
00578          "identity (%1).");
00579       err = true;
00580     }
00581 
00582     if ( err )
00583       if ( KMessageBox::warningContinueCancel( this, msg.arg( email ),
00584                                           i18n("Email Address Not Found in Key/Certificates"),
00585                                           KStdGuiItem::cont(), "warn_email_not_in_certificate" )
00586      != KMessageBox::Continue)
00587         return;
00588 
00589 
00590     if ( mSignatureConfigurator->isSignatureEnabled() &&
00591          mSignatureConfigurator->signatureType()==Signature::FromFile ) {
00592       KURL url( mSignatureConfigurator->fileURL() );
00593       KFileItem signatureFile( KFileItem::Unknown, KFileItem::Unknown, url );
00594       if ( !signatureFile.isFile() || !signatureFile.isReadable() || !signatureFile.isLocalFile() ) {
00595         KMessageBox::error( this, i18n( "The signature file is not valid" ) );
00596         return;
00597       }
00598     }
00599 
00600     return KDialogBase::slotOk();
00601   }
00602 
00603   bool IdentityDialog::checkFolderExists( const TQString & folderID,
00604                                           const TQString & msg ) {
00605     KMFolder * folder = kmkernel->findFolderById( folderID );
00606     if ( !folder ) {
00607       KMessageBox::sorry( this, msg );
00608       return false;
00609     }
00610     return true;
00611   }
00612 
00613   void IdentityDialog::setIdentity( KPIM::Identity & ident ) {
00614 
00615     setCaption( i18n("Edit Identity \"%1\"").arg( ident.identityName() ) );
00616 
00617     // "General" tab:
00618     mNameEdit->setText( ident.fullName() );
00619     mOrganizationEdit->setText( ident.organization() );
00620     mEmailEdit->setText( ident.primaryEmailAddress() );
00621     mAliasEdit->setStringList( ident.emailAliases() );
00622 
00623     // "Cryptography" tab:
00624     mPGPSigningKeyRequester->setFingerprint( ident.pgpSigningKey() );
00625     mPGPEncryptionKeyRequester->setFingerprint( ident.pgpEncryptionKey() );
00626     mSMIMESigningKeyRequester->setFingerprint( ident.smimeSigningKey() );
00627     mSMIMEEncryptionKeyRequester->setFingerprint( ident.smimeEncryptionKey() );
00628     mPreferredCryptoMessageFormat->setCurrentItem( format2cb( ident.preferredCryptoMessageFormat() ) );
00629 
00630     // "Advanced" tab:
00631     mReplyToEdit->setText( ident.replyToAddr() );
00632     mBccEdit->setText( ident.bcc() );
00633     mTransportCheck->setChecked( !ident.transport().isEmpty() );
00634     mTransportCombo->setEditText( ident.transport() );
00635     mTransportCombo->setEnabled( !ident.transport().isEmpty() );
00636     mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
00637 
00638     if ( ident.fcc().isEmpty() ||
00639          !checkFolderExists( ident.fcc(),
00640                              i18n("The custom sent-mail folder for identity "
00641                                   "\"%1\" does not exist (anymore); "
00642                                   "therefore, the default sent-mail folder "
00643                                   "will be used.")
00644                              .arg( ident.identityName() ) ) )
00645       mFccCombo->setFolder( kmkernel->sentFolder() );
00646     else
00647       mFccCombo->setFolder( ident.fcc() );
00648 
00649     if ( ident.drafts().isEmpty() ||
00650          !checkFolderExists( ident.drafts(),
00651                              i18n("The custom drafts folder for identity "
00652                                   "\"%1\" does not exist (anymore); "
00653                                   "therefore, the default drafts folder "
00654                                   "will be used.")
00655                              .arg( ident.identityName() ) ) )
00656       mDraftsCombo->setFolder( kmkernel->draftsFolder() );
00657     else
00658       mDraftsCombo->setFolder( ident.drafts() );
00659     
00660     if ( ident.templates().isEmpty() ||
00661          !checkFolderExists( ident.templates(),
00662                              i18n("The custom templates folder for identity "
00663                                   "\"%1\" does not exist (anymore); "
00664                                   "therefore, the default templates folder "
00665                                   "will be used.")
00666                              .arg( ident.identityName() ) ) )
00667       mTemplatesCombo->setFolder( kmkernel->templatesFolder() );
00668     else
00669       mTemplatesCombo->setFolder( ident.templates() );
00670     
00671     // "Templates" tab:
00672     uint identity = ident.uoid();
00673         TQString iid = TQString("IDENTITY_%1").arg( identity );
00674         Templates t( iid );
00675         mCustom->setChecked(t.useCustomTemplates());
00676         mWidget->loadFromIdentity( identity );
00677     
00678     // "Signature" tab:
00679     mSignatureConfigurator->setSignature( ident.signature() );
00680     mXFaceConfigurator->setXFace( ident.xface() );
00681     mXFaceConfigurator->setXFaceEnabled( ident.isXFaceEnabled() );
00682   }
00683 
00684   void IdentityDialog::updateIdentity( KPIM::Identity & ident ) {
00685     // "General" tab:
00686     ident.setFullName( mNameEdit->text() );
00687     ident.setOrganization( mOrganizationEdit->text() );
00688     TQString email = mEmailEdit->text();
00689     ident.setPrimaryEmailAddress( email );
00690     const TQStringList aliases = mAliasEdit->stringList();
00691     ident.setEmailAliases( aliases );
00692     // "Cryptography" tab:
00693     ident.setPGPSigningKey( mPGPSigningKeyRequester->fingerprint().latin1() );
00694     ident.setPGPEncryptionKey( mPGPEncryptionKeyRequester->fingerprint().latin1() );
00695     ident.setSMIMESigningKey( mSMIMESigningKeyRequester->fingerprint().latin1() );
00696     ident.setSMIMEEncryptionKey( mSMIMEEncryptionKeyRequester->fingerprint().latin1() );
00697     ident.setPreferredCryptoMessageFormat( cb2format( mPreferredCryptoMessageFormat->currentItem() ) );
00698     // "Advanced" tab:
00699     ident.setReplyToAddr( mReplyToEdit->text() );
00700     ident.setBcc( mBccEdit->text() );
00701     ident.setTransport( ( mTransportCheck->isChecked() ) ?
00702                         mTransportCombo->currentText() : TQString::null );
00703     ident.setDictionary( mDictionaryCombo->currentDictionary() );
00704     ident.setFcc( mFccCombo->folder() ?
00705                   mFccCombo->folder()->idString() : TQString::null );
00706     ident.setDrafts( mDraftsCombo->folder() ?
00707                      mDraftsCombo->folder()->idString() : TQString::null );
00708     ident.setTemplates( mTemplatesCombo->folder() ?
00709                      mTemplatesCombo->folder()->idString() : TQString::null );
00710     // "Templates" tab:
00711     uint identity = ident.uoid();
00712     TQString iid = TQString("IDENTITY_%1").arg( identity );
00713     Templates t( iid );
00714         kdDebug() << "use custom templates for identity " << identity << ": " << mCustom->isChecked() << endl;
00715         t.setUseCustomTemplates(mCustom->isChecked());
00716         t.writeConfig();
00717         mWidget->saveToIdentity( identity );
00718     // "Signature" tab:
00719     ident.setSignature( mSignatureConfigurator->signature() );
00720     ident.setXFace( mXFaceConfigurator->xface() );
00721     ident.setXFaceEnabled( mXFaceConfigurator->isXFaceEnabled() );
00722   }
00723 
00724   void IdentityDialog::slotUpdateTransportCombo( const TQStringList & sl ) {
00725     // save old setting:
00726     TQString content = mTransportCombo->currentText();
00727     // update combo box:
00728     mTransportCombo->clear();
00729     mTransportCombo->insertStringList( sl );
00730     // restore saved setting:
00731     mTransportCombo->setEditText( content );
00732   }
00733 
00734 }
00735 
00736 #include "identitydialog.moc"