00001
00002
00003
00004
00005
00006
00007
#define DEFAULT_EDITOR_STR "kate %f"
00008
00009
#undef GrayScale
00010
#undef Color
00011
#include <config.h>
00012
00013
#include "kmcomposewin.h"
00014
00015
#include "kmmainwin.h"
00016
#include "kmreaderwin.h"
00017
#include "kmreadermainwin.h"
00018
#include "kmsender.h"
00019
#include "kmmsgpartdlg.h"
00020
#include <kpgpblock.h>
00021
#include <kaddrbook.h>
00022
#include "kmaddrbook.h"
00023
#include "kmmsgdict.h"
00024
#include "kmfolderimap.h"
00025
#include "kmfoldermgr.h"
00026
#include "kmfoldercombobox.h"
00027
#include "kmtransport.h"
00028
#include "kmcommands.h"
00029
#include "kcursorsaver.h"
00030
#include "kmkernel.h"
00031
#include "partNode.h"
00032
#include "attachmentlistview.h"
00033
using KMail::AttachmentListView;
00034
#include "dictionarycombobox.h"
00035
using KMail::DictionaryComboBox;
00036
#include "addressesdialog.h"
00037
using KPIM::AddressesDialog;
00038
#include <maillistdrag.h>
00039
using KPIM::MailListDrag;
00040
#include "recentaddresses.h"
00041
using KRecentAddress::RecentAddresses;
00042
#include "attachmentcollector.h"
00043
#include "objecttreeparser.h"
00044
00045
#include <libkpimidentities/identitymanager.h>
00046
#include <libkpimidentities/identitycombo.h>
00047
#include <libkpimidentities/identity.h>
00048
#include <libkdepim/kfileio.h>
00049
#include <libkdepim/email.h>
00050
#include <kleo/cryptobackendfactory.h>
00051
#include <kleo/exportjob.h>
00052
#include <ui/progressdialog.h>
00053
#include <ui/keyselectiondialog.h>
00054
00055
#include <gpgmepp/context.h>
00056
#include <gpgmepp/key.h>
00057
00058
#include "klistboxdialog.h"
00059
00060
#include "messagecomposer.h"
00061
00062
#include <kcharsets.h>
00063
#include <kcompletionbox.h>
00064
#include <kcursor.h>
00065
#include <kcombobox.h>
00066
#include <kstdaccel.h>
00067
#include <kpopupmenu.h>
00068
#include <kedittoolbar.h>
00069
#include <kkeydialog.h>
00070
#include <kdebug.h>
00071
#include <kfiledialog.h>
00072
#include <kwin.h>
00073
#include <kinputdialog.h>
00074
#include <kmessagebox.h>
00075
#include <kurldrag.h>
00076
#include <kio/scheduler.h>
00077
#include <ktempfile.h>
00078
#include <klocale.h>
00079
#include <kapplication.h>
00080
#include <kstatusbar.h>
00081
#include <kaction.h>
00082
#include <kdirwatch.h>
00083
#include <kstdguiitem.h>
00084
#include <kiconloader.h>
00085
#include <kpushbutton.h>
00086
00087
00088
#include <kspell.h>
00089
#include <kspelldlg.h>
00090
#include <spellingfilter.h>
00091
#include <ksyntaxhighlighter.h>
00092
#include <kcolordialog.h>
00093
00094
#include <qtabdialog.h>
00095
#include <qregexp.h>
00096
#include <qbuffer.h>
00097
#include <qtooltip.h>
00098
#include <qtextcodec.h>
00099
#include <qheader.h>
00100
#include <qwhatsthis.h>
00101
#include <qfontdatabase.h>
00102
00103
#include <mimelib/mimepp.h>
00104
00105
#include <algorithm>
00106
00107
#include <sys/stat.h>
00108
#include <sys/types.h>
00109
#include <stdlib.h>
00110
#include <unistd.h>
00111
#include <errno.h>
00112
#include <fcntl.h>
00113
#include <assert.h>
00114
00115
#include "kmcomposewin.moc"
00116
00117
static const Kleo::CryptoMessageFormat cryptoMessageFormats[] = {
00118 Kleo::AutoFormat,
00119 Kleo::InlineOpenPGPFormat,
00120 Kleo::OpenPGPMIMEFormat,
00121 Kleo::SMIMEFormat,
00122 Kleo::SMIMEOpaqueFormat,
00123 };
00124
static const int numCryptoMessageFormats =
sizeof cryptoMessageFormats /
sizeof *cryptoMessageFormats ;
00125
00126
static inline Kleo::CryptoMessageFormat cb2format(
int idx ) {
00127
return cryptoMessageFormats[ idx >= 0 && idx < numCryptoMessageFormats ? idx : 0 ];
00128 }
00129
00130
static inline int format2cb( Kleo::CryptoMessageFormat f ) {
00131
for (
int i = 0 ; i < numCryptoMessageFormats ; ++i )
00132
if ( f == cryptoMessageFormats[i] )
00133
return i;
00134
return 0;
00135 }
00136
00137
00138 KMComposeWin::KMComposeWin( KMMessage *aMsg, uint
id )
00139 :
MailComposerIface(), KMail::
SecondaryWindow( "kmail-composer#" ),
00140 mSpellCheckInProgress( false ),
00141 mDone( false ),
00142 mAtmModified( false ),
00143 mMsg( 0 ),
00144 mAttachMenu( 0 ),
00145 mAutoRequestMDN( false ),
00146 mFolder( 0 ),
00147 mUseHTMLEditor( false ),
00148 mId( id ),
00149 mAttachPK( 0 ), mAttachMPK( 0 ),
00150 mAttachRemoveAction( 0 ), mAttachSaveAction( 0 ), mAttachPropertiesAction( 0 ),
00151 mSignAction( 0 ), mEncryptAction( 0 ), mRequestMDNAction( 0 ),
00152 mUrgentAction( 0 ), mAllFieldsAction( 0 ), mFromAction( 0 ),
00153 mReplyToAction( 0 ), mToAction( 0 ), mCcAction( 0 ), mBccAction( 0 ),
00154 mSubjectAction( 0 ),
00155 mIdentityAction( 0 ), mTransportAction( 0 ), mFccAction( 0 ),
00156 mWordWrapAction( 0 ), mFixedFontAction( 0 ), mAutoSpellCheckingAction( 0 ),
00157 mDictionaryAction( 0 ),
00158 mEncodingAction( 0 ),
00159 mCryptoModuleAction( 0 ),
00160 mComposer( 0 )
00161 {
00162 mSubjectTextWasSpellChecked =
false;
00163
if (kmkernel->xmlGuiInstance())
00164 setInstance( kmkernel->xmlGuiInstance() );
00165 mMainWidget =
new QWidget(
this);
00166 mIdentity =
new KPIM::IdentityCombo(kmkernel->identityManager(), mMainWidget);
00167 mDictionaryCombo =
new DictionaryComboBox( mMainWidget );
00168 mFcc =
new KMFolderComboBox(mMainWidget);
00169 mFcc->showOutboxFolder( FALSE );
00170 mTransport =
new QComboBox(
true, mMainWidget);
00171 mEdtFrom =
new KMLineEdit(
this,
false,mMainWidget);
00172 mEdtReplyTo =
new KMLineEdit(
this,
false,mMainWidget);
00173 mEdtTo =
new KMLineEdit(
this,
true,mMainWidget);
00174 mEdtCc =
new KMLineEdit(
this,
true,mMainWidget);
00175 mEdtBcc =
new KMLineEdit(
this,
true,mMainWidget);
00176 mEdtSubject =
new KMLineEditSpell(
this,
false,mMainWidget,
"subjectLine");
00177 mLblIdentity =
new QLabel(mMainWidget);
00178 mDictionaryLabel =
new QLabel( mMainWidget );
00179 mLblFcc =
new QLabel(mMainWidget);
00180 mLblTransport =
new QLabel(mMainWidget);
00181 mLblFrom =
new QLabel(mMainWidget);
00182 mLblReplyTo =
new QLabel(mMainWidget);
00183 mLblTo =
new QLabel(mMainWidget);
00184 mLblCc =
new QLabel(mMainWidget);
00185 mLblBcc =
new QLabel(mMainWidget);
00186 mLblSubject =
new QLabel(mMainWidget);
00187
QString sticky = i18n(
"Sticky");
00188 mBtnIdentity =
new QCheckBox(sticky,mMainWidget);
00189 mBtnFcc =
new QCheckBox(sticky,mMainWidget);
00190 mBtnTransport =
new QCheckBox(sticky,mMainWidget);
00191 mBtnTo =
new QPushButton(
"...",mMainWidget);
00192 mBtnCc =
new QPushButton(
"...",mMainWidget);
00193 mBtnBcc =
new QPushButton(
"...",mMainWidget);
00194
00195 mBtnReplyTo =
new QPushButton(
"...",mMainWidget);
00196
00197
00198 mDone =
false;
00199 mGrid = 0;
00200 mAtmListView = 0;
00201 mAtmList.setAutoDelete(TRUE);
00202 mAtmTempList.setAutoDelete(TRUE);
00203 mAtmModified = FALSE;
00204 mAutoDeleteMsg = FALSE;
00205 mFolder = 0;
00206 mAutoCharset = TRUE;
00207 mFixedFontAction = 0;
00208 mEditor =
new KMEdit( mMainWidget,
this, mDictionaryCombo->spellConfig() );
00209 mEditor->setTextFormat(Qt::PlainText);
00210 mEditor->setAcceptDrops(
true );
00211
00212
QString tip = i18n(
"Select email address(es)");
00213 QToolTip::add( mBtnTo, tip );
00214 QToolTip::add( mBtnCc, tip );
00215 QToolTip::add( mBtnReplyTo, tip );
00216
00217 QWhatsThis::add( mBtnIdentity, i18n(
"Remember this identity, so that it "
00218
"will be used in future composer windows as well."));
00219 QWhatsThis::add( mBtnFcc, i18n(
"Remember this folder for sent items, so "
00220
"that it will be used in future composer windows as well."));
00221 QWhatsThis::add( mBtnTransport, i18n(
"Remember this mail transport, so "
00222
"that it will be used in future composer windows as well."));
00223
00224 mSpellCheckInProgress=FALSE;
00225
00226 setCaption( i18n(
"Composer") );
00227 setMinimumSize(200,200);
00228
00229 mBtnIdentity->setFocusPolicy(QWidget::NoFocus);
00230 mBtnFcc->setFocusPolicy(QWidget::NoFocus);
00231 mBtnTransport->setFocusPolicy(QWidget::NoFocus);
00232 mBtnTo->setFocusPolicy(QWidget::NoFocus);
00233 mBtnCc->setFocusPolicy(QWidget::NoFocus);
00234 mBtnBcc->setFocusPolicy(QWidget::NoFocus);
00235
00236 mBtnReplyTo->setFocusPolicy(QWidget::NoFocus);
00237
00238 mAtmListView =
new AttachmentListView(
this, mMainWidget,
00239
"attachment list view" );
00240 mAtmListView->setSelectionMode( QListView::Extended );
00241 mAtmListView->setFocusPolicy( QWidget::NoFocus );
00242 mAtmListView->addColumn( i18n(
"Name"), 200 );
00243 mAtmListView->addColumn( i18n(
"Size"), 80 );
00244 mAtmListView->addColumn( i18n(
"Encoding"), 120 );
00245
int atmColType = mAtmListView->addColumn( i18n(
"Type"), 120 );
00246
00247 mAtmListView->header()->setStretchEnabled(
true, atmColType );
00248 mAtmEncryptColWidth = 80;
00249 mAtmSignColWidth = 80;
00250 mAtmColEncrypt = mAtmListView->addColumn( i18n(
"Encrypt"),
00251 mAtmEncryptColWidth );
00252 mAtmColSign = mAtmListView->addColumn( i18n(
"Sign"),
00253 mAtmSignColWidth );
00254 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
00255 mAtmListView->setColumnWidth( mAtmColSign, 0 );
00256 mAtmListView->setAllColumnsShowFocus(
true );
00257
00258 connect( mAtmListView,
00259 SIGNAL( doubleClicked(
QListViewItem* ) ),
00260 SLOT( slotAttachProperties() ) );
00261 connect( mAtmListView,
00262 SIGNAL( rightButtonPressed(
QListViewItem*,
const QPoint&,
int ) ),
00263 SLOT( slotAttachPopupMenu(
QListViewItem*,
const QPoint&,
int ) ) );
00264 connect( mAtmListView,
00265 SIGNAL( selectionChanged() ),
00266 SLOT( slotUpdateAttachActions() ) );
00267 mAttachMenu = 0;
00268
00269 readConfig();
00270 setupStatusBar();
00271 setupEditor();
00272 setupActions();
00273
00274 applyMainWindowSettings(KMKernel::config(),
"Composer");
00275
00276 connect( mEdtSubject, SIGNAL( subjectTextSpellChecked() ),
00277 SLOT( slotSubjectTextSpellChecked() ) );
00278 connect(mEdtSubject,SIGNAL(textChanged(
const QString&)),
00279 SLOT(slotUpdWinTitle(
const QString&)));
00280 connect(mBtnTo,SIGNAL(clicked()),SLOT(slotAddrBookTo()));
00281 connect(mBtnCc,SIGNAL(clicked()),SLOT(slotAddrBookTo()));
00282 connect(mBtnBcc,SIGNAL(clicked()),SLOT(slotAddrBookTo()));
00283 connect(mBtnReplyTo,SIGNAL(clicked()),SLOT(slotAddrBookReplyTo()));
00284
00285 connect(mIdentity,SIGNAL(identityChanged(uint)),
00286 SLOT(slotIdentityChanged(uint)));
00287 connect( kmkernel->identityManager(), SIGNAL(changed(uint)),
00288 SLOT(slotIdentityChanged(uint)));
00289
00290 connect(mEdtTo,SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
00291 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)));
00292 connect(mEdtCc,SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
00293 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)));
00294 connect(mEdtBcc,SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
00295 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)));
00296 connect(mEdtReplyTo,SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
00297 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)));
00298 connect(mEdtFrom,SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
00299 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)));
00300 connect(kmkernel->folderMgr(),SIGNAL(folderRemoved(
KMFolder*)),
00301 SLOT(slotFolderRemoved(
KMFolder*)));
00302 connect(kmkernel->imapFolderMgr(),SIGNAL(folderRemoved(
KMFolder*)),
00303 SLOT(slotFolderRemoved(
KMFolder*)));
00304 connect(kmkernel->dimapFolderMgr(),SIGNAL(folderRemoved(
KMFolder*)),
00305 SLOT(slotFolderRemoved(
KMFolder*)));
00306 connect( kmkernel, SIGNAL( configChanged() ),
00307
this, SLOT( slotConfigChanged() ) );
00308
00309 connect (mEditor, SIGNAL (spellcheck_done(
int)),
00310
this, SLOT (slotSpellcheckDone (
int)));
00311
00312 mMainWidget->resize(480,510);
00313 setCentralWidget(mMainWidget);
00314 rethinkFields();
00315
00316
if (mUseExtEditor) {
00317 mEditor->setUseExternalEditor(
true);
00318 mEditor->setExternalEditorPath(mExtEditor);
00319 }
00320
00321 mMsg = 0;
00322
if (aMsg)
00323 setMsg(aMsg);
00324
00325 mEdtTo->setFocus();
00326
00327 mDone =
true;
00328 }
00329
00330
template <
typename T>
00331
inline void Delete(
const T * t ) {
00332
delete t; t = 0;
00333 }
00334
00335
00336 KMComposeWin::~KMComposeWin()
00337 {
00338 writeConfig();
00339
if (mFolder && mMsg)
00340 {
00341 mAutoDeleteMsg = FALSE;
00342 mFolder->addMsg(mMsg);
00343
00344 mFolder->unGetMsg( mFolder->count() - 1 );
00345 }
00346
if (mAutoDeleteMsg) {
00347
delete mMsg;
00348 mMsg = 0;
00349 }
00350
QMap<KIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.begin();
00351
while ( it != mMapAtmLoadData.end() )
00352 {
00353 KIO::Job *job = it.key();
00354 mMapAtmLoadData.remove( it );
00355 job->kill();
00356 it = mMapAtmLoadData.begin();
00357 }
00358 std::for_each( mComposedMessages.begin(), mComposedMessages.end(), Delete<KMMessage> );
00359 }
00360
00361
void KMComposeWin::setAutoDeleteWindow(
bool f )
00362 {
00363
if ( f )
00364 setWFlags( getWFlags() | WDestructiveClose );
00365
else
00366 setWFlags( getWFlags() & ~WDestructiveClose );
00367 }
00368
00369
00370
void KMComposeWin::send(
int how)
00371 {
00372
switch (how) {
00373
case 1:
00374 slotSendNow();
00375
break;
00376
default:
00377
case 0:
00378
00379
case 2:
00380 slotSendLater();
00381
break;
00382 }
00383 }
00384
00385
00386
void KMComposeWin::addAttachment(KURL url,
QString )
00387 {
00388 addAttach(url);
00389 }
00390
00391
00392
void KMComposeWin::addAttachment(
const QString &name,
00393
const QCString &,
00394
const QByteArray &data,
00395
const QCString &type,
00396
const QCString &subType,
00397
const QCString ¶mAttr,
00398
const QString ¶mValue,
00399
const QCString &contDisp)
00400 {
00401
if (!data.isEmpty()) {
00402 KMMessagePart *msgPart =
new KMMessagePart;
00403 msgPart->setName(name);
00404
QValueList<int> dummy;
00405 msgPart->setBodyAndGuessCte(data, dummy,
00406 kmkernel->msgSender()->sendQuotedPrintable());
00407 msgPart->setTypeStr(type);
00408 msgPart->setSubtypeStr(subType);
00409 msgPart->setParameter(paramAttr,paramValue);
00410 msgPart->setContentDisposition(contDisp);
00411 addAttach(msgPart);
00412 }
00413 }
00414
00415
00416
void KMComposeWin::setBody(
QString body)
00417 {
00418 mEditor->setText(body);
00419 }
00420
00421
00422
bool KMComposeWin::event(
QEvent *e)
00423 {
00424
if (e->type() == QEvent::ApplicationPaletteChange)
00425 {
00426 readColorConfig();
00427 }
00428
return KMail::SecondaryWindow::event(e);
00429 }
00430
00431
00432
00433
void KMComposeWin::readColorConfig(
void)
00434 {
00435 KConfig *config = KMKernel::config();
00436 KConfigGroupSaver saver(config,
"Reader");
00437
QColor c1=
QColor(kapp->palette().active().text());
00438 QColor c4=QColor(kapp->palette().active().base());
00439
00440
if (!config->readBoolEntry(
"defaultColors",TRUE)) {
00441 mForeColor = config->readColorEntry(
"ForegroundColor",&c1);
00442 mBackColor = config->readColorEntry(
"BackgroundColor",&c4);
00443 }
00444
else {
00445 mForeColor = c1;
00446 mBackColor = c4;
00447 }
00448
00449
00450 mPalette = kapp->palette();
00451
QColorGroup cgrp = mPalette.active();
00452 cgrp.setColor( QColorGroup::Base, mBackColor);
00453 cgrp.setColor( QColorGroup::Text, mForeColor);
00454 mPalette.setDisabled(cgrp);
00455 mPalette.setActive(cgrp);
00456 mPalette.setInactive(cgrp);
00457
00458 mEdtTo->setPalette(mPalette);
00459 mEdtFrom->setPalette(mPalette);
00460 mEdtCc->setPalette(mPalette);
00461 mEdtSubject->setPalette(mPalette);
00462 mEdtReplyTo->setPalette(mPalette);
00463 mEdtBcc->setPalette(mPalette);
00464 mTransport->setPalette(mPalette);
00465 mEditor->setPalette(mPalette);
00466 mFcc->setPalette(mPalette);
00467 }
00468
00469
00470
void KMComposeWin::readConfig(
void)
00471 {
00472 KConfig *config = KMKernel::config();
00473
QCString str;
00474
00475
int maxTransportItems;
00476
00477 KConfigGroupSaver saver(config,
"Composer");
00478
00479 mDefCharset = KMMessage::defaultCharset();
00480 mForceReplyCharset = config->readBoolEntry(
"force-reply-charset",
false );
00481 mAutoSign = config->readEntry(
"signature",
"auto") ==
"auto";
00482 mShowHeaders = config->readNumEntry(
"headers", HDR_STANDARD);
00483 mWordWrap = config->readBoolEntry(
"word-wrap",
true);
00484 mUseFixedFont = config->readBoolEntry(
"use-fixed-font",
false);
00485 mLineBreak = config->readNumEntry(
"break-at", 78);
00486 mBtnIdentity->setChecked(config->readBoolEntry(
"sticky-identity",
false));
00487
if (mBtnIdentity->isChecked())
00488 mId = config->readUnsignedNumEntry(
"previous-identity", mId );
00489 mBtnFcc->setChecked(config->readBoolEntry(
"sticky-fcc",
false));
00490
QString previousFcc = kmkernel->sentFolder()->idString();
00491
if (mBtnFcc->isChecked())
00492 previousFcc = config->readEntry(
"previous-fcc", previousFcc );
00493 mBtnTransport->setChecked(config->readBoolEntry(
"sticky-transport",
false));
00494 mTransportHistory = config->readListEntry(
"transport-history");
00495
QString currentTransport = config->readEntry(
"current-transport");
00496 maxTransportItems = config->readNumEntry(
"max-transport-items",10);
00497
00498
if ((mLineBreak == 0) || (mLineBreak > 78))
00499 mLineBreak = 78;
00500
if (mLineBreak < 30)
00501 mLineBreak = 30;
00502 mOutlookCompatible = config->readBoolEntry(
"outlook-compatible-attachments",
false );
00503 mAutoPgpSign = config->readBoolEntry(
"pgp-auto-sign",
false);
00504 mAutoPgpEncrypt = config->readBoolEntry(
"pgp-auto-encrypt",
false);
00505 mNeverEncryptWhenSavingInDrafts = config->readBoolEntry(
"never-encrypt-drafts",
true);
00506 mConfirmSend = config->readBoolEntry(
"confirm-before-send",
false);
00507 mAutoRequestMDN = config->readBoolEntry(
"request-mdn",
false);
00508
00509
int mode = config->readNumEntry(
"Completion Mode",
00510 KGlobalSettings::completionMode() );
00511 mEdtFrom->setCompletionMode( (KGlobalSettings::Completion) mode );
00512 mEdtReplyTo->setCompletionMode( (KGlobalSettings::Completion) mode );
00513 mEdtTo->setCompletionMode( (KGlobalSettings::Completion) mode );
00514 mEdtCc->setCompletionMode( (KGlobalSettings::Completion) mode );
00515 mEdtBcc->setCompletionMode( (KGlobalSettings::Completion) mode );
00516
00517 readColorConfig();
00518
00519 {
00520 KConfigGroupSaver saver(config,
"General");
00521 mExtEditor = config->readPathEntry(
"external-editor", DEFAULT_EDITOR_STR);
00522 mUseExtEditor = config->readBoolEntry(
"use-external-editor", FALSE);
00523
00524
int headerCount = config->readNumEntry(
"mime-header-count", 0);
00525 mCustHeaders.clear();
00526 mCustHeaders.setAutoDelete(
true);
00527
for (
int i = 0; i < headerCount; i++) {
00528
QString thisGroup;
00529 _StringPair *thisItem =
new _StringPair;
00530 thisGroup.sprintf(
"Mime #%d", i);
00531 KConfigGroupSaver saver(config, thisGroup);
00532 thisItem->name = config->readEntry(
"name");
00533
if ((thisItem->name).length() > 0) {
00534 thisItem->value = config->readEntry(
"value");
00535 mCustHeaders.append(thisItem);
00536 }
else {
00537
delete thisItem;
00538 thisItem = 0;
00539 }
00540 }
00541 }
00542
00543 {
00544 KConfigGroupSaver saver(config,
"Fonts");
00545 mBodyFont = KGlobalSettings::generalFont();
00546 mFixedFont = KGlobalSettings::fixedFont();
00547
if (!config->readBoolEntry(
"defaultFonts",TRUE)) {
00548 mBodyFont = config->readFontEntry(
"composer-font", &mBodyFont);
00549 mFixedFont = config->readFontEntry(
"fixed-font", &mFixedFont);
00550 }
00551 slotUpdateFont();
00552 mEdtFrom->setFont(mBodyFont);
00553 mEdtReplyTo->setFont(mBodyFont);
00554 mEdtTo->setFont(mBodyFont);
00555 mEdtCc->setFont(mBodyFont);
00556 mEdtBcc->setFont(mBodyFont);
00557 mEdtSubject->setFont(mBodyFont);
00558 }
00559
00560 {
00561 KConfigGroupSaver saver(config,
"Geometry");
00562
QSize defaultSize(480,510);
00563
QSize siz = config->readSizeEntry(
"composer", &defaultSize);
00564
if (siz.width() < 200) siz.setWidth(200);
00565
if (siz.height() < 200) siz.setHeight(200);
00566 resize(siz);
00567 }
00568
00569 mIdentity->setCurrentIdentity( mId );
00570
00571 kdDebug(5006) <<
"KMComposeWin::readConfig. " << mIdentity->currentIdentityName() << endl;
00572
const KPIM::Identity & ident =
00573 kmkernel->identityManager()->identityForUoid( mIdentity->currentIdentity() );
00574
00575 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
00576
00577 mTransport->clear();
00578 mTransport->insertStringList( KMTransportInfo::availableTransports() );
00579
while (mTransportHistory.count() > (uint)maxTransportItems)
00580 mTransportHistory.remove( mTransportHistory.last() );
00581 mTransport->insertStringList( mTransportHistory );
00582
if (mBtnTransport->isChecked() && !currentTransport.isEmpty())
00583 {
00584
for (
int i = 0; i < mTransport->count(); i++)
00585
if (mTransport->text(i) == currentTransport)
00586 mTransport->setCurrentItem(i);
00587 mTransport->setEditText( currentTransport );
00588 }
00589
00590
if ( !mBtnFcc->isChecked() )
00591 {
00592 kdDebug(5006) <<
"KMComposeWin::readConfig: identity.fcc()='"
00593 << ident.fcc() <<
"'" << endl;
00594
if ( ident.fcc().isEmpty() )
00595 previousFcc = kmkernel->sentFolder()->idString();
00596
else
00597 previousFcc = ident.fcc();
00598 kdDebug(5006) <<
"KMComposeWin::readConfig: previousFcc="
00599 << previousFcc << endl;
00600 }
00601
00602 setFcc( previousFcc );
00603 }
00604
00605
00606
void KMComposeWin::writeConfig(
void)
00607 {
00608 KConfig *config = KMKernel::config();
00609
QString str;
00610
00611 {
00612 KConfigGroupSaver saver(config,
"Composer");
00613 config->writeEntry(
"signature", mAutoSign?
"auto":
"manual");
00614 config->writeEntry(
"headers", mShowHeaders);
00615 config->writeEntry(
"sticky-transport", mBtnTransport->isChecked());
00616 config->writeEntry(
"sticky-identity", mBtnIdentity->isChecked());
00617 config->writeEntry(
"sticky-fcc", mBtnFcc->isChecked());
00618 config->writeEntry(
"previous-identity", mIdentity->currentIdentity() );
00619 config->writeEntry(
"current-transport", mTransport->currentText());
00620 config->writeEntry(
"previous-fcc", mFcc->getFolder()->idString() );
00621 config->writeEntry(
"autoSpellChecking",
00622 mAutoSpellCheckingAction->isChecked() );
00623 mTransportHistory.remove(mTransport->currentText());
00624
if (KMTransportInfo::availableTransports().findIndex(mTransport
00625 ->currentText()) == -1)
00626 mTransportHistory.prepend(mTransport->currentText());
00627 config->writeEntry(
"transport-history", mTransportHistory );
00628 config->writeEntry(
"use-fixed-font", mUseFixedFont );
00629 }
00630
00631 {
00632 KConfigGroupSaver saver(config,
"Geometry");
00633 config->writeEntry(
"composer", size());
00634
00635 saveMainWindowSettings(config,
"Composer");
00636 config->sync();
00637 }
00638 }
00639
00640
00641
00642
void KMComposeWin::deadLetter()
00643 {
00644
if (!mMsg || mComposer)
return;
00645
00646 connect(
this, SIGNAL( applyChangesDone(
bool ) ),
00647
this, SLOT( slotContinueDeadLetter(
bool ) ) );
00648
00649
00650
00651 applyChanges(
true,
true );
00652
00653
00654 qApp->enter_loop();
00655
00656
00657
if ( mComposedMessages.isEmpty() ) {
00658 kdDebug(5006) <<
"Composing the message failed." << endl;
00659
return;
00660 }
00661 KMMessage *msg = mComposedMessages.first();
00662
QCString msgStr = msg->asString();
00663
QCString fname = getenv(
"HOME");
00664 fname +=
"/dead.letter.tmp";
00665
00666
00667
00668
00669
00670
int fd = open(fname, O_CREAT|O_APPEND|O_WRONLY, S_IWRITE|S_IREAD);
00671
if (fd != -1)
00672 {
00673
QCString startStr( msg->mboxMessageSeparator() );
00674 ::write(fd, startStr, startStr.length());
00675 ::write(fd, msgStr, msgStr.length());
00676 ::write(fd,
"\n", 1);
00677 ::close(fd);
00678 fprintf(stderr,
"appending message to ~/dead.letter.tmp\n");
00679 }
else {
00680 perror(
"cannot open ~/dead.letter.tmp for saving the current message");
00681 kmkernel->emergencyExit( i18n(
"cannot open ~/dead.letter.tmp for saving the current message: ") +
00682 QString::fromLocal8Bit(strerror(errno)));
00683 }
00684 }
00685
00686
void KMComposeWin::slotContinueDeadLetter(
bool )
00687 {
00688 disconnect(
this, SIGNAL( applyChangesDone(
bool ) ),
00689
this, SLOT( slotContinueDeadLetter(
bool ) ) );
00690 qApp->exit_loop();
00691 }
00692
00693
00694
void KMComposeWin::slotView(
void)
00695 {
00696
if (!mDone)
00697
return;
00698
00699
int id;
00700
00701
00702
00703
if (!sender()->isA(
"KToggleAction"))
00704
return;
00705 KToggleAction *act = (KToggleAction *) sender();
00706
00707
if (act == mAllFieldsAction)
00708
id = 0;
00709
else if (act == mIdentityAction)
00710
id = HDR_IDENTITY;
00711
else if (act == mTransportAction)
00712
id = HDR_TRANSPORT;
00713
else if (act == mFromAction)
00714
id = HDR_FROM;
00715
else if (act == mReplyToAction)
00716
id = HDR_REPLY_TO;
00717
else if (act == mToAction)
00718
id = HDR_TO;
00719
else if (act == mCcAction)
00720
id = HDR_CC;
00721
else if (act == mBccAction)
00722
id = HDR_BCC;
00723
else if (act == mSubjectAction)
00724
id = HDR_SUBJECT;
00725
else if (act == mFccAction)
00726
id = HDR_FCC;
00727
else if ( act == mDictionaryAction )
00728
id = HDR_DICTIONARY;
00729
else
00730 {
00731
id = 0;
00732 kdDebug(5006) <<
"Something is wrong (Oh, yeah?)" << endl;
00733
return;
00734 }
00735
00736
00737
00738
00739
if (!act->isChecked())
00740 {
00741
00742
if (
id > 0) mShowHeaders = mShowHeaders & ~id;
00743
else mShowHeaders = abs(mShowHeaders);
00744 }
00745
else
00746 {
00747
00748
if (
id > 0) mShowHeaders |=
id;
00749
else mShowHeaders = -abs(mShowHeaders);
00750 }
00751 rethinkFields(
true);
00752
00753 }
00754
00755
void KMComposeWin::rethinkFields(
bool fromSlot)
00756 {
00757
00758
int mask, row, numRows;
00759
long showHeaders;
00760
00761
if (mShowHeaders < 0)
00762 showHeaders = HDR_ALL;
00763
else
00764 showHeaders = mShowHeaders;
00765
00766
for (mask=1,mNumHeaders=0; mask<=showHeaders; mask<<=1)
00767
if ((showHeaders&mask) != 0) mNumHeaders++;
00768
00769 numRows = mNumHeaders + 2;
00770
00771
delete mGrid;
00772 mGrid =
new QGridLayout(mMainWidget, numRows, 3, 4, 4);
00773 mGrid->setColStretch(0, 1);
00774 mGrid->setColStretch(1, 100);
00775 mGrid->setColStretch(2, 1);
00776 mGrid->setRowStretch(mNumHeaders, 100);
00777
00778 mEdtList.clear();
00779 row = 0;
00780 kdDebug(5006) <<
"KMComposeWin::rethinkFields" << endl;
00781
if (!fromSlot) mAllFieldsAction->setChecked(showHeaders==HDR_ALL);
00782
00783
if (!fromSlot) mIdentityAction->setChecked(abs(mShowHeaders)&HDR_IDENTITY);
00784 rethinkHeaderLine(showHeaders,HDR_IDENTITY, row, i18n(
"&Identity:"),
00785 mLblIdentity, mIdentity, mBtnIdentity);
00786
if (!fromSlot) mDictionaryAction->setChecked(abs(mShowHeaders)&HDR_DICTIONARY);
00787 rethinkHeaderLine(showHeaders,HDR_DICTIONARY, row, i18n(
"&Dictionary:"),
00788 mDictionaryLabel, mDictionaryCombo, 0 );
00789
if (!fromSlot) mFccAction->setChecked(abs(mShowHeaders)&HDR_FCC);
00790 rethinkHeaderLine(showHeaders,HDR_FCC, row, i18n(
"Se&nt-Mail folder:"),
00791 mLblFcc, mFcc, mBtnFcc);
00792
if (!fromSlot) mTransportAction->setChecked(abs(mShowHeaders)&HDR_TRANSPORT);
00793 rethinkHeaderLine(showHeaders,HDR_TRANSPORT, row, i18n(
"Mai&l transport:"),
00794 mLblTransport, mTransport, mBtnTransport);
00795
if (!fromSlot) mFromAction->setChecked(abs(mShowHeaders)&HDR_FROM);
00796 rethinkHeaderLine(showHeaders,HDR_FROM, row, i18n(
"&From:"),
00797 mLblFrom, mEdtFrom );
00798
if (!fromSlot) mReplyToAction->setChecked(abs(mShowHeaders)&HDR_REPLY_TO);
00799 rethinkHeaderLine(showHeaders,HDR_REPLY_TO,row,i18n(
"&Reply to:"),
00800 mLblReplyTo, mEdtReplyTo, mBtnReplyTo);
00801
if (!fromSlot) mToAction->setChecked(abs(mShowHeaders)&HDR_TO);
00802 rethinkHeaderLine(showHeaders, HDR_TO, row, i18n(
"To:"),
00803 mLblTo, mEdtTo, mBtnTo,
00804 i18n(
"Primary Recipients"),
00805 i18n(
"<qt>The email addresses you put "
00806
"in this field receive a copy of the email.</qt>"));
00807
if (!fromSlot) mCcAction->setChecked(abs(mShowHeaders)&HDR_CC);
00808 rethinkHeaderLine(showHeaders, HDR_CC, row, i18n(
"&Copy to (CC):"),
00809 mLblCc, mEdtCc, mBtnCc,
00810 i18n(
"Additional Recipients"),
00811 i18n(
"<qt>The email addresses you put "
00812
"in this field receive a copy of the email. "
00813
"Technically it is the same thing as putting all the "
00814
"addresses in the <b>To:</b> field but differs in "
00815
"that it usually symbolises the receiver of the "
00816
"Carbon Copy (CC) is a listener, not the main "
00817
"recipient.</qt>"));
00818
if (!fromSlot) mBccAction->setChecked(abs(mShowHeaders)&HDR_BCC);
00819 rethinkHeaderLine(showHeaders,HDR_BCC, row, i18n(
"&Blind copy to (BCC):"),
00820 mLblBcc, mEdtBcc, mBtnBcc,
00821 i18n(
"Hidden Recipients"),
00822 i18n(
"<qt>Essentially the same thing "
00823
"as the <b>Copy To:</b> field but differs in that "
00824
"all other recipients do not see who receives a "
00825
"blind copy.</qt>"));
00826
if (!fromSlot) mSubjectAction->setChecked(abs(mShowHeaders)&HDR_SUBJECT);
00827 rethinkHeaderLine(showHeaders,HDR_SUBJECT, row, i18n(
"S&ubject:"),
00828 mLblSubject, mEdtSubject);
00829 assert(row<=mNumHeaders);
00830
00831 mGrid->addMultiCellWidget(mEditor, row, mNumHeaders, 0, 2);
00832 mGrid->addMultiCellWidget(mAtmListView, mNumHeaders+1, mNumHeaders+1, 0, 2);
00833
00834
if( !mAtmList.isEmpty() )
00835 mAtmListView->show();
00836
else
00837 mAtmListView->hide();
00838 resize(this->size());
00839 repaint();
00840
00841 mGrid->activate();
00842
00843 slotUpdateAttachActions();
00844 mIdentityAction->setEnabled(!mAllFieldsAction->isChecked());
00845 mDictionaryAction->setEnabled( !mAllFieldsAction->isChecked() );
00846 mTransportAction->setEnabled(!mAllFieldsAction->isChecked());
00847 mFromAction->setEnabled(!mAllFieldsAction->isChecked());
00848 mReplyToAction->setEnabled(!mAllFieldsAction->isChecked());
00849 mToAction->setEnabled(!mAllFieldsAction->isChecked());
00850 mCcAction->setEnabled(!mAllFieldsAction->isChecked());
00851 mBccAction->setEnabled(!mAllFieldsAction->isChecked());
00852 mFccAction->setEnabled(!mAllFieldsAction->isChecked());
00853 mSubjectAction->setEnabled(!mAllFieldsAction->isChecked());
00854 }
00855
00856
00857
00858
void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
00859
const QString &aLabelStr, QLabel* aLbl,
00860
QLineEdit* aEdt, QPushButton* aBtn,
00861
const QString &toolTip,
const QString &whatsThis )
00862 {
00863
if (aValue & aMask)
00864 {
00865 aLbl->setText(aLabelStr);
00866
if ( !toolTip.isEmpty() )
00867 QToolTip::add( aLbl, toolTip );
00868
if ( !whatsThis.isEmpty() )
00869 QWhatsThis::add( aLbl, whatsThis );
00870 aLbl->adjustSize();
00871 aLbl->resize((
int)aLbl->sizeHint().width(),aLbl->sizeHint().height() + 6);
00872 aLbl->setMinimumSize(aLbl->size());
00873 aLbl->show();
00874 aLbl->setBuddy(aEdt);
00875 mGrid->addWidget(aLbl, aRow, 0);
00876
00877 aEdt->setBackgroundColor( mBackColor );
00878 aEdt->show();
00879 aEdt->setMinimumSize(100, aLbl->height()+2);
00880 mEdtList.append(aEdt);
00881
00882 mGrid->addWidget(aEdt, aRow, 1);
00883
if (aBtn)
00884 {
00885 mGrid->addWidget(aBtn, aRow, 2);
00886 aBtn->setFixedSize(aBtn->sizeHint().width(), aLbl->height());
00887 aBtn->show();
00888 }
00889 aRow++;
00890 }
00891
else
00892 {
00893 aLbl->hide();
00894 aEdt->hide();
00895
if (aBtn) aBtn->hide();
00896 }
00897 }
00898
00899
00900
void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
00901
const QString &aLabelStr, QLabel* aLbl,
00902 QComboBox* aCbx, QCheckBox* aChk)
00903 {
00904
if (aValue & aMask)
00905 {
00906 aLbl->setText(aLabelStr);
00907 aLbl->adjustSize();
00908 aLbl->resize((
int)aLbl->sizeHint().width(),aLbl->sizeHint().height() + 6);
00909 aLbl->setMinimumSize(aLbl->size());
00910 aLbl->show();
00911 aLbl->setBuddy(aCbx);
00912 mGrid->addWidget(aLbl, aRow, 0);
00913
00914
00915 aCbx->show();
00916 aCbx->setMinimumSize(100, aLbl->height()+2);
00917
00918 mGrid->addWidget(aCbx, aRow, 1);
00919
if ( aChk ) {
00920 mGrid->addWidget(aChk, aRow, 2);
00921 aChk->setFixedSize(aChk->sizeHint().width(), aLbl->height());
00922 aChk->show();
00923 }
00924 aRow++;
00925 }
00926
else
00927 {
00928 aLbl->hide();
00929 aCbx->hide();
00930
if ( aChk )
00931 aChk->hide();
00932 }
00933 }
00934
00935
00936
void KMComposeWin::setupActions(
void)
00937 {
00938
if (kmkernel->msgSender()->sendImmediate())
00939 {
00940
00941 (
void)
new KAction (i18n(
"&Send"),
"mail_send", CTRL+Key_Return,
00942
this, SLOT(slotSendNow()), actionCollection(),
00943
"send_default");
00944 (
void)
new KAction (i18n(
"&Queue"),
"queue", 0,
00945
this, SLOT(slotSendLater()),
00946 actionCollection(),
"send_alternative");
00947 }
00948
else
00949 {
00950
00951 (
void)
new KAction (i18n(
"&Queue"),
"queue",
00952 CTRL+Key_Return,
00953
this, SLOT(slotSendLater()), actionCollection(),
00954
"send_default");
00955 (
void)
new KAction (i18n(
"&Send Now"),
"mail_send", 0,
00956
this, SLOT(slotSendNow()),
00957 actionCollection(),
"send_alternative");
00958 }
00959
00960 (
void)
new KAction (i18n(
"Save in &Drafts Folder"),
"filesave", 0,
00961
this, SLOT(slotSaveDraft()),
00962 actionCollection(),
"save_in_drafts");
00963 (
void)
new KAction (i18n(
"&Insert File..."),
"fileopen", 0,
00964
this, SLOT(slotInsertFile()),
00965 actionCollection(),
"insert_file");
00966 (
void)
new KAction (i18n(
"&Address Book"),
"contents",0,
00967
this, SLOT(slotAddrBook()),
00968 actionCollection(),
"addressbook");
00969 (
void)
new KAction (i18n(
"&New Composer"),
"mail_new",
00970 KStdAccel::shortcut(KStdAccel::New),
00971
this, SLOT(slotNewComposer()),
00972 actionCollection(),
"new_composer");
00973 (
void)
new KAction (i18n(
"New Main &Window"),
"window_new", 0,
00974
this, SLOT(slotNewMailReader()),
00975 actionCollection(),
"open_mailreader");
00976
00977
00978
00979 KStdAction::print (
this, SLOT(slotPrint()), actionCollection());
00980 KStdAction::close (
this, SLOT(slotClose()), actionCollection());
00981
00982 KStdAction::undo (
this, SLOT(slotUndo()), actionCollection());
00983 KStdAction::redo (
this, SLOT(slotRedo()), actionCollection());
00984 KStdAction::cut (
this, SLOT(slotCut()), actionCollection());
00985 KStdAction::copy (
this, SLOT(slotCopy()), actionCollection());
00986 KStdAction::pasteText (
this, SLOT(slotPaste()), actionCollection());
00987 KStdAction::selectAll (
this, SLOT(slotMarkAll()), actionCollection());
00988
00989 KStdAction::find (
this, SLOT(slotFind()), actionCollection());
00990 KStdAction::findNext(
this, SLOT(slotSearchAgain()), actionCollection());
00991
00992 KStdAction::replace (
this, SLOT(slotReplace()), actionCollection());
00993 KStdAction::spelling (
this, SLOT(slotSpellcheck()), actionCollection(),
"spellcheck");
00994
00995 (
void)
new KAction (i18n(
"Pa&ste as Quotation"),0,
this,SLOT( slotPasteAsQuotation()),
00996 actionCollection(),
"paste_quoted");
00997
00998 (
void)
new KAction(i18n(
"Add &Quote Characters"), 0,
this,
00999 SLOT(slotAddQuotes()), actionCollection(),
"tools_quote");
01000
01001 (
void)
new KAction(i18n(
"Re&move Quote Characters"), 0,
this,
01002 SLOT(slotRemoveQuotes()), actionCollection(),
"tools_unquote");
01003
01004
01005 (
void)
new KAction (i18n(
"Cl&ean Spaces"), 0,
this, SLOT(slotCleanSpace()),
01006 actionCollection(),
"clean_spaces");
01007
01008 mFixedFontAction =
new KToggleAction( i18n(
"Use Fi&xed Font"), 0,
this,
01009 SLOT(slotUpdateFont()), actionCollection(),
"toggle_fixedfont" );
01010 mFixedFontAction->setChecked(mUseFixedFont);
01011
01012
01013 mUrgentAction =
new KToggleAction (i18n(
"&Urgent"), 0,
01014 actionCollection(),
01015
"urgent");
01016 mRequestMDNAction =
new KToggleAction ( i18n(
"&Request Disposition Notification"), 0,
01017 actionCollection(),
01018
"options_request_mdn");
01019 mRequestMDNAction->setChecked(mAutoRequestMDN);
01020
01021 mEncodingAction =
new KSelectAction( i18n(
"Se&t Encoding" ),
"charset",
01022 0,
this, SLOT(slotSetCharset() ),
01023 actionCollection(),
"charsets" );
01024 mWordWrapAction =
new KToggleAction (i18n(
"&Wordwrap"), 0,
01025 actionCollection(),
"wordwrap");
01026 mWordWrapAction->setChecked(mWordWrap);
01027 connect(mWordWrapAction, SIGNAL(toggled(
bool)), SLOT(slotWordWrapToggled(
bool)));
01028
01029 mAutoSpellCheckingAction =
01030
new KToggleAction( i18n(
"&Automatic Spellchecking" ),
"spellcheck", 0,
01031 actionCollection(),
"options_auto_spellchecking" );
01032 KConfigGroup composerConfig( KMKernel::config(),
"Composer" );
01033
const bool spellChecking =
01034 composerConfig.readBoolEntry(
"autoSpellChecking",
true );
01035 mAutoSpellCheckingAction->setEnabled( !mUseExtEditor );
01036 mAutoSpellCheckingAction->setChecked( !mUseExtEditor && spellChecking );
01037 slotAutoSpellCheckingToggled( !mUseExtEditor && spellChecking );
01038 connect( mAutoSpellCheckingAction, SIGNAL( toggled(
bool ) ),
01039
this, SLOT( slotAutoSpellCheckingToggled(
bool ) ) );
01040
01041
QStringList encodings = KMMsgBase::supportedEncodings(TRUE);
01042 encodings.prepend( i18n(
"Auto-Detect"));
01043 mEncodingAction->setItems( encodings );
01044 mEncodingAction->setCurrentItem( -1 );
01045
01046
01047 markupAction =
new KToggleAction (i18n(
"Formatting (HTML)"), 0,
this,
01048 SLOT(slotToggleMarkup()),
01049 actionCollection(),
"html");
01050 markupAction->setChecked(mUseHTMLEditor);
01051
01052 mAllFieldsAction =
new KToggleAction (i18n(
"&All Fields"), 0,
this,
01053 SLOT(slotView()),
01054 actionCollection(),
"show_all_fields");
01055 mIdentityAction =
new KToggleAction (i18n(
"&Identity"), 0,
this,
01056 SLOT(slotView()),
01057 actionCollection(),
"show_identity");
01058 mDictionaryAction =
new KToggleAction (i18n(
"&Dictionary"), 0,
this,
01059 SLOT(slotView()),
01060 actionCollection(),
"show_dictionary");
01061 mFccAction =
new KToggleAction (i18n(
"Sent-Mail F&older"), 0,
this,
01062 SLOT(slotView()),
01063 actionCollection(),
"show_fcc");
01064 mTransportAction =
new KToggleAction (i18n(
"&Mail Transport"), 0,
this,
01065 SLOT(slotView()),
01066 actionCollection(),
"show_transport");
01067 mFromAction =
new KToggleAction (i18n(
"&From"), 0,
this,
01068 SLOT(slotView()),
01069 actionCollection(),
"show_from");
01070 mReplyToAction =
new KToggleAction (i18n(
"&Reply To"), 0,
this,
01071 SLOT(slotView()),
01072 actionCollection(),
"show_reply_to");
01073 mToAction =
new KToggleAction (i18n(
"&To"), 0,
this,
01074 SLOT(slotView()),
01075 actionCollection(),
"show_to");
01076 mCcAction =
new KToggleAction (i18n(
"&CC"), 0,
this,
01077 SLOT(slotView()),
01078 actionCollection(),
"show_cc");
01079 mBccAction =
new KToggleAction (i18n(
"&BCC"), 0,
this,
01080 SLOT(slotView()),
01081 actionCollection(),
"show_bcc");
01082 mSubjectAction =
new KToggleAction (i18n(
"&Subject"), 0,
this,
01083 SLOT(slotView()),
01084 actionCollection(),
"show_subject");
01085
01086
01087 (
void)
new KAction (i18n(
"Append S&ignature"), 0,
this,
01088 SLOT(slotAppendSignature()),
01089 actionCollection(),
"append_signature");
01090 mAttachPK =
new KAction (i18n(
"Attach &Public Key..."), 0,
this,
01091 SLOT(slotInsertPublicKey()),
01092 actionCollection(),
"attach_public_key");
01093 mAttachMPK =
new KAction (i18n(
"Attach &My Public Key"), 0,
this,
01094 SLOT(slotInsertMyPublicKey()),
01095 actionCollection(),
"attach_my_public_key");
01096 (
void)
new KAction (i18n(
"&Attach File..."),
"attach",
01097 0,
this, SLOT(slotAttachFile()),
01098 actionCollection(),
"attach");
01099 mAttachRemoveAction =
new KAction (i18n(
"&Remove Attachment"), 0,
this,
01100 SLOT(slotAttachRemove()),
01101 actionCollection(),
"remove");
01102 mAttachSaveAction =
new KAction (i18n(
"&Save Attachment As..."),
"filesave",0,
01103
this, SLOT(slotAttachSave()),
01104 actionCollection(),
"attach_save");
01105 mAttachPropertiesAction =
new KAction (i18n(
"Attachment Pr&operties"), 0,
this,
01106 SLOT(slotAttachProperties()),
01107 actionCollection(),
"attach_properties");
01108
01109 setStandardToolBarMenuEnabled(
true);
01110
01111 KStdAction::keyBindings(
this, SLOT(slotEditKeys()), actionCollection());
01112 KStdAction::configureToolbars(
this, SLOT(slotEditToolbars()), actionCollection());
01113 KStdAction::preferences(kmkernel, SLOT(slotShowConfigurationDialog()), actionCollection());
01114
01115 (
void)
new KAction (i18n(
"&Spellchecker..."), 0,
this, SLOT(slotSpellcheckConfig()),
01116 actionCollection(),
"setup_spellchecker");
01117
01118 mEncryptAction =
new KToggleAction (i18n(
"&Encrypt Message"),
01119
"decrypted", 0,
01120 actionCollection(),
"encrypt_message");
01121 mSignAction =
new KToggleAction (i18n(
"&Sign Message"),
01122
"signature", 0,
01123 actionCollection(),
"sign_message");
01124
01125
const KPIM::Identity & ident =
01126 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
01127
01128
01129 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
01130 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
01131
01132 mLastEncryptActionState =
false;
01133 mLastSignActionState = mAutoPgpSign;
01134
01135
01136 mAttachPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() );
01137
01138
01139
01140 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
01141 !ident.pgpEncryptionKey().isEmpty() );
01142
01143
if ( !Kleo::CryptoBackendFactory::instance()->openpgp() && !Kleo::CryptoBackendFactory::instance()->smime() ) {
01144
01145 mEncryptAction->setEnabled(
false );
01146 setEncryption(
false );
01147 mSignAction->setEnabled(
false );
01148 setSigning(
false );
01149 }
else {
01150
const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
01151 && !ident.pgpSigningKey().isEmpty();
01152
const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
01153 && !ident.smimeSigningKey().isEmpty();
01154
01155 setEncryption(
false );
01156 setSigning( ( canOpenPGPSign || canSMIMESign ) && mAutoPgpSign );
01157 }
01158
01159 connect(mEncryptAction, SIGNAL(toggled(
bool)),
01160 SLOT(slotEncryptToggled(
bool )));
01161 connect(mSignAction, SIGNAL(toggled(
bool)),
01162 SLOT(slotSignToggled(
bool )));
01163
01164
QStringList l;
01165
for (
int i = 0 ; i < numCryptoMessageFormats ; ++i )
01166 l.push_back( Kleo::cryptoMessageFormatToLabel( cryptoMessageFormats[i] ) );
01167
01168 mCryptoModuleAction =
new KSelectAction( i18n(
"&Cryptographic Message Format" ), 0,
01169
this, SLOT(slotSelectCryptoModule()),
01170 actionCollection(),
"options_select_crypto" );
01171 mCryptoModuleAction->setItems( l );
01172 mCryptoModuleAction->setCurrentItem( format2cb( ident.preferredCryptoMessageFormat() ) );
01173 slotSelectCryptoModule();
01174
01175
QStringList styleItems;
01176 styleItems << i18n(
"Standard" );
01177 styleItems << i18n(
"Bulleted List (Disc)" );
01178 styleItems << i18n(
"Bulleted List (Circle)" );
01179 styleItems << i18n(
"Bulleted List (Square)" );
01180 styleItems << i18n(
"Ordered List (Decimal)" );
01181 styleItems << i18n(
"Ordered List (Alpha lower)" );
01182 styleItems << i18n(
"Ordered List (Alpha upper)" );
01183
01184 listAction =
new KSelectAction( i18n(
"Select Style" ), 0, actionCollection(),
01185
"text_list" );
01186 listAction->setItems( styleItems );
01187 connect( listAction, SIGNAL( activated(
const QString& ) ),
01188 SLOT( slotListAction(
const QString& ) ) );
01189 fontAction =
new KFontAction(
"Select Font", 0, actionCollection(),
01190
"text_font" );
01191 connect( fontAction, SIGNAL( activated(
const QString& ) ),
01192 SLOT( slotFontAction(
const QString& ) ) );
01193 fontSizeAction =
new KFontSizeAction(
"Select Size", 0, actionCollection(),
01194
"text_size" );
01195 connect( fontSizeAction, SIGNAL( fontSizeChanged(
int ) ),
01196 SLOT( slotSizeAction(
int ) ) );
01197
01198 alignLeftAction =
new KToggleAction (i18n(
"Align Left"),
"text_left", 0,
01199
this, SLOT(slotAlignLeft()), actionCollection(),
01200
"align_left");
01201 alignLeftAction->setChecked( TRUE );
01202 alignRightAction =
new KToggleAction (i18n(
"Align Right"),
"text_right", 0,
01203
this, SLOT(slotAlignRight()), actionCollection(),
01204
"align_right");
01205 alignCenterAction =
new KToggleAction (i18n(
"Align Center"),
"text_center", 0,
01206
this, SLOT(slotAlignCenter()), actionCollection(),
01207
"align_center");
01208 textBoldAction =
new KToggleAction (i18n(
"&Bold"),
"text_bold", 0,
01209
this, SLOT(slotTextBold()),
01210 actionCollection(),
"text_bold");
01211 textItalicAction =
new KToggleAction (i18n(
"&Italic"),
"text_italic", 0,
01212
this, SLOT(slotTextItalic()),
01213 actionCollection(),
"text_italic");
01214 textUnderAction =
new KToggleAction (i18n(
"&Underline"),
"text_under", 0,
01215
this, SLOT(slotTextUnder()),
01216 actionCollection(),
"text_under");
01217 actionFormatReset =
new KAction( i18n(
"Reset Font Settings" ),
"eraser", 0,
01218
this, SLOT( slotFormatReset() ),
01219 actionCollection(),
"format_reset");
01220 actionFormatColor =
new KAction( i18n(
"Text Color..." ),
"colorize", 0,
01221
this, SLOT( slotTextColor() ),
01222 actionCollection(),
"format_color");
01223
01224
01225 createGUI(
"kmcomposerui.rc");
01226 }
01227
01228
01229
void KMComposeWin::setupStatusBar(
void)
01230 {
01231 statusBar()->insertItem(
"", 0, 1);
01232 statusBar()->setItemAlignment(0, AlignLeft | AlignVCenter);
01233
01234 statusBar()->insertItem(i18n(
" Column: %1 ").arg(
" "),2,0,
true);
01235 statusBar()->insertItem(i18n(
" Line: %1 ").arg(
" "),1,0,
true);
01236 }
01237
01238
01239
01240
void KMComposeWin::updateCursorPosition()
01241 {
01242
int col,line;
01243
QString temp;
01244 line = mEditor->currentLine();
01245 col = mEditor->currentColumn();
01246 temp = i18n(
" Line: %1 ").arg(line+1);
01247 statusBar()->changeItem(temp,1);
01248 temp = i18n(
" Column: %1 ").arg(col+1);
01249 statusBar()->changeItem(temp,2);
01250 }
01251
01252
01253
01254
void KMComposeWin::setupEditor(
void)
01255 {
01256
01257 mEditor->setModified(FALSE);
01258
QFontMetrics fm(mBodyFont);
01259 mEditor->setTabStopWidth(fm.width(
QChar(
' ')) * 8);
01260
01261
01262
if (mWordWrap)
01263 {
01264 mEditor->setWordWrap( QMultiLineEdit::FixedColumnWidth );
01265 mEditor->setWrapColumnOrWidth(mLineBreak);
01266 }
01267
else
01268 {
01269 mEditor->setWordWrap( QMultiLineEdit::NoWrap );
01270 }
01271
01272
01273 slotUpdateFont();
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 updateCursorPosition();
01297 connect(mEditor,SIGNAL(CursorPositionChanged()),SLOT(updateCursorPosition()));
01298 connect( mEditor, SIGNAL( currentFontChanged(
const QFont & ) ),
01299
this, SLOT( fontChanged(
const QFont & ) ) );
01300 connect( mEditor, SIGNAL( currentAlignmentChanged(
int ) ),
01301
this, SLOT( alignmentChanged(
int ) ) );
01302
01303 }
01304
01305
01306
01307
static QString cleanedUpHeaderString(
const QString & s )
01308 {
01309
01310
QString res( s );
01311 res.replace(
'\r',
"" );
01312 res.replace(
'\n',
" " );
01313
return res.stripWhiteSpace();
01314 }
01315
01316
01317
QString KMComposeWin::subject()
const
01318
{
01319
return cleanedUpHeaderString( mEdtSubject->text() );
01320 }
01321
01322
01323
QString KMComposeWin::to()
const
01324
{
01325
return cleanedUpHeaderString( mEdtTo->text() );
01326 }
01327
01328
01329
QString KMComposeWin::cc()
const
01330
{
01331
if ( mEdtCc->isHidden() )
01332
return QString::null;
01333
else
01334
return cleanedUpHeaderString( mEdtCc->text() );
01335 }
01336
01337
01338
QString KMComposeWin::bcc()
const
01339
{
01340
if ( mEdtBcc->isHidden() )
01341
return QString::null;
01342
else
01343
return cleanedUpHeaderString( mEdtBcc->text() );
01344 }
01345
01346
01347
QString KMComposeWin::from()
const
01348
{
01349
return cleanedUpHeaderString( mEdtFrom->text() );
01350 }
01351
01352
01353
QString KMComposeWin::replyTo()
const
01354
{
01355
return cleanedUpHeaderString( mEdtReplyTo->text() );
01356 }
01357
01358
01359
void KMComposeWin::verifyWordWrapLengthIsAdequate(
const QString &body)
01360 {
01361
int maxLineLength = 0;
01362
int curPos;
01363
int oldPos = 0;
01364
if (mEditor->QMultiLineEdit::wordWrap() == QMultiLineEdit::FixedColumnWidth) {
01365
for (curPos = 0; curPos < (
int)body.length(); ++curPos)
01366
if (body[curPos] ==
'\n') {
01367
if ((curPos - oldPos) > maxLineLength)
01368 maxLineLength = curPos - oldPos;
01369 oldPos = curPos;
01370 }
01371
if ((curPos - oldPos) > maxLineLength)
01372 maxLineLength = curPos - oldPos;
01373
if (mEditor->wrapColumnOrWidth() < maxLineLength)
01374 mEditor->setWrapColumnOrWidth(maxLineLength);
01375 }
01376 }
01377
01378
01379
void KMComposeWin::decryptOrStripOffCleartextSignature(
QCString& body )
01380 {
01381
QPtrList<Kpgp::Block> pgpBlocks;
01382
QStrList nonPgpBlocks;
01383
if( Kpgp::Module::prepareMessageForDecryption( body,
01384 pgpBlocks, nonPgpBlocks ) )
01385 {
01386
01387
01388
if( pgpBlocks.count() == 1 )
01389 {
01390 Kpgp::Block* block = pgpBlocks.first();
01391
if( ( block->type() == Kpgp::PgpMessageBlock ) ||
01392 ( block->type() == Kpgp::ClearsignedBlock ) )
01393 {
01394
if( block->type() == Kpgp::PgpMessageBlock )
01395
01396 block->decrypt();
01397
else
01398
01399 block->verify();
01400
01401 body = nonPgpBlocks.first()
01402 + block->text()
01403 + nonPgpBlocks.last();
01404 }
01405 }
01406 }
01407 }
01408
01409
01410
void KMComposeWin::setMsg(KMMessage* newMsg,
bool mayAutoSign,
01411
bool allowDecryption,
bool isModified)
01412 {
01413
01414
if(!newMsg)
01415 {
01416 kdDebug(5006) <<
"KMComposeWin::setMsg() : newMsg == 0!" << endl;
01417
return;
01418 }
01419 mMsg = newMsg;
01420
01421 mEdtTo->setText(mMsg->to());
01422 mEdtFrom->setText(mMsg->from());
01423 mEdtCc->setText(mMsg->cc());
01424 mEdtSubject->setText(mMsg->subject());
01425 mEdtReplyTo->setText(mMsg->replyTo());
01426 mEdtBcc->setText(mMsg->bcc());
01427
01428
if (!mBtnIdentity->isChecked() && !newMsg->headerField(
"X-KMail-Identity").isEmpty())
01429 mId = newMsg->headerField(
"X-KMail-Identity").stripWhiteSpace().toUInt();
01430
01431
01432
01433
if ( !mBtnIdentity->isChecked() ) {
01434 disconnect(mIdentity,SIGNAL(identityChanged(uint)),
01435
this, SLOT(slotIdentityChanged(uint)));
01436 }
01437 mIdentity->setCurrentIdentity( mId );
01438
if ( !mBtnIdentity->isChecked() ) {
01439 connect(mIdentity,SIGNAL(identityChanged(uint)),
01440
this, SLOT(slotIdentityChanged(uint)));
01441 }
01442
else {
01443
01444
01445
01446 slotIdentityChanged( mId );
01447 }
01448
01449 KPIM::IdentityManager * im = kmkernel->identityManager();
01450
01451
const KPIM::Identity & ident = im->identityForUoid( mIdentity->currentIdentity() );
01452
01453 mOldSigText = ident.signatureText();
01454
01455
01456
01457
QString mdnAddr = newMsg->headerField(
"Disposition-Notification-To");
01458 mRequestMDNAction->setChecked( ( !mdnAddr.isEmpty() &&
01459 im->thatIsMe( mdnAddr ) ) || mAutoRequestMDN );
01460
01461
01462 mUrgentAction->setChecked( newMsg->isUrgent() );
01463
01464
01465
switch ( mMsg->encryptionState() ) {
01466
case KMMsgFullyEncrypted:
01467
case KMMsgPartiallyEncrypted:
01468 mLastEncryptActionState =
true;
01469
break;
01470
case KMMsgNotEncrypted:
01471 mLastEncryptActionState =
false;
01472
break;
01473
default:
01474
break;
01475 }
01476
01477
01478
switch ( mMsg->signatureState() ) {
01479
case KMMsgFullySigned:
01480
case KMMsgPartiallySigned:
01481 mLastSignActionState =
true;
01482
break;
01483
case KMMsgNotSigned:
01484 mLastSignActionState =
false;
01485
break;
01486
default:
01487
break;
01488 }
01489
01490 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
01491 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
01492
01493
if ( Kleo::CryptoBackendFactory::instance()->openpgp() || Kleo::CryptoBackendFactory::instance()->smime() ) {
01494
const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
01495 && !ident.pgpSigningKey().isEmpty();
01496
const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
01497 && !ident.smimeSigningKey().isEmpty();
01498
01499 setEncryption( mLastEncryptActionState );
01500 setSigning( ( canOpenPGPSign || canSMIMESign ) && mLastSignActionState );
01501 }
01502
01503
01504
01505 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
01506 !ident.pgpEncryptionKey().isEmpty() );
01507
01508
QString transport = newMsg->headerField(
"X-KMail-Transport");
01509
if (!mBtnTransport->isChecked() && !transport.isEmpty())
01510 {
01511
for (
int i = 0; i < mTransport->count(); i++)
01512
if (mTransport->text(i) == transport)
01513 mTransport->setCurrentItem(i);
01514 mTransport->setEditText( transport );
01515 }
01516
01517
if (!mBtnFcc->isChecked())
01518 {
01519
if (!mMsg->fcc().isEmpty())
01520 setFcc(mMsg->fcc());
01521
else
01522 setFcc(ident.fcc());
01523 }
01524
01525 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
01526
01527 partNode * root = partNode::fromMessage( mMsg );
01528
01529 KMail::ObjectTreeParser otp;
01530 otp.parseObjectTree( root );
01531
01532 KMail::AttachmentCollector ac;
01533 ac.setDiveIntoEncryptions(
true );
01534 ac.setDiveIntoSignatures(
true );
01535 ac.setDiveIntoMessages(
false );
01536
01537 ac.collectAttachmentsFrom( root );
01538
01539
for ( std::vector<partNode*>::const_iterator it = ac.attachments().begin() ; it != ac.attachments().end() ; ++it )
01540 addAttach(
new KMMessagePart( (*it)->msgPart() ) );
01541
01542 kdDebug(5006) << endl << endl <<
"TEXTUAL CONTENT: " << endl << otp.textualContent() << endl;
01543 mEditor->setText( otp.textualContent() );
01544
01545 mCharset = otp.textualContentCharset();
01546
if ( mCharset.isEmpty() )
01547 mCharset = mMsg->charset();
01548
if ( mCharset.isEmpty() )
01549 mCharset = mDefCharset;
01550 setCharset( mCharset );
01551
01552
if ( partNode * n = root->findType( DwMime::kTypeText, DwMime::kSubtypeHtml ) )
01553
if ( partNode * p = n->parentNode() )
01554
if ( p->hasType( DwMime::kTypeMultipart ) &&
01555 p->hasSubType( DwMime::kSubtypeAlternative ) )
01556
if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" )
01557 toggleMarkup(
true );
01558
01559
01560
if ( mMsg->numBodyParts() == 0 ) {
01561 mCharset=mMsg->charset();
01562
if ( mCharset.isEmpty() || mCharset ==
"default" )
01563 mCharset = mDefCharset;
01564
01565
QCString bodyDecoded = mMsg->bodyDecoded();
01566
01567
if( allowDecryption )
01568 decryptOrStripOffCleartextSignature( bodyDecoded );
01569
01570
const QTextCodec *codec = KMMsgBase::codecForName(mCharset);
01571
if (codec) {
01572 mEditor->setText(codec->toUnicode(bodyDecoded));
01573 }
else
01574 mEditor->setText(QString::fromLocal8Bit(bodyDecoded));
01575 }
01576
01577
01578
#ifdef BROKEN_FOR_OPAQUE_SIGNED_OR_ENCRYPTED_MAILS
01579
const int num = mMsg->numBodyParts();
01580 kdDebug(5006) <<
"KMComposeWin::setMsg() mMsg->numBodyParts="
01581 << mMsg->numBodyParts() << endl;
01582
01583
if ( num > 0 ) {
01584 KMMessagePart bodyPart;
01585
int firstAttachment = 0;
01586
01587 mMsg->bodyPart(1, &bodyPart);
01588
if ( bodyPart.typeStr().lower() ==
"text" &&
01589 bodyPart.subtypeStr().lower() ==
"html" ) {
01590
01591 partNode *root = partNode::fromMessage( mMsg );
01592 partNode *node = root->findType( DwMime::kTypeText,
01593 DwMime::kSubtypeHtml );
01594
if ( node && node->parentNode() &&
01595 node->parentNode()->hasType( DwMime::kTypeMultipart ) &&
01596 node->parentNode()->hasSubType( DwMime::kSubtypeAlternative ) ) {
01597
01598 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/html found" << endl;
01599 firstAttachment = 2;
01600
if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" )
01601 toggleMarkup(
true );
01602 }
01603
delete root; root = 0;
01604 }
01605
if ( firstAttachment == 0 ) {
01606 mMsg->bodyPart(0, &bodyPart);
01607
if ( bodyPart.typeStr().lower() ==
"text" ) {
01608
01609 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/* found" << endl;
01610 firstAttachment = 1;
01611 }
01612 }
01613
01614
if ( firstAttachment != 0 )
01615 {
01616 mCharset = bodyPart.charset();
01617
if ( mCharset.isEmpty() || mCharset ==
"default" )
01618 mCharset = mDefCharset;
01619
01620
QCString bodyDecoded = bodyPart.bodyDecoded();
01621
01622
if( allowDecryption )
01623 decryptOrStripOffCleartextSignature( bodyDecoded );
01624
01625
01626
01627
01628
01629
01630
01631
const QTextCodec *codec = KMMsgBase::codecForName(mCharset);
01632
if (codec)
01633 mEditor->setText(codec->toUnicode(bodyDecoded));
01634
else
01635 mEditor->setText(QString::fromLocal8Bit(bodyDecoded));
01636
01637 }
else mEditor->setText(
"");
01638
for(
int i = firstAttachment; i < num; ++i )
01639 {
01640 KMMessagePart *msgPart =
new KMMessagePart;
01641 mMsg->bodyPart(i, msgPart);
01642
QCString mimeType = msgPart->typeStr().lower() +
'/'
01643 + msgPart->subtypeStr().lower();
01644
01645
01646
if( mimeType !=
"application/pgp-signature" ) {
01647 addAttach(msgPart);
01648 }
01649 }
01650 }
else{
01651 mCharset=mMsg->charset();
01652
if ( mCharset.isEmpty() || mCharset ==
"default" )
01653 mCharset = mDefCharset;
01654
01655
QCString bodyDecoded = mMsg->bodyDecoded();
01656
01657
if( allowDecryption )
01658 decryptOrStripOffCleartextSignature( bodyDecoded );
01659
01660
const QTextCodec *codec = KMMsgBase::codecForName(mCharset);
01661
if (codec) {
01662 mEditor->setText(codec->toUnicode(bodyDecoded));
01663 }
else
01664 mEditor->setText(QString::fromLocal8Bit(bodyDecoded));
01665 }
01666
01667 setCharset(mCharset);
01668
#endif // BROKEN_FOR_OPAQUE_SIGNED_OR_ENCRYPTED_MAILS
01669
01670
if( mAutoSign && mayAutoSign ) {
01671
01672
01673
01674
01675
01676
01677 QTimer::singleShot( 0,
this, SLOT(slotAppendSignature()) );
01678 }
01679 mEditor->setModified(isModified);
01680 }
01681
01682
01683
01684
void KMComposeWin::setFcc(
const QString &idString )
01685 {
01686
01687
KMFolder *folder = kmkernel->findFolderById( idString );
01688
if ( folder )
01689 mFcc->setFolder( idString );
01690
else
01691 mFcc->setFolder( kmkernel->sentFolder() );
01692 }
01693
01694
01695
01696
bool KMComposeWin::queryClose ()
01697 {
01698
if ( !mEditor->checkExternalEditorFinished() )
01699
return false;
01700
if (kmkernel->shuttingDown() || kapp->sessionSaving())
01701
return true;
01702
01703
if(mEditor->isModified() || mEdtFrom->edited() || mEdtReplyTo->edited() ||
01704 mEdtTo->edited() || mEdtCc->edited() || mEdtBcc->edited() ||
01705 mEdtSubject->edited() || mAtmModified ||
01706 (mTransport->lineEdit() && mTransport->lineEdit()->edited()))
01707 {
01708
const int rc = KMessageBox::warningYesNoCancel(
this,
01709 i18n(
"Do you want to save the message for later or discard it?"),
01710 i18n(
"Close Composer"),
01711 i18n(
"&Save as Draft"),
01712 KStdGuiItem::discard() );
01713
if (rc == KMessageBox::Cancel)
01714
return false;
01715
else if (rc == KMessageBox::Yes) {
01716
01717 slotSaveDraft();
01718
return false;
01719 }
01720 }
01721
return true;
01722 }
01723
01724
01725
bool KMComposeWin::userForgotAttachment()
01726 {
01727 KConfigGroup composer( KMKernel::config(),
"Composer" );
01728
bool checkForForgottenAttachments =
01729 composer.readBoolEntry(
"showForgottenAttachmentWarning",
false );
01730
01731
if ( !checkForForgottenAttachments || ( mAtmList.count() > 0 ) )
01732
return false;
01733
01734
01735
QStringList attachWordsList =
01736 composer.readListEntry(
"attachment-keywords" );
01737
01738
if ( attachWordsList.isEmpty() ) {
01739
01740 attachWordsList << QString::fromLatin1(
"attachment")
01741 << QString::fromLatin1(
"attached");
01742
if ( QString::fromLatin1(
"attachment") != i18n(
"attachment") )
01743 attachWordsList << i18n(
"attachment");
01744
if ( QString::fromLatin1(
"attached") != i18n(
"attached") )
01745 attachWordsList << i18n(
"attached");
01746 }
01747
01748
QRegExp rx ( QString::fromLatin1(
"\\b") +
01749 attachWordsList.join(
"\\b|\\b") +
01750 QString::fromLatin1(
"\\b") );
01751 rx.setCaseSensitive(
false );
01752
01753
bool gotMatch =
false;
01754
01755
01756
01757
QString subj = subject();
01758 gotMatch = ( KMMessage::stripOffPrefixes( subj ) == subj )
01759 && ( rx.search( subj ) >= 0 );
01760
01761
if ( !gotMatch ) {
01762
01763
01764
QRegExp quotationRx (
"^([ \\t]*([|>:}#]|[A-Za-z]+>))+");
01765
for (
int i = 0; i < mEditor->numLines(); ++i ) {
01766
QString line = mEditor->textLine( i );
01767 gotMatch = ( quotationRx.search( line ) < 0 )
01768 && ( rx.search( line ) >= 0 );
01769
if ( gotMatch )
01770
break;
01771 }
01772 }
01773
01774
if ( !gotMatch )
01775
return false;
01776
01777
int rc = KMessageBox::warningYesNoCancel(
this,
01778 i18n(
"The message you have composed seems to refer to an "
01779
"attached file but you have not attached anything.\n"
01780
"Do you want to attach a file to your message?"),
01781 i18n(
"File Attachment Reminder"),
01782 i18n(
"&Attach File..."),
01783 i18n(
"&Send as Is") );
01784
if ( rc == KMessageBox::Cancel )
01785
return true;
01786
if ( rc == KMessageBox::Yes ) {
01787 slotAttachFile();
01788
01789
return true;
01790 }
01791
return false;
01792 }
01793
01794
01795
void KMComposeWin::applyChanges(
bool dontSignNorEncrypt,
bool dontDisable )
01796 {
01797
#ifdef DEBUG
01798
kdDebug(5006) <<
"entering KMComposeWin::applyChanges" << endl;
01799
#endif
01800
01801
if(!mMsg) {
01802 kdDebug(5006) <<
"KMComposeWin::applyChanges() : mMsg == 0!\n" << endl;
01803 emit applyChangesDone(
false );
01804
return;
01805 }
01806
01807
if( mComposer ) {
01808 kdDebug(5006) <<
"KMComposeWin::applyChanges() : applyChanges called twice"
01809 << endl;
01810
return;
01811 }
01812
01813
01814 mComposer =
new MessageComposer(
this );
01815 connect( mComposer, SIGNAL( done(
bool ) ),
01816
this, SLOT( slotComposerDone(
bool ) ) );
01817
01818
01819
if ( !dontDisable )
01820 setEnabled(
false );
01821
01822 mComposer->setDisableBreaking( mDisableBreaking );
01823 mComposer->applyChanges( dontSignNorEncrypt );
01824 }
01825
01826
void KMComposeWin::slotComposerDone(
bool rc )
01827 {
01828 std::for_each( mComposedMessages.begin(), mComposedMessages.end(), Delete<KMMessage> );
01829 mComposedMessages = mComposer->composedMessageList();
01830 emit applyChangesDone( rc );
01831
delete mComposer;
01832 mComposer = 0;
01833 }
01834
01835
const KPIM::Identity & KMComposeWin::identity()
const {
01836
return kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
01837 }
01838
01839 Kleo::CryptoMessageFormat KMComposeWin::cryptoMessageFormat()
const {
01840
if ( !mCryptoModuleAction )
01841
return Kleo::AutoFormat;
01842
return cb2format( mCryptoModuleAction->currentItem() );
01843 }
01844
01845
bool KMComposeWin::encryptToSelf()
const {
01846
return !Kpgp::Module::getKpgp() || Kpgp::Module::getKpgp()->encryptToSelf();
01847 }
01848
01849
bool KMComposeWin::queryExit ()
01850 {
01851
return true;
01852 }
01853
01854
01855
void KMComposeWin::addAttach(
const KURL aUrl)
01856 {
01857
if ( !aUrl.isValid() ) {
01858 KMessageBox::sorry(
this, i18n(
"<qt><p>KMail could not recognize the location of the attachment (%1);</p>"
01859
"<p>you have to specify the full path if you wish to attach a file.</p></qt>" )
01860 .arg( aUrl.prettyURL() ) );
01861
return;
01862 }
01863 KIO::TransferJob *job = KIO::get(aUrl);
01864 KIO::Scheduler::scheduleJob( job );
01865 atmLoadData ld;
01866 ld.url = aUrl;
01867 ld.data =
QByteArray();
01868 ld.insert =
false;
01869
if( !aUrl.fileEncoding().isEmpty() )
01870 ld.encoding = aUrl.fileEncoding().latin1();
01871
01872 mMapAtmLoadData.insert(job, ld);
01873 connect(job, SIGNAL(result(KIO::Job *)),
01874
this, SLOT(slotAttachFileResult(KIO::Job *)));
01875 connect(job, SIGNAL(data(KIO::Job *,
const QByteArray &)),
01876
this, SLOT(slotAttachFileData(KIO::Job *,
const QByteArray &)));
01877 }
01878
01879
01880
01881
void KMComposeWin::addAttach(
const KMMessagePart* msgPart)
01882 {
01883 mAtmList.append(msgPart);
01884
01885
01886
if (mAtmList.count()==1)
01887 {
01888 mGrid->setRowStretch(mNumHeaders+1, 50);
01889 mAtmListView->setMinimumSize(100, 80);
01890 mAtmListView->setMaximumHeight( 100 );
01891 mAtmListView->show();
01892 resize(size());
01893 }
01894
01895
01896 KMAtmListViewItem *lvi =
new KMAtmListViewItem( mAtmListView );
01897 msgPartToItem(msgPart, lvi);
01898 mAtmItemList.append(lvi);
01899
01900 slotUpdateAttachActions();
01901 }
01902
01903
01904
01905
void KMComposeWin::slotUpdateAttachActions()
01906 {
01907
int selectedCount = 0;
01908
for (
QPtrListIterator<QListViewItem> it(mAtmItemList); *it; ++it ) {
01909
if ( (*it)->isSelected() ) {
01910 ++selectedCount;
01911 }
01912 }
01913
01914 mAttachRemoveAction->setEnabled( selectedCount >= 1 );
01915 mAttachSaveAction->setEnabled( selectedCount == 1 );
01916 mAttachPropertiesAction->setEnabled( selectedCount == 1 );
01917 }
01918
01919
01920
01921
01922
QString KMComposeWin::prettyMimeType(
const QString& type )
01923 {
01924
QString t = type.lower();
01925 KServiceType::Ptr st = KServiceType::serviceType( t );
01926
return st ? st->comment() : t;
01927 }
01928
01929
void KMComposeWin::msgPartToItem(
const KMMessagePart* msgPart,
01930 KMAtmListViewItem *lvi)
01931 {
01932 assert(msgPart != 0);
01933
01934
if (!msgPart->fileName().isEmpty())
01935 lvi->setText(0, msgPart->fileName());
01936
else
01937 lvi->setText(0, msgPart->name());
01938 lvi->setText(1, KIO::convertSize( msgPart->decodedSize()));
01939 lvi->setText(2, msgPart->contentTransferEncodingStr());
01940 lvi->setText(3, prettyMimeType(msgPart->typeStr() +
"/" + msgPart->subtypeStr()));
01941
if( canSignEncryptAttachments() ) {
01942 lvi->enableCryptoCBs(
true );
01943 lvi->setEncrypt( mEncryptAction->isChecked() );
01944 lvi->setSign( mSignAction->isChecked() );
01945 }
else {
01946 lvi->enableCryptoCBs(
false );
01947 }
01948 }
01949
01950
01951
01952
void KMComposeWin::removeAttach(
const QString &aUrl)
01953 {
01954
int idx;
01955 KMMessagePart* msgPart;
01956
for(idx=0,msgPart=mAtmList.first(); msgPart;
01957 msgPart=mAtmList.next(),idx++) {
01958
if (msgPart->name() == aUrl) {
01959 removeAttach(idx);
01960
return;
01961 }
01962 }
01963 }
01964
01965
01966
01967
void KMComposeWin::removeAttach(
int idx)
01968 {
01969 mAtmModified = TRUE;
01970 mAtmList.remove(idx);
01971
delete mAtmItemList.take(idx);
01972
01973
if( mAtmList.isEmpty() )
01974 {
01975 mAtmListView->hide();
01976 mGrid->setRowStretch(mNumHeaders+1, 0);
01977 mAtmListView->setMinimumSize(0, 0);
01978 resize(size());
01979 }
01980 }
01981
01982
01983
01984
bool KMComposeWin::encryptFlagOfAttachment(
int idx)
01985 {
01986
return (
int)(mAtmItemList.count()) > idx
01987 ? ((KMAtmListViewItem*)(mAtmItemList.at( idx )))->isEncrypt()
01988 : false;
01989 }
01990
01991
01992
01993
bool KMComposeWin::signFlagOfAttachment(
int idx)
01994 {
01995
return (
int)(mAtmItemList.count()) > idx
01996 ? ((KMAtmListViewItem*)(mAtmItemList.at( idx )))->isSign()
01997 : false;
01998 }
01999
02000
02001
02002
void KMComposeWin::addrBookSelInto()
02003 {
02004 AddressesDialog dlg(
this );
02005
QString txt;
02006
QStringList lst;
02007
02008 txt = to();
02009
if ( !txt.isEmpty() ) {
02010 lst = KPIM::splitEmailAddrList( txt );
02011 dlg.setSelectedTo( lst );
02012 }
02013
02014 txt = cc();
02015
if ( !txt.isEmpty() ) {
02016 lst = KPIM::splitEmailAddrList( txt );
02017 dlg.setSelectedCC( lst );
02018 }
02019
02020 txt = bcc();
02021
if ( !txt.isEmpty() ) {
02022 lst = KPIM::splitEmailAddrList( txt );
02023 dlg.setSelectedBCC( lst );
02024 }
02025
02026 dlg.setRecentAddresses( RecentAddresses::self( KMKernel::config() )->kabcAddresses() );
02027
02028
if (dlg.exec()==QDialog::Rejected)
return;
02029
02030 mEdtTo->setText( dlg.to().join(
", ") );
02031 mEdtTo->setEdited(
true );
02032
02033 mEdtCc->setText( dlg.cc().join(
", ") );
02034 mEdtCc->setEdited(
true );
02035
02036 mEdtBcc->setText( dlg.bcc().join(
", ") );
02037 mEdtBcc->setEdited(
true );
02038 }
02039
02040
02041
02042
void KMComposeWin::setCharset(
const QCString& aCharset,
bool forceDefault)
02043 {
02044
if ((forceDefault && mForceReplyCharset) || aCharset.isEmpty())
02045 mCharset = mDefCharset;
02046
else
02047 mCharset = aCharset.lower();
02048
02049
if ( mCharset.isEmpty() || mCharset ==
"default" )
02050 mCharset = mDefCharset;
02051
02052
if (mAutoCharset)
02053 {
02054 mEncodingAction->setCurrentItem( 0 );
02055
return;
02056 }
02057
02058
QStringList encodings = mEncodingAction->items();
02059
int i = 0;
02060
bool charsetFound = FALSE;
02061
for ( QStringList::Iterator it = encodings.begin(); it != encodings.end();
02062 ++it, i++ )
02063 {
02064
if (i > 0 && ((mCharset ==
"us-ascii" && i == 1) ||
02065 (i != 1 && KGlobal::charsets()->codecForName(
02066 KGlobal::charsets()->encodingForName(*it))
02067 == KGlobal::charsets()->codecForName(mCharset))))
02068 {
02069 mEncodingAction->setCurrentItem( i );
02070 slotSetCharset();
02071 charsetFound = TRUE;
02072
break;
02073 }
02074 }
02075
if (!aCharset.isEmpty() && !charsetFound) setCharset(
"", TRUE);
02076 }
02077
02078
02079
02080
void KMComposeWin::slotAddrBook()
02081 {
02082 KAddrBookExternal::openAddressBook(
this);
02083 }
02084
02085
02086
02087
void KMComposeWin::slotAddrBookFrom()
02088 {
02089 addrBookSelInto();
02090 }
02091
02092
02093
02094
void KMComposeWin::slotAddrBookReplyTo()
02095 {
02096 addrBookSelInto();
02097 }
02098
02099
02100
02101
void KMComposeWin::slotAddrBookTo()
02102 {
02103 addrBookSelInto();
02104 }
02105
02106
02107
void KMComposeWin::slotAttachFile()
02108 {
02109
02110
02111
02112
02113 KFileDialog fdlg(QString::null, QString::null,
this, 0, TRUE);
02114 fdlg.setOperationMode( KFileDialog::Other );
02115 fdlg.setCaption(i18n(
"Attach File"));
02116 fdlg.okButton()->setGuiItem(KGuiItem(i18n(
"&Attach"),
"fileopen"));
02117 fdlg.setMode(KFile::Files);
02118 fdlg.exec();
02119 KURL::List files = fdlg.selectedURLs();
02120
02121
for (KURL::List::Iterator it = files.begin(); it != files.end(); ++it)
02122 addAttach(*it);
02123 }
02124
02125
02126
02127
void KMComposeWin::slotAttachFileData(KIO::Job *job,
const QByteArray &data)
02128 {
02129
QMap<KIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
02130 assert(it != mMapAtmLoadData.end());
02131
QBuffer buff((*it).data);
02132 buff.open(IO_WriteOnly | IO_Append);
02133 buff.writeBlock(data.data(), data.size());
02134 buff.close();
02135 }
02136
02137
02138
02139
void KMComposeWin::slotAttachFileResult(KIO::Job *job)
02140 {
02141
QMap<KIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
02142 assert(it != mMapAtmLoadData.end());
02143
if (job->error())
02144 {
02145 mMapAtmLoadData.remove(it);
02146 job->showErrorDialog();
02147
return;
02148 }
02149
if ((*it).insert)
02150 {
02151 (*it).data.resize((*it).data.size() + 1);
02152 (*it).data[(*it).data.size() - 1] =
'\0';
02153
if (
const QTextCodec * codec = KGlobal::charsets()->codecForName((*it).encoding) )
02154 mEditor->insert( codec->toUnicode( (*it).data ) );
02155
else
02156 mEditor->insert( QString::fromLocal8Bit( (*it).data ) );
02157 mMapAtmLoadData.remove(it);
02158
return;
02159 }
02160
QString name;
02161
const QString urlStr = (*it).url.prettyURL();
02162
const QCString partCharset = (*it).url.fileEncoding().isEmpty()
02163 ? mCharset
02164 :
QCString((*it).url.fileEncoding().latin1());
02165
02166 KMMessagePart* msgPart;
02167
int i;
02168
02169
KCursorSaver busy(KBusyPtr::busy());
02170
02171
02172
QString mimeType = static_cast<KIO::MimetypeJob*>(job)->mimetype();
02173
02174 i = urlStr.findRev(
'/');
02175
if( i == -1 )
02176 name = urlStr;
02177
else if( i + 1 < int( urlStr.length() ) )
02178 name = urlStr.mid( i + 1, 256 );
02179
else {
02180
02181
02182
if( mimeType ==
"text/html" )
02183 name =
"index.html";
02184
else {
02185
02186
QStringList patterns( KMimeType::mimeType( mimeType )->patterns() );
02187
QString ext;
02188
if( !patterns.isEmpty() ) {
02189 ext = patterns[0];
02190
int i = ext.findRev(
'.' );
02191
if( i == -1 )
02192 ext.prepend(
'.' );
02193
else if( i > 0 )
02194 ext = ext.mid( i );
02195 }
02196 name =
QString(
"unknown") += ext;
02197 }
02198 }
02199
02200
QCString encoding = KMMsgBase::autoDetectCharset(partCharset,
02201 KMMessage::preferredCharsets(), name);
02202
if (encoding.isEmpty()) encoding =
"utf-8";
02203
02204
QCString encName;
02205
if ( mOutlookCompatible )
02206 encName = KMMsgBase::encodeRFC2047String( name, encoding );
02207
else
02208 encName = KMMsgBase::encodeRFC2231String( name, encoding );
02209
bool RFC2231encoded =
false;
02210
if ( !mOutlookCompatible )
02211 RFC2231encoded = name !=
QString( encName );
02212
02213
02214 msgPart =
new KMMessagePart;
02215 msgPart->setName(name);
02216
QValueList<int> allowedCTEs;
02217 msgPart->setBodyAndGuessCte((*it).data, allowedCTEs,
02218 !kmkernel->msgSender()->sendQuotedPrintable());
02219 kdDebug(5006) <<
"autodetected cte: " << msgPart->cteStr() << endl;
02220
int slash = mimeType.find(
'/' );
02221
if( slash == -1 )
02222 slash = mimeType.length();
02223 msgPart->setTypeStr( mimeType.left( slash ).latin1() );
02224 msgPart->setSubtypeStr( mimeType.mid( slash + 1 ).latin1() );
02225 msgPart->setContentDisposition(
QCString(
"attachment;\n\tfilename")
02226 + ((RFC2231encoded) ?
"*" :
"") +
"=\"" + encName +
"\"");
02227
02228 mMapAtmLoadData.remove(it);
02229
02230 msgPart->setCharset(partCharset);
02231
02232
02233 KConfigGroup composer(KMKernel::config(),
"Composer");
02234
if (!composer.hasKey(
"showMessagePartDialogOnAttach"))
02235
02236 composer.writeEntry(
"showMessagePartDialogOnAttach",
false);
02237
if (composer.readBoolEntry(
"showMessagePartDialogOnAttach",
false)) {
02238
KMMsgPartDialogCompat dlg;
02239
int encodings = 0;
02240
for (
QValueListConstIterator<int> it = allowedCTEs.begin() ;
02241 it != allowedCTEs.end() ; ++it )
02242
switch ( *it ) {
02243
case DwMime::kCteBase64: encodings |= KMMsgPartDialog::Base64;
break;
02244
case DwMime::kCteQp: encodings |= KMMsgPartDialog::QuotedPrintable;
break;
02245
case DwMime::kCte7bit: encodings |= KMMsgPartDialog::SevenBit;
break;
02246
case DwMime::kCte8bit: encodings |= KMMsgPartDialog::EightBit;
break;
02247
default: ;
02248 }
02249 dlg.
setShownEncodings( encodings );
02250 dlg.
setMsgPart(msgPart);
02251
if (!dlg.exec()) {
02252
delete msgPart;
02253 msgPart = 0;
02254
return;
02255 }
02256 }
02257 mAtmModified = TRUE;
02258
if (msgPart->typeStr().lower() !=
"text") msgPart->setCharset(
QCString());
02259
02260
02261 addAttach(msgPart);
02262 }
02263
02264
02265
02266
void KMComposeWin::slotInsertFile()
02267 {
02268 KFileDialog fdlg(QString::null, QString::null,
this, 0, TRUE);
02269 fdlg.setOperationMode( KFileDialog::Opening );
02270 fdlg.okButton()->setText(i18n(
"&Insert"));
02271 fdlg.setCaption(i18n(
"Insert File"));
02272 fdlg.toolBar()->insertCombo(KMMsgBase::supportedEncodings(FALSE), 4711,
02273
false, 0, 0, 0);
02274 KComboBox *combo = fdlg.toolBar()->getCombo(4711);
02275
for (
int i = 0; i < combo->count(); i++)
02276
if (KGlobal::charsets()->codecForName(KGlobal::charsets()->
02277 encodingForName(combo->text(i)))
02278 == QTextCodec::codecForLocale()) combo->setCurrentItem(i);
02279
if (!fdlg.exec())
return;
02280
02281 KURL u = fdlg.selectedURL();
02282
02283
if (u.fileName().isEmpty())
return;
02284
02285 KIO::Job *job = KIO::get(u);
02286 atmLoadData ld;
02287 ld.url = u;
02288 ld.data =
QByteArray();
02289 ld.insert =
true;
02290 ld.encoding = KGlobal::charsets()->encodingForName(
02291 combo->currentText()).latin1();
02292 mMapAtmLoadData.insert(job, ld);
02293 connect(job, SIGNAL(result(KIO::Job *)),
02294
this, SLOT(slotAttachFileResult(KIO::Job *)));
02295 connect(job, SIGNAL(data(KIO::Job *,
const QByteArray &)),
02296
this, SLOT(slotAttachFileData(KIO::Job *,
const QByteArray &)));
02297 }
02298
02299
02300
02301
void KMComposeWin::slotSetCharset()
02302 {
02303
if (mEncodingAction->currentItem() == 0)
02304 {
02305 mAutoCharset =
true;
02306
return;
02307 }
02308 mAutoCharset =
false;
02309
02310 mCharset = KGlobal::charsets()->encodingForName( mEncodingAction->
02311 currentText() ).latin1();
02312 }
02313
02314
02315
02316
void KMComposeWin::slotSelectCryptoModule()
02317 {
02318
if( canSignEncryptAttachments() ) {
02319
02320
if( 0 == mAtmListView->columnWidth( mAtmColEncrypt ) ) {
02321
02322
02323
if( !mAtmList.isEmpty() ) {
02324
for( KMAtmListViewItem* lvi = (KMAtmListViewItem*)mAtmItemList.first();
02325 lvi;
02326 lvi = (KMAtmListViewItem*)mAtmItemList.next() ) {
02327 lvi->setSign( mSignAction->isChecked() );
02328 lvi->setEncrypt( mEncryptAction->isChecked() );
02329 }
02330 }
02331
int totalWidth = 0;
02332
02333
for(
int col=0; col < mAtmColEncrypt; col++ )
02334 totalWidth += mAtmListView->columnWidth( col );
02335
int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
02336 - mAtmSignColWidth;
02337
02338
02339
int usedWidth = 0;
02340
for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
02341
int newWidth = mAtmListView->columnWidth( col ) * reducedTotalWidth
02342 / totalWidth;
02343 mAtmListView->setColumnWidth( col, newWidth );
02344 usedWidth += newWidth;
02345 }
02346
02347
02348
02349 mAtmListView->setColumnWidth( mAtmColEncrypt-1,
02350 reducedTotalWidth - usedWidth );
02351 mAtmListView->setColumnWidth( mAtmColEncrypt, mAtmEncryptColWidth );
02352 mAtmListView->setColumnWidth( mAtmColSign, mAtmSignColWidth );
02353
for( KMAtmListViewItem* lvi = (KMAtmListViewItem*)mAtmItemList.first();
02354 lvi;
02355 lvi = (KMAtmListViewItem*)mAtmItemList.next() ) {
02356 lvi->enableCryptoCBs(
true );
02357 }
02358 }
02359 }
else {
02360
02361
if( 0 != mAtmListView->columnWidth( mAtmColEncrypt ) ) {
02362 mAtmEncryptColWidth = mAtmListView->columnWidth( mAtmColEncrypt );
02363 mAtmSignColWidth = mAtmListView->columnWidth( mAtmColSign );
02364
int totalWidth = 0;
02365
02366
for(
int col=0; col < mAtmListView->columns(); col++ )
02367 totalWidth += mAtmListView->columnWidth( col );
02368
int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
02369 - mAtmSignColWidth;
02370
02371
02372
int usedWidth = 0;
02373
for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
02374
int newWidth = mAtmListView->columnWidth( col ) * totalWidth
02375 / reducedTotalWidth;
02376 mAtmListView->setColumnWidth( col, newWidth );
02377 usedWidth += newWidth;
02378 }
02379
02380
02381
02382 mAtmListView->setColumnWidth( mAtmColEncrypt-1, totalWidth - usedWidth );
02383 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
02384 mAtmListView->setColumnWidth( mAtmColSign, 0 );
02385
for( KMAtmListViewItem* lvi = (KMAtmListViewItem*)mAtmItemList.first();
02386 lvi;
02387 lvi = (KMAtmListViewItem*)mAtmItemList.next() ) {
02388 lvi->enableCryptoCBs(
false );
02389 }
02390 }
02391 }
02392 }
02393
02394
static void showExportError( QWidget * w,
const GpgME::Error & err ) {
02395 assert( err );
02396
const QString msg = i18n(
"<qt><p>An error occurred while trying to export "
02397
"the key from the backend:</p>"
02398
"<p><b>%1</b></p></qt>")
02399 .arg( QString::fromLocal8Bit( err.asString() ) );
02400 KMessageBox::error( w, msg, i18n(
"Key Export Failed") );
02401 }
02402
02403
02404
02405
void KMComposeWin::slotInsertMyPublicKey()
02406 {
02407
02408 mFingerprint =
02409 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() ).pgpEncryptionKey();
02410
if ( !mFingerprint.isEmpty() )
02411 startPublicKeyExport();
02412 }
02413
02414
void KMComposeWin::startPublicKeyExport() {
02415
if ( mFingerprint.isEmpty() )
02416
return;
02417 Kleo::ExportJob * job = Kleo::CryptoBackendFactory::instance()->openpgp()->publicKeyExportJob(
true );
02418 assert( job );
02419
02420 connect( job, SIGNAL(result(
const GpgME::Error&,
const QByteArray&)),
02421
this, SLOT(slotPublicKeyExportResult(
const GpgME::Error&,
const QByteArray&)) );
02422
02423
const GpgME::Error err = job->start( mFingerprint );
02424
if ( err )
02425 showExportError(
this, err );
02426
else
02427 (
void)
new Kleo::ProgressDialog( job, i18n(
"Exporting key..."),
this );
02428 }
02429
02430
void KMComposeWin::slotPublicKeyExportResult(
const GpgME::Error & err,
const QByteArray & keydata ) {
02431
if ( err ) {
02432 showExportError(
this, err );
02433
return;
02434 }
02435
02436
02437 KMMessagePart * msgPart =
new KMMessagePart();
02438 msgPart->setName( i18n(
"OpenPGP key 0x%1").arg( mFingerprint ) );
02439 msgPart->setTypeStr(
"application");
02440 msgPart->setSubtypeStr(
"pgp-keys");
02441
QValueList<int> dummy;
02442 msgPart->setBodyAndGuessCte(keydata, dummy,
false);
02443 msgPart->setContentDisposition(
"attachment;\n\tfilename=0x" +
QCString( mFingerprint.latin1() ) +
".asc" );
02444
02445
02446 addAttach(msgPart);
02447 rethinkFields();
02448 }
02449
02450
02451
void KMComposeWin::slotInsertPublicKey()
02452 {
02453 Kleo::KeySelectionDialog dlg( i18n(
"Attach Public OpenPGP Key"),
02454 i18n(
"Select the public key which should "
02455
"be attached."),
02456 std::vector<GpgME::Key>(),
02457 Kleo::KeySelectionDialog::PublicKeys|Kleo::KeySelectionDialog::OpenPGPKeys,
02458
false ,
02459
false ,
02460
this,
"attach public key selection dialog" );
02461
if ( dlg.exec() != QDialog::Accepted )
02462
return;
02463
02464 mFingerprint = dlg.fingerprint();
02465 startPublicKeyExport();
02466 }
02467
02468
02469
02470
void KMComposeWin::slotAttachPopupMenu(
QListViewItem *,
const QPoint &,
int)
02471 {
02472
if (!mAttachMenu)
02473 {
02474 mAttachMenu =
new QPopupMenu(
this);
02475
02476 mViewId = mAttachMenu->insertItem(i18n(
"to view",
"View"),
this,
02477 SLOT(slotAttachView()));
02478 mRemoveId = mAttachMenu->insertItem(i18n(
"Remove"),
this, SLOT(slotAttachRemove()));
02479 mSaveAsId = mAttachMenu->insertItem( SmallIcon(
"filesaveas"), i18n(
"Save As..."),
this,
02480 SLOT( slotAttachSave() ) );
02481 mPropertiesId = mAttachMenu->insertItem( i18n(
"Properties"),
this,
02482 SLOT( slotAttachProperties() ) );
02483 mAttachMenu->insertSeparator();
02484 mAttachMenu->insertItem(i18n(
"Add Attachment..."),
this, SLOT(slotAttachFile()));
02485 }
02486
02487
int selectedCount = 0;
02488
for (
QPtrListIterator<QListViewItem> it(mAtmItemList); *it; ++it ) {
02489
if ( (*it)->isSelected() ) {
02490 ++selectedCount;
02491 }
02492 }
02493
02494 mAttachMenu->setItemEnabled( mViewId, selectedCount > 0 );
02495 mAttachMenu->setItemEnabled( mRemoveId, selectedCount > 0 );
02496 mAttachMenu->setItemEnabled( mSaveAsId, selectedCount == 1 );
02497 mAttachMenu->setItemEnabled( mPropertiesId, selectedCount == 1 );
02498
02499 mAttachMenu->popup(QCursor::pos());
02500 }
02501
02502
02503
int KMComposeWin::currentAttachmentNum()
02504 {
02505
int i = 0;
02506
for (
QPtrListIterator<QListViewItem> it(mAtmItemList); *it; ++it, ++i )
02507
if ( *it == mAtmListView->currentItem() )
02508
return i;
02509
return -1;
02510 }
02511
02512
02513
void KMComposeWin::slotAttachProperties()
02514 {
02515
int idx = currentAttachmentNum();
02516
02517
if (idx < 0)
return;
02518
02519 KMMessagePart* msgPart = mAtmList.at(idx);
02520 msgPart->setCharset(mCharset);
02521
02522
KMMsgPartDialogCompat dlg;
02523 dlg.
setMsgPart(msgPart);
02524 KMAtmListViewItem* listItem = (KMAtmListViewItem*)(mAtmItemList.at(idx));
02525
if( canSignEncryptAttachments() && listItem ) {
02526 dlg.
setCanSign(
true );
02527 dlg.
setCanEncrypt(
true );
02528 dlg.
setSigned( listItem->isSign() );
02529 dlg.
setEncrypted( listItem->isEncrypt() );
02530 }
else {
02531 dlg.
setCanSign(
false );
02532 dlg.
setCanEncrypt(
false );
02533 }
02534
if (dlg.exec())
02535 {
02536 mAtmModified = TRUE;
02537
02538
if( listItem ) {
02539 msgPartToItem(msgPart, listItem);
02540
if( canSignEncryptAttachments() ) {
02541 listItem->setSign( dlg.
isSigned() );
02542 listItem->setEncrypt( dlg.
isEncrypted() );
02543 }
02544 }
02545 }
02546
if (msgPart->typeStr().lower() !=
"text") msgPart->setCharset(
QCString());
02547 }
02548
02549
02550
02551
void KMComposeWin::slotAttachView()
02552 {
02553
int i = 0;
02554
for (
QPtrListIterator<QListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
02555
if ( (*it)->isSelected() ) {
02556 viewAttach( i );
02557 }
02558 }
02559 }
02560
02561
bool KMComposeWin::inlineSigningEncryptionSelected() {
02562
if ( !mSignAction->isChecked() && !mEncryptAction->isChecked() )
02563
return false;
02564
return cryptoMessageFormat() == Kleo::InlineOpenPGPFormat;
02565 }
02566
02567
02568
void KMComposeWin::viewAttach(
int index )
02569 {
02570
QString str, pname;
02571 KMMessagePart* msgPart;
02572 msgPart = mAtmList.at(index);
02573 pname = msgPart->name().stripWhiteSpace();
02574
if (pname.isEmpty()) pname=msgPart->contentDescription();
02575
if (pname.isEmpty()) pname=
"unnamed";
02576
02577 KTempFile* atmTempFile =
new KTempFile();
02578 mAtmTempList.append( atmTempFile );
02579 atmTempFile->setAutoDelete(
true );
02580 KPIM::kByteArrayToFile(msgPart->bodyDecodedBinary(), atmTempFile->name(),
false,
false,
02581
false);
02582 KMReaderMainWin *win =
new KMReaderMainWin(msgPart,
false,
02583 atmTempFile->name(), pname, KMMsgBase::codecForName(mCharset) );
02584 win->show();
02585 }
02586
02587
02588
02589
void KMComposeWin::slotAttachSave()
02590 {
02591 KMMessagePart* msgPart;
02592
QString fileName, pname;
02593
int idx = currentAttachmentNum();
02594
02595
if (idx < 0)
return;
02596
02597 msgPart = mAtmList.at(idx);
02598 pname = msgPart->name();
02599
if (pname.isEmpty()) pname=
"unnamed";
02600
02601 KURL url = KFileDialog::getSaveURL(QString::null, QString::null, 0, i18n(
"Save Attachment As"));
02602
02603
if( url.isEmpty() )
02604
return;
02605
02606 kmkernel->byteArrayToRemoteFile(msgPart->bodyDecodedBinary(), url);
02607 }
02608
02609
02610
02611
void KMComposeWin::slotAttachRemove()
02612 {
02613
bool attachmentRemoved =
false;
02614
int i = 0;
02615
for (
QPtrListIterator<QListViewItem> it(mAtmItemList); *it; ) {
02616
if ( (*it)->isSelected() ) {
02617 removeAttach( i );
02618 attachmentRemoved =
true;
02619 }
02620
else {
02621 ++it;
02622 ++i;
02623 }
02624 }
02625
02626
if ( attachmentRemoved ) {
02627 mEditor->setModified(
true );
02628 slotUpdateAttachActions();
02629 }
02630 }
02631
02632
02633
void KMComposeWin::slotFind()
02634 {
02635 mEditor->search();
02636 }
02637
02638
void KMComposeWin::slotSearchAgain()
02639 {
02640 mEditor->repeatSearch();
02641 }
02642
02643
02644
void KMComposeWin::slotReplace()
02645 {
02646 mEditor->replace();
02647 }
02648
02649
02650
void KMComposeWin::slotUpdateFont()
02651 {
02652
if ( mFixedFontAction ) {
02653 mUseFixedFont = mFixedFontAction->isChecked();
02654 }
02655 mEditor->setFont( mUseFixedFont ? mFixedFont : mBodyFont );
02656 }
02657
02658
QString KMComposeWin::quotePrefixName()
const
02659
{
02660
if ( !msg() )
02661
return QString::null;
02662
02663 KConfig *config=KMKernel::config();
02664 KConfigGroupSaver saver(config,
"General");
02665
02666
int languageNr = config->readNumEntry(
"reply-current-language",0);
02667 config->setGroup(
QString(
"KMMessage #%1").arg(languageNr) );
02668
02669
QString quotePrefix = config->readEntry(
"indent-prefix",
">%_");
02670 quotePrefix = msg()->formatString(quotePrefix);
02671
return quotePrefix;
02672 }
02673
02674
void KMComposeWin::slotPasteAsQuotation()
02675 {
02676
if( mEditor->hasFocus() && msg() )
02677 {
02678
QString quotePrefix = quotePrefixName();
02679
QString s = QApplication::clipboard()->text();
02680
if (!s.isEmpty()) {
02681
for (
int i=0; (uint)i<s.length(); i++) {
02682
if ( s[i] <
' ' && s[i] !=
'\n' && s[i] !=
'\t' )
02683 s[i] =
' ';
02684 }
02685 s.prepend(quotePrefix);
02686 s.replace(
"\n",
"\n"+quotePrefix);
02687 mEditor->insert(s);
02688 }
02689 }
02690 }
02691
02692
02693
void KMComposeWin::slotAddQuotes()
02694 {
02695
if( mEditor->hasFocus() && msg() )
02696 {
02697
if ( mEditor->hasMarkedText()) {
02698
QString s = mEditor->markedText();
02699
QString quotePrefix = quotePrefixName();
02700 s.prepend(quotePrefix);
02701 s.replace(
"\n",
"\n"+quotePrefix);
02702 mEditor->insert(s);
02703 }
else {
02704
int l = mEditor->currentLine();
02705
int c = mEditor->currentColumn();
02706
QString s = mEditor->textLine(l);
02707 s.prepend(
"> ");
02708 mEditor->insertLine(s,l);
02709 mEditor->removeLine(l+1);
02710 mEditor->setCursorPosition(l,c+2);
02711 }
02712 }
02713 }
02714
02715
02716
void KMComposeWin::slotRemoveQuotes()
02717 {
02718
if( mEditor->hasFocus() && msg() )
02719 {
02720
QString quotePrefix = quotePrefixName();
02721
if (mEditor->hasMarkedText()) {
02722
QString s = mEditor->markedText();
02723
QString quotePrefix = quotePrefixName();
02724
if (s.left(2) == quotePrefix )
02725 s.remove(0,2);
02726 s.replace(
"\n"+quotePrefix,
"\n");
02727 mEditor->insert(s);
02728 }
else {
02729
int l = mEditor->currentLine();
02730
int c = mEditor->currentColumn();
02731
QString s = mEditor->textLine(l);
02732
if (s.left(2) == quotePrefix) {
02733 s.remove(0,2);
02734 mEditor->insertLine(s,l);
02735 mEditor->removeLine(l+1);
02736 mEditor->setCursorPosition(l,c-2);
02737 }
02738 }
02739 }
02740 }
02741
02742
02743
02744
void KMComposeWin::slotUndo()
02745 {
02746 QWidget* fw = focusWidget();
02747
if (!fw)
return;
02748
02749
if ( ::qt_cast<KEdit*>(fw) )
02750 static_cast<QMultiLineEdit*>(fw)->undo();
02751
else if (::qt_cast<QLineEdit*>(fw))
02752 static_cast<QLineEdit*>(fw)->undo();
02753 }
02754
02755
void KMComposeWin::slotRedo()
02756 {
02757 QWidget* fw = focusWidget();
02758
if (!fw)
return;
02759
02760
if (::qt_cast<KEdit*>(fw))
02761 static_cast<KEdit*>(fw)->redo();
02762
else if (::qt_cast<QLineEdit*>(fw))
02763 static_cast<QLineEdit*>(fw)->redo();
02764 }
02765
02766
02767
void KMComposeWin::slotCut()
02768 {
02769 QWidget* fw = focusWidget();
02770
if (!fw)
return;
02771
02772
if (::qt_cast<KEdit*>(fw))
02773 static_cast<KEdit*>(fw)->cut();
02774
else if (::qt_cast<QLineEdit*>(fw))
02775 static_cast<QLineEdit*>(fw)->cut();
02776 }
02777
02778
02779
02780
void KMComposeWin::slotCopy()
02781 {
02782 QWidget* fw = focusWidget();
02783
if (!fw)
return;
02784
02785
#ifdef KeyPress
02786
#undef KeyPress
02787
#endif
02788
02789
QKeyEvent k(QEvent::KeyPress, Key_C , 0 , ControlButton);
02790 kapp->notify(fw, &k);
02791 }
02792
02793
02794
02795
void KMComposeWin::slotPaste()
02796 {
02797 QWidget* fw = focusWidget();
02798
if (!fw)
return;
02799
02800
#ifdef KeyPress
02801
#undef KeyPress
02802
#endif
02803
02804
QKeyEvent k(QEvent::KeyPress, Key_V , 0 , ControlButton);
02805 kapp->notify(fw, &k);
02806 }
02807
02808
02809
02810
void KMComposeWin::slotMarkAll()
02811 {
02812 QWidget* fw = focusWidget();
02813
if (!fw)
return;
02814
02815
if (::qt_cast<QLineEdit*>(fw))
02816 static_cast<QLineEdit*>(fw)->selectAll();
02817
else if (::qt_cast<KEdit*>(fw))
02818 static_cast<KEdit*>(fw)->selectAll();
02819 }
02820
02821
02822
02823
void KMComposeWin::slotClose()
02824 {
02825 close(FALSE);
02826 }
02827
02828
02829
02830
void KMComposeWin::slotNewComposer()
02831 {
02832 KMComposeWin* win;
02833 KMMessage* msg =
new KMMessage;
02834
02835 msg->initHeader();
02836 win =
new KMComposeWin(msg);
02837 win->show();
02838 }
02839
02840
02841
02842
void KMComposeWin::slotNewMailReader()
02843 {
02844 KMMainWin *kmmwin =
new KMMainWin(0);
02845 kmmwin->show();
02846
02847 }
02848
02849
02850
02851
void KMComposeWin::slotUpdWinTitle(
const QString& text)
02852 {
02853
if (text.isEmpty())
02854 setCaption(
"("+i18n(
"unnamed")+
")");
02855
else setCaption(text);
02856 }
02857
02858
02859
02860
void KMComposeWin::slotEncryptToggled(
bool on)
02861 {
02862 setEncryption( on,
true );
02863 }
02864
02865
02866
02867
void KMComposeWin::setEncryption(
bool encrypt,
bool setByUser )
02868 {
02869
if ( !mEncryptAction->isEnabled() )
02870 encrypt =
false;
02871
02872
02873
else if ( encrypt && encryptToSelf() && !mLastIdentityHasEncryptionKey ) {
02874
if ( setByUser )
02875 KMessageBox::sorry(
this,
02876 i18n(
"<qt><p>You have requested that messages be "
02877
"encrypted to yourself, but the currently selected "
02878
"identity does not define an (OpenPGP or S/MIME) "
02879
"encryption key to use for this.</p>"
02880
"<p>Please select the key(s) to use "
02881
"in the identity configuration.</p>"
02882
"</qt>"),
02883 i18n(
"Undefined Encryption Key") );
02884 encrypt =
false;
02885 }
02886
02887
02888 mEncryptAction->setChecked( encrypt );
02889
02890
02891
if ( encrypt )
02892 mEncryptAction->setIcon(
"encrypted");
02893
else
02894 mEncryptAction->setIcon(
"decrypted");
02895
02896
02897
if ( canSignEncryptAttachments() ) {
02898
for ( KMAtmListViewItem* entry =
02899 static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
02900 entry;
02901 entry = static_cast<KMAtmListViewItem*>( mAtmItemList.next() ) )
02902 entry->setEncrypt( encrypt );
02903 }
02904 }
02905
02906
02907
02908
void KMComposeWin::slotSignToggled(
bool on)
02909 {
02910 setSigning( on,
true );
02911 }
02912
02913
02914
02915
void KMComposeWin::setSigning(
bool sign,
bool setByUser )
02916 {
02917
if ( !mSignAction->isEnabled() )
02918 sign =
false;
02919
02920
02921
if ( sign && !mLastIdentityHasSigningKey ) {
02922
if ( setByUser )
02923 KMessageBox::sorry(
this,
02924 i18n(
"<qt><p>In order to be able to sign "
02925
"this message you first have to "
02926
"define the (OpenPGP or S/MIME) signing key "
02927
"to use.</p>"
02928
"<p>Please select the key to use "
02929
"in the identity configuration.</p>"
02930
"</qt>"),
02931 i18n(
"Undefined Signing Key") );
02932 sign =
false;
02933 }
02934
02935
02936 mSignAction->setChecked( sign );
02937
02938
02939
if ( canSignEncryptAttachments() ) {
02940
for ( KMAtmListViewItem* entry =
02941 static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
02942 entry;
02943 entry = static_cast<KMAtmListViewItem*>( mAtmItemList.next() ) )
02944 entry->setSign( sign );
02945 }
02946 }
02947
02948
02949
02950
void KMComposeWin::slotWordWrapToggled(
bool on)
02951 {
02952
if (on)
02953 {
02954 mEditor->setWordWrap( QMultiLineEdit::FixedColumnWidth );
02955 mEditor->setWrapColumnOrWidth(mLineBreak);
02956 }
02957
else
02958 {
02959 mEditor->setWordWrap( QMultiLineEdit::NoWrap );
02960 }
02961 }
02962
02963
02964
02965
void KMComposeWin::slotPrint()
02966 {
02967 mMessageWasModified = ( mEditor->isModified() || mEdtFrom->edited() ||
02968 mEdtReplyTo->edited() || mEdtTo->edited() ||
02969 mEdtCc->edited() || mEdtBcc->edited() ||
02970 mEdtSubject->edited() || mAtmModified ||
02971 ( mTransport->lineEdit() &&
02972 mTransport->lineEdit()->edited() ) );
02973 connect(
this, SIGNAL( applyChangesDone(
bool ) ),
02974
this, SLOT( slotContinuePrint(
bool ) ) );
02975 applyChanges(
true );
02976 }
02977
02978
void KMComposeWin::slotContinuePrint(
bool rc )
02979 {
02980 disconnect(
this, SIGNAL( applyChangesDone(
bool ) ),
02981
this, SLOT( slotContinuePrint(
bool ) ) );
02982
02983
if( rc ) {
02984
if ( mComposedMessages.isEmpty() ) {
02985 kdDebug(5006) <<
"Composing the message failed." << endl;
02986
return;
02987 }
02988 KMCommand *command =
new KMPrintCommand(
this, mComposedMessages.first() );
02989 command->start();
02990 mEditor->setModified( mMessageWasModified );
02991 }
02992 }
02993
02994
02995
02996
void KMComposeWin::doSend(
int aSendNow,
bool saveInDrafts)
02997 {
02998 mSendNow = aSendNow;
02999 mSaveInDrafts = saveInDrafts;
03000
03001
if (!saveInDrafts)
03002 {
03003
if ( from().isEmpty() ) {
03004
if ( !( mShowHeaders & HDR_FROM ) ) {
03005 mShowHeaders |= HDR_FROM;
03006 rethinkFields(
false );
03007 }
03008 mEdtFrom->setFocus();
03009 KMessageBox::sorry(
this,
03010 i18n(
"You must enter your email address in the "
03011
"From: field. You should also set your email "
03012
"address for all identities, so that you do "
03013
"not have to enter it for each message.") );
03014
return;
03015 }
03016
if (to().isEmpty() && cc().isEmpty() && bcc().isEmpty())
03017 {
03018 mEdtTo->setFocus();
03019 KMessageBox::information(
this,
03020 i18n(
"You must specify at least one receiver,"
03021
"either in the To: field or as CC or as BCC.") );
03022
return;
03023 }
03024
03025
if (subject().isEmpty())
03026 {
03027 mEdtSubject->setFocus();
03028
int rc =
03029 KMessageBox::questionYesNo(
this,
03030 i18n(
"You did not specify a subject. "
03031
"Send message anyway?"),
03032 i18n(
"No Subject Specified"),
03033 i18n(
"S&end as Is"),
03034 i18n(
"&Specify the Subject"),
03035
"no_subject_specified" );
03036
if( rc == KMessageBox::No )
03037 {
03038
return;
03039 }
03040 }
03041
03042
if ( userForgotAttachment() )
03043
return;
03044 }
03045
03046
KCursorSaver busy(KBusyPtr::busy());
03047 mMsg->setDateToday();
03048
03049
03050
03051
03052
03053
03054
QString hf = mMsg->headerField(
"X-KMail-Transport");
03055
if ((mTransport->currentText() != mTransport->text(0)) ||
03056 (!hf.isEmpty() && (hf != mTransport->text(0))))
03057 mMsg->setHeaderField(
"X-KMail-Transport", mTransport->currentText());
03058
03059 mDisableBreaking = saveInDrafts;
03060
03061
const bool neverEncrypt = saveInDrafts && mNeverEncryptWhenSavingInDrafts;
03062 connect(
this, SIGNAL( applyChangesDone(
bool ) ),
03063 SLOT( slotContinueDoSend(
bool ) ) );
03064
03065
if ( mEditor->textFormat() == Qt::RichText )
03066 mMsg->setHeaderField(
"X-KMail-Markup",
"true" );
03067
else
03068 mMsg->removeHeaderField(
"X-KMail-Markup" );
03069
if ( mEditor->textFormat() == Qt::RichText && inlineSigningEncryptionSelected() ) {
03070
QString keepBtnText = mEncryptAction->isChecked() ?
03071 mSignAction->isChecked() ? i18n(
"&Keep markup, do not sign/encrypt" )
03072 : i18n( "&Keep markup, do not encrypt" )
03073 : i18n( "&Keep markup, do not sign" );
03074
QString yesBtnText = mEncryptAction->isChecked() ?
03075 mSignAction->isChecked() ? i18n(
"Sign/Encrypt (delete markup)")
03076 : i18n( "Encrypt (delete markup)" )
03077 : i18n( "Sign (delete markup)" );
03078
int ret = KMessageBox::warningYesNoCancel(
this,
03079 i18n(
"<qt><p>Inline signing/encrypting of HTML messages is not possible;</p>"
03080
"<p>do you want to delete your markup?</p></qt>"),
03081 i18n(
"Sign/Encrypt Message?"),
03082 KGuiItem( yesBtnText ),
03083 KGuiItem( keepBtnText ) );
03084
if ( KMessageBox::Cancel == ret )
03085
return;
03086
if ( KMessageBox::No == ret ) {
03087 mEncryptAction->setChecked(
false);
03088 mSignAction->setChecked(
false);
03089 }
03090
else {
03091 toggleMarkup(
false);
03092 }
03093 }
03094
03095 kdDebug(5006) <<
"KMComposeWin::doSend() - calling applyChanges()"
03096 << endl;
03097 applyChanges( neverEncrypt );
03098 }
03099
03100
void KMComposeWin::slotContinueDoSend(
bool sentOk )
03101 {
03102 kdDebug(5006) <<
"KMComposeWin::slotContinueDoSend( " << sentOk <<
" )"
03103 << endl;
03104 disconnect(
this, SIGNAL( applyChangesDone(
bool ) ),
03105
this, SLOT( slotContinueDoSend(
bool ) ) );
03106
03107
if ( !sentOk ) {
03108 mDisableBreaking =
false;
03109
return;
03110 }
03111
if (!mAutoDeleteMsg) mEditor->setModified(FALSE);
03112 mEdtFrom->setEdited(FALSE);
03113 mEdtReplyTo->setEdited(FALSE);
03114 mEdtTo->setEdited(FALSE);
03115 mEdtCc->setEdited(FALSE);
03116 mEdtBcc->setEdited(FALSE);
03117 mEdtSubject->setEdited(FALSE);
03118
if (mTransport->lineEdit())
03119 mTransport->lineEdit()->setEdited(FALSE);
03120 mAtmModified = FALSE;
03121
03122
for (
QValueVector<KMMessage*>::iterator it = mComposedMessages.begin() ; it != mComposedMessages.
end() ; ++it ) {
03123
03124
03125 (*it)->cleanupHeader();
03126
03127
03128 (*it)->setComplete(
true );
03129
03130
if (mSaveInDrafts) {
03131
KMFolder* draftsFolder = 0, *imapDraftsFolder = 0;
03132
03133
if ( !(*it)->drafts().isEmpty() ) {
03134 draftsFolder = kmkernel->folderMgr()->findIdString( (*it)->drafts() );
03135
if ( draftsFolder == 0 )
03136
03137
03138 draftsFolder = kmkernel->dimapFolderMgr()->findIdString( (*it)->drafts() );
03139
if ( draftsFolder == 0 )
03140 imapDraftsFolder = kmkernel->imapFolderMgr()->findIdString( (*it)->drafts() );
03141
if ( !draftsFolder && !imapDraftsFolder ) {
03142
const KPIM::Identity &
id = kmkernel->identityManager()
03143 ->identityForUoidOrDefault( (*it)->headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
03144 KMessageBox::information(0, i18n(
"The custom drafts folder for identity "
03145
"\"%1\" does not exist (anymore); "
03146
"therefore, the default drafts folder "
03147
"will be used.")
03148 .arg(
id.identityName() ) );
03149 }
03150 }
03151
if (imapDraftsFolder && imapDraftsFolder->
noContent())
03152 imapDraftsFolder = 0;
03153
03154
if ( draftsFolder == 0 ) {
03155 draftsFolder = kmkernel->draftsFolder();
03156 }
else {
03157 draftsFolder->
open();
03158 }
03159 kdDebug(5006) <<
"saveindrafts: drafts=" << draftsFolder->name() << endl;
03160
if (imapDraftsFolder)
03161 kdDebug(5006) <<
"saveindrafts: imapdrafts="
03162 << imapDraftsFolder->name() << endl;
03163
03164 sentOk = !(draftsFolder->
addMsg((*it)));
03165
03166
03167 draftsFolder->
unGetMsg(draftsFolder->
count() - 1);
03168 (*it) = draftsFolder->
getMsg(draftsFolder->
count() - 1);
03169
03170
if (imapDraftsFolder) {
03171
03172 imapDraftsFolder->
moveMsg((*it));
03173 (static_cast<KMFolderImap*>(imapDraftsFolder->
storage()))->getFolder();
03174 }
03175
03176 }
else {
03177 (*it)->setTo( KMMessage::expandAliases( to() ));
03178 (*it)->setCc( KMMessage::expandAliases( cc() ));
03179
if( !mComposer->originalBCC().isEmpty() )
03180 (*it)->setBcc( KMMessage::expandAliases( mComposer->originalBCC() ));
03181
QString recips = (*it)->headerField(
"X-KMail-Recipients" );
03182
if( !recips.isEmpty() ) {
03183 (*it)->setHeaderField(
"X-KMail-Recipients", KMMessage::expandAliases( recips ) );
03184 }
03185 (*it)->cleanupHeader();
03186 sentOk = kmkernel->msgSender()->send((*it), mSendNow);
03187 }
03188
03189
if (!sentOk)
03190
return;
03191
03192 *it = 0;
03193 }
03194
03195 RecentAddresses::self( KMKernel::config() )->add( bcc() );
03196 RecentAddresses::self( KMKernel::config() )->add( cc() );
03197 RecentAddresses::self( KMKernel::config() )->add( to() );
03198
03199 mAutoDeleteMsg = FALSE;
03200 mFolder = 0;
03201 close();
03202
return;
03203 }
03204
03205
03206
03207
03208
void KMComposeWin::slotSendLater()
03209 {
03210
if ( mEditor->checkExternalEditorFinished() )
03211 doSend(
false );
03212 }
03213
03214
03215
03216
void KMComposeWin::slotSaveDraft() {
03217
if ( mEditor->checkExternalEditorFinished() )
03218 doSend(
false,
true );
03219 }
03220
03221
03222
03223
void KMComposeWin::slotSendNow() {
03224
if ( !mEditor->checkExternalEditorFinished() )
03225
return;
03226
if (mConfirmSend) {
03227
switch(KMessageBox::warningYesNoCancel(mMainWidget,
03228 i18n(
"About to send email..."),
03229 i18n(
"Send Confirmation"),
03230 i18n(
"Send &Now"),
03231 i18n(
"Send &Later"))) {
03232
case KMessageBox::Yes:
03233 doSend(TRUE);
03234
break;
03235
case KMessageBox::No:
03236 doSend(FALSE);
03237
break;
03238
case KMessageBox::Cancel:
03239
break;
03240
default:
03241 ;
03242 }
03243
return;
03244 }
03245
03246 doSend(TRUE);
03247 }
03248
03249
03250
03251
void KMComposeWin::slotAppendSignature()
03252 {
03253
bool mod = mEditor->isModified();
03254
03255
const KPIM::Identity & ident =
03256 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
03257 mOldSigText = ident.signatureText();
03258
if( !mOldSigText.isEmpty() )
03259 {
03260 mEditor->sync();
03261 mEditor->append(mOldSigText);
03262 mEditor->update();
03263 mEditor->setModified(mod);
03264 mEditor->setContentsPos( 0, 0 );
03265 }
03266 }
03267
03268
03269
03270
void KMComposeWin::slotHelp()
03271 {
03272 kapp->invokeHelp();
03273 }
03274
03275
03276
void KMComposeWin::slotCleanSpace()
03277 {
03278 mEditor->cleanWhiteSpace();
03279 }
03280
03281
03282
void KMComposeWin::slotToggleMarkup()
03283 {
03284
if ( markupAction->isChecked() ) {
03285 toolBar(
"htmlToolBar")->show();
03286
03287 fontChanged( mEditor->currentFont().family() );
03288 fontAction->setFont( mEditor->currentFont().family() );
03289 fontSizeAction->setFontSize( mEditor->currentFont().pointSize() );
03290 mSaveFont = mEditor->currentFont();
03291 }
03292
else
03293 toggleMarkup(
false);
03294
03295 }
03296
03297
void KMComposeWin::toggleMarkup(
bool markup)
03298 {
03299
if ( markup ) {
03300
if ( !mUseHTMLEditor ) {
03301 kdDebug(5006) <<
"setting RichText editor" << endl;
03302 mUseHTMLEditor =
true;
03303
03304
03305
int paraFrom, indexFrom, paraTo, indexTo;
03306 mEditor->getSelection ( ¶From, &indexFrom, ¶To, &indexTo);
03307 mEditor->selectAll();
03308
03309
bool _bold = textBoldAction->isChecked();
03310
bool _italic = textItalicAction->isChecked();
03311 mEditor->setColor(
QColor(0,0,0));
03312 textBoldAction->setChecked(_bold);
03313 textItalicAction->setChecked(_italic);
03314 mEditor->setSelection ( paraFrom, indexFrom, paraTo, indexTo);
03315
03316 mEditor->setTextFormat(Qt::RichText);
03317 mEditor->setModified(
true);
03318 markupAction->setChecked(
true);
03319 toolBar(
"htmlToolBar" )->show();
03320 mEditor->deleteAutoSpellChecking();
03321 mAutoSpellCheckingAction->setChecked(
false);
03322 slotAutoSpellCheckingToggled(
false);
03323 }
03324 }
03325
else if ( mUseHTMLEditor ) {
03326 kdDebug(5006) <<
"setting PlainText editor" << endl;
03327 mUseHTMLEditor =
false;
03328 mEditor->setTextFormat(Qt::PlainText);
03329
QString text = mEditor->text();
03330 mEditor->setText(text);
03331 mEditor->setModified(
true);
03332 toolBar(
"htmlToolBar")->hide();
03333 mEditor->initializeAutoSpellChecking( mDictionaryCombo->spellConfig());
03334 slotAutoSpellCheckingToggled(
true);
03335 }
03336
else if ( !markup && !mUseHTMLEditor )
03337 {
03338 toolBar(
"htmlToolBar")->hide();
03339 }
03340 }
03341
03342
void KMComposeWin::slotSubjectTextSpellChecked()
03343 {
03344 mSubjectTextWasSpellChecked =
true;
03345 }
03346
03347
03348
void KMComposeWin::slotAutoSpellCheckingToggled(
bool on )
03349 {
03350
if ( mEditor->autoSpellChecking(on) == -1 )
03351 mAutoSpellCheckingAction->setChecked(
false);
03352 }
03353
03354
void KMComposeWin::slotSpellcheck()
03355 {
03356
if (mSpellCheckInProgress)
return;
03357 mSubjectTextWasSpellChecked =
false;
03358 mSpellCheckInProgress=TRUE;
03359
03360
03361
03362
03363
03364 mEditor->spellcheck();
03365 }
03366
03367
03368
03369
void KMComposeWin::slotSpellcheckDone(
int result)
03370 {
03371 kdDebug(5006) <<
"spell check complete: result = " << result << endl;
03372 mSpellCheckInProgress=FALSE;
03373
03374
switch( result )
03375 {
03376
case KS_CANCEL:
03377 statusBar()->changeItem(i18n(
" Spell check canceled."),0);
03378
break;
03379
case KS_STOP:
03380 statusBar()->changeItem(i18n(
" Spell check stopped."),0);
03381
break;
03382
default:
03383 statusBar()->changeItem(i18n(
" Spell check complete."),0);
03384
break;
03385 }
03386 QTimer::singleShot( 2000,
this, SLOT(slotSpellcheckDoneClearStatus()) );
03387 }
03388
03389
void KMComposeWin::slotSpellcheckDoneClearStatus()
03390 {
03391 statusBar()->changeItem(
"", 0);
03392 }
03393
03394
03395
03396
void KMComposeWin::focusNextPrevEdit(
const QWidget* aCur,
bool aNext)
03397 {
03398 QWidget* cur;
03399
03400
if (!aCur)
03401 {
03402 cur=mEdtList.last();
03403 }
03404
else
03405 {
03406
for (cur=mEdtList.first(); aCur!=cur && cur; cur=mEdtList.next())
03407 ;
03408
if (!cur)
return;
03409
if (aNext) cur = mEdtList.next();
03410
else cur = mEdtList.prev();
03411 }
03412
if (cur) cur->setFocus();
03413
else if (aNext) mEditor->setFocus();
03414 }
03415
03416
03417
void KMComposeWin::slotIdentityChanged(uint uoid)
03418 {
03419
const KPIM::Identity & ident =
03420 kmkernel->identityManager()->identityForUoid( uoid );
03421
if ( ident.isNull() )
return;
03422
03423
if(!ident.fullEmailAddr().isNull())
03424 mEdtFrom->setText(ident.fullEmailAddr());
03425
03426
if ( from().isEmpty() )
03427 mShowHeaders |= HDR_FROM;
03428 mEdtReplyTo->setText(ident.replyToAddr());
03429
03430
03431
if( !mEdtBcc->edited() || !ident.bcc().isEmpty() )
03432 mEdtBcc->setText(ident.bcc());
03433
03434
if (! ident.bcc().isEmpty()) {
03435 mShowHeaders |= HDR_BCC;
03436 }
03437
if (ident.organization().isEmpty())
03438 mMsg->removeHeaderField(
"Organization");
03439
else
03440 mMsg->setHeaderField(
"Organization", ident.organization());
03441
03442
if (!mBtnTransport->isChecked()) {
03443
QString transp = ident.transport();
03444
if (transp.isEmpty())
03445 {
03446 mMsg->removeHeaderField(
"X-KMail-Transport");
03447 transp = mTransport->text(0);
03448 }
03449
else
03450 mMsg->setHeaderField(
"X-KMail-Transport", transp);
03451
bool found =
false;
03452
int i;
03453
for (i = 0; i < mTransport->count(); i++) {
03454
if (mTransport->text(i) == transp) {
03455 found =
true;
03456 mTransport->setCurrentItem(i);
03457
break;
03458 }
03459 }
03460
if (found ==
false) {
03461
if (i == mTransport->maxCount()) mTransport->setMaxCount(i + 1);
03462 mTransport->insertItem(transp,i);
03463 mTransport->setCurrentItem(i);
03464 }
03465 }
03466
03467 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
03468
03469
if ( !mBtnFcc->isChecked() )
03470 {
03471
if ( ident.fcc().isEmpty() )
03472 mFcc->setFolder( kmkernel->sentFolder() );
03473
else
03474 setFcc( ident.fcc() );
03475 }
03476
03477
QString edtText = mEditor->text();
03478
bool appendNewSig =
true;
03479
03480
if( !mOldSigText.isEmpty() )
03481 {
03482
if( edtText.endsWith( mOldSigText ) )
03483 edtText.truncate( edtText.length() - mOldSigText.length() );
03484
else
03485 appendNewSig =
false;
03486 }
03487
03488 mOldSigText = ident.signatureText();
03489
if( appendNewSig )
03490 {
03491
if( !mOldSigText.isEmpty() && mAutoSign )
03492 edtText.append( mOldSigText );
03493 mEditor->setText( edtText );
03494 }
03495
03496
03497
03498
bool bNewIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
03499
bool bNewIdentityHasEncryptionKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
03500 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
03501 !ident.pgpEncryptionKey().isEmpty() );
03502
03503
if ( !bNewIdentityHasEncryptionKey && mLastIdentityHasEncryptionKey ) {
03504 mLastEncryptActionState = mEncryptAction->isChecked();
03505 setEncryption(
false );
03506 }
03507
if ( !bNewIdentityHasSigningKey && mLastIdentityHasSigningKey ) {
03508 mLastSignActionState = mSignAction->isChecked();
03509 setSigning(
false );
03510 }
03511
03512
if ( bNewIdentityHasEncryptionKey && !mLastIdentityHasEncryptionKey )
03513 setEncryption( mLastEncryptActionState );
03514
if ( bNewIdentityHasSigningKey && !mLastIdentityHasSigningKey )
03515 setSigning( mLastSignActionState );
03516
03517 mLastIdentityHasSigningKey = bNewIdentityHasSigningKey;
03518 mLastIdentityHasEncryptionKey = bNewIdentityHasEncryptionKey;
03519
03520 mEditor->setModified(TRUE);
03521 mId = uoid;
03522
03523
03524 rethinkFields(
false );
03525 }
03526
03527
03528
void KMComposeWin::slotSpellcheckConfig()
03529 {
03530 KWin kwin;
03531
QTabDialog qtd (
this,
"tabdialog",
true);
03532 KSpellConfig mKSpellConfig (&qtd);
03533
03534 qtd.addTab (&mKSpellConfig, i18n(
"Spellchecker"));
03535 qtd.setCancelButton ();
03536
03537 kwin.setIcons (qtd.winId(), kapp->icon(), kapp->miniIcon());
03538 qtd.setCancelButton(KStdGuiItem::cancel().text());
03539 qtd.
setOkButton(KStdGuiItem::ok().text());
03540
03541
if (qtd.exec())
03542 mKSpellConfig.writeGlobalSettings();
03543 }
03544
03545
03546
void KMComposeWin::slotStatusMessage(
const QString &message)
03547 {
03548 statusBar()->changeItem( message, 0 );
03549 }
03550
03551
void KMComposeWin::slotEditToolbars()
03552 {
03553 saveMainWindowSettings(KMKernel::config(),
"Composer");
03554 KEditToolbar dlg(guiFactory(),
this);
03555
03556 connect( &dlg, SIGNAL(newToolbarConfig()),
03557 SLOT(slotUpdateToolbars()) );
03558
03559 dlg.exec();
03560 }
03561
03562
void KMComposeWin::slotUpdateToolbars()
03563 {
03564 createGUI(
"kmcomposerui.rc");
03565 applyMainWindowSettings(KMKernel::config(),
"Composer");
03566 }
03567
03568
void KMComposeWin::slotEditKeys()
03569 {
03570 KKeyDialog::configure( actionCollection(),
03571
false
03572 );
03573 }
03574
03575
void KMComposeWin::setReplyFocus(
bool hasMessage )
03576 {
03577 mEditor->setFocus();
03578
if ( hasMessage )
03579 mEditor->setCursorPosition( 1, 0 );
03580 }
03581
03582
void KMComposeWin::setFocusToSubject()
03583 {
03584 mEdtSubject->setFocus();
03585 }
03586
03587
void KMComposeWin::slotCompletionModeChanged( KGlobalSettings::Completion mode)
03588 {
03589 KConfig *config = KMKernel::config();
03590 KConfigGroupSaver cs( config,
"Composer" );
03591 config->writeEntry(
"Completion Mode", (
int) mode );
03592 config->sync();
03593
03594
03595 mEdtFrom->setCompletionMode( mode );
03596 mEdtReplyTo->setCompletionMode( mode );
03597 mEdtTo->setCompletionMode( mode );
03598 mEdtCc->setCompletionMode( mode );
03599 mEdtBcc->setCompletionMode( mode );
03600 }
03601
03602
void KMComposeWin::slotConfigChanged()
03603 {
03604 readConfig();
03605 }
03606
03607
03608
03609
03610
03611
void KMComposeWin::slotFolderRemoved(
KMFolder* folder)
03612 {
03613
if ( (mFolder) && (folder->
idString() == mFolder->idString()) )
03614 {
03615 mFolder = kmkernel->draftsFolder();
03616 kdDebug(5006) <<
"restoring drafts to " << mFolder->idString() << endl;
03617 }
03618
if (mMsg) mMsg->setParent(0);
03619 }
03620
03621
03622
03623
void KMComposeWin::slotSetAlwaysSend(
bool bAlways )
03624 {
03625 mAlwaysSend = bAlways;
03626 }
03627
03628
void KMComposeWin::slotListAction(
const QString& style )
03629 {
03630 toggleMarkup(
true);
03631
if ( style == i18n(
"Standard" ) )
03632 mEditor->setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
03633
else if ( style == i18n(
"Bulleted List (Disc)" ) )
03634 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
03635
else if ( style == i18n(
"Bulleted List (Circle)" ) )
03636 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListCircle );
03637
else if ( style == i18n(
"Bulleted List (Square)" ) )
03638 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListSquare );
03639
else if ( style == i18n(
"Ordered List (Decimal)" ))
03640 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDecimal );
03641
else if ( style == i18n(
"Ordered List (Alpha lower)" ) )
03642 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListLowerAlpha );
03643
else if ( style == i18n(
"Ordered List (Alpha upper)" ) )
03644 mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListUpperAlpha );
03645 mEditor->viewport()->setFocus();
03646 }
03647
03648
void KMComposeWin::slotFontAction(
const QString& font)
03649 {
03650 toggleMarkup(
true);
03651 mEditor->QTextEdit::setFamily( font );
03652 mEditor->viewport()->setFocus();
03653 }
03654
03655
void KMComposeWin::slotSizeAction(
int size )
03656 {
03657 toggleMarkup(
true);
03658 mEditor->setPointSize( size );
03659 mEditor->viewport()->setFocus();
03660 }
03661
03662
void KMComposeWin::slotAlignLeft()
03663 {
03664 toggleMarkup(
true);
03665 mEditor->QTextEdit::setAlignment( AlignLeft );
03666 }
03667
03668
void KMComposeWin::slotAlignCenter()
03669 {
03670 toggleMarkup(
true);
03671 mEditor->QTextEdit::setAlignment( AlignHCenter );
03672 }
03673
03674
void KMComposeWin::slotAlignRight()
03675 {
03676 toggleMarkup(
true);
03677 mEditor->QTextEdit::setAlignment( AlignRight );
03678 }
03679
03680
void KMComposeWin::slotTextBold()
03681 {
03682 toggleMarkup(
true);
03683 mEditor->QTextEdit::setBold( textBoldAction->isChecked() );
03684 }
03685
03686
void KMComposeWin::slotTextItalic()
03687 {
03688 toggleMarkup(
true);
03689 mEditor->QTextEdit::setItalic( textItalicAction->isChecked() );
03690 }
03691
03692
void KMComposeWin::slotTextUnder()
03693 {
03694 toggleMarkup(
true);
03695 mEditor->QTextEdit::setUnderline( textUnderAction->isChecked() );
03696 }
03697
03698
void KMComposeWin::slotFormatReset()
03699 {
03700 mEditor->setColor(mForeColor);
03701 mEditor->setCurrentFont( mSaveFont );
03702 }
03703
void KMComposeWin::slotTextColor()
03704 {
03705
QColor color = mEditor->color();
03706
03707
if ( KColorDialog::getColor( color,
this ) ) {
03708 toggleMarkup(
true);
03709 mEditor->setColor( color );
03710 }
03711 }
03712
03713
void KMComposeWin::fontChanged(
const QFont &f )
03714 {
03715
QFontDatabase *fontdb =
new QFontDatabase();
03716
03717
if ( fontdb->bold(f.family(),
"Bold") ) {
03718 textBoldAction->setChecked( f.bold() );
03719 textBoldAction->setEnabled(
true);
03720 }
03721
else
03722 textBoldAction->setEnabled(
false);
03723
03724
if ( fontdb->italic(f.family(),
"Italic") ) {
03725 textItalicAction->setChecked( f.
italic() );
03726 textItalicAction->setEnabled(
true);
03727 }
03728
else
03729 textItalicAction->setEnabled(
false);
03730
03731 textUnderAction->setChecked( f.underline() );
03732
03733 fontAction->setFont( f.family() );
03734 fontSizeAction->setFontSize( f.
pointSize() );
03735
delete fontdb;
03736 }
03737
03738
void KMComposeWin::alignmentChanged(
int a )
03739 {
03740
03741 alignLeftAction->setChecked( ( a == AlignAuto ) || ( a & AlignLeft ) );
03742 alignCenterAction->setChecked( ( a & AlignHCenter ) );
03743 alignRightAction->setChecked( ( a & AlignRight ) );
03744 }
03745
03746
03747
void KMEdit::contentsDragEnterEvent(
QDragEnterEvent *e)
03748 {
03749
if (e->provides(MailListDrag::format()))
03750 e->accept(
true);
03751
else
03752
return KEdit::contentsDragEnterEvent(e);
03753 }
03754
03755
void KMEdit::contentsDragMoveEvent(
QDragMoveEvent *e)
03756 {
03757
if (e->provides(MailListDrag::format()))
03758 e->accept();
03759
else
03760
return KEdit::contentsDragMoveEvent(e);
03761 }
03762
03763
void KMEdit::keyPressEvent(
QKeyEvent* e )
03764 {
03765
if( e->key() == Key_Return ) {
03766
int line, col;
03767 getCursorPosition( &line, &col );
03768
QString lineText = text( line );
03769
03770 lineText.truncate( lineText.length() - 1 );
03771
03772
03773
if( ( col > 0 ) && ( col < int( lineText.length() ) ) ) {
03774
bool isQuotedLine =
false;
03775 uint bot = 0;
03776
while( bot < lineText.length() ) {
03777
if( ( lineText[bot] ==
'>' ) || ( lineText[bot] ==
'|' ) ) {
03778 isQuotedLine =
true;
03779 ++bot;
03780 }
03781
else if( lineText[bot].isSpace() ) {
03782 ++bot;
03783 }
03784
else {
03785
break;
03786 }
03787 }
03788
03789 KEdit::keyPressEvent( e );
03790
03791
03792
03793
03794
if( isQuotedLine
03795 && ( bot != lineText.length() )
03796 && ( col >= int( bot ) ) ) {
03797
03798
03799
03800 getCursorPosition( &line, &col );
03801
QString newLine = text( line );
03802
03803
03804
unsigned int leadingWhiteSpaceCount = 0;
03805
while( ( leadingWhiteSpaceCount < newLine.length() )
03806 && newLine[leadingWhiteSpaceCount].isSpace() ) {
03807 ++leadingWhiteSpaceCount;
03808 }
03809 newLine = newLine.replace( 0, leadingWhiteSpaceCount,
03810 lineText.left( bot ) );
03811 removeParagraph( line );
03812 insertParagraph( newLine, line );
03813
03814
03815
03816 setCursorPosition( line, 0 );
03817 }
03818 }
03819
else
03820 KEdit::keyPressEvent( e );
03821 }
03822
else
03823 KEdit::keyPressEvent( e );
03824 }
03825
03826
void KMEdit::contentsDropEvent(
QDropEvent *e)
03827 {
03828
if (e->provides(MailListDrag::format())) {
03829
03830
QByteArray serNums;
03831 MailListDrag::decode( e, serNums );
03832
QBuffer serNumBuffer(serNums);
03833 serNumBuffer.open(IO_ReadOnly);
03834
QDataStream serNumStream(&serNumBuffer);
03835
unsigned long serNum;
03836
KMFolder *folder = 0;
03837
int idx;
03838
QPtrList<KMMsgBase> messageList;
03839
while (!serNumStream.atEnd()) {
03840 KMMsgBase *msgBase = 0;
03841 serNumStream >> serNum;
03842 kmkernel->msgDict()->getLocation(serNum, &folder, &idx);
03843
if (folder)
03844 msgBase = folder->
getMsgBase(idx);
03845
if (msgBase)
03846 messageList.append( msgBase );
03847 }
03848 serNumBuffer.close();
03849 uint identity = folder ? folder->
identity() : 0;
03850 KMCommand *command =
03851
new KMForwardAttachedCommand(mComposer, messageList,
03852 identity, mComposer);
03853 command->start();
03854 }
03855
else if( KURLDrag::canDecode( e ) ) {
03856 KURL::List urlList;
03857
if( KURLDrag::decode( e, urlList ) ) {
03858
for( KURL::List::Iterator it = urlList.begin();
03859 it != urlList.end(); ++it ) {
03860 mComposer->addAttach( *it );
03861 }
03862 }
03863 }
03864
else {
03865
return KEdit::contentsDropEvent(e);
03866 }
03867 }
03868
03869
03870
03871
03872
03873
03874
03875 KMAtmListViewItem::KMAtmListViewItem(
QListView *parent) :
03876
QObject(),
QListViewItem( parent )
03877 {
03878
03879 mCBSignEnabled =
false;
03880 mCBEncryptEnabled =
false;
03881
03882 mListview = parent;
03883 mCBEncrypt =
new QCheckBox(mListview->viewport());
03884 mCBSign =
new QCheckBox(mListview->viewport());
03885
03886 mCBEncrypt->hide();
03887 mCBSign->hide();
03888 }
03889
03890 KMAtmListViewItem::~KMAtmListViewItem()
03891 {
03892 }
03893
03894
void KMAtmListViewItem::paintCell(
QPainter * p,
const QColorGroup & cg,
03895
int column,
int width,
int align )
03896 {
03897
03898
03899 QListViewItem::paintCell( p, cg, column, width, align );
03900
if( 4 == column || 5 == column ) {
03901
QRect r = mListview->itemRect(
this );
03902
if ( !r.size().isValid() ) {
03903 mListview->ensureItemVisible(
this );
03904 mListview->repaintContents( FALSE );
03905 r = mListview->itemRect(
this );
03906 }
03907
int colWidth = mListview->header()->sectionSize( column );
03908 r.setX( mListview->header()->sectionPos( column )
03909 + colWidth / 2
03910 - r.height() / 2
03911 - 1 );
03912 r.setY( r.y() + 1 );
03913 r.setWidth( r.height() - 2 );
03914 r.setHeight( r.height() - 2 );
03915 r =
QRect( mListview->viewportToContents( r.topLeft() ), r.size() );
03916
03917 QCheckBox* cb = (4 == column) ? mCBEncrypt : mCBSign;
03918 cb->resize( r.size() );
03919 mListview->moveChild( cb, r.x(), r.y() );
03920
03921
QColor bg;
03922
if (isSelected())
03923 bg = cg.highlight();
03924
else
03925 bg = cg.base();
03926
03927
bool enabled = (4 == column) ? mCBEncryptEnabled : mCBSignEnabled;
03928 cb->setPaletteBackgroundColor(bg);
03929
if (enabled) cb->show();
03930 }
03931 }
03932
03933
void KMAtmListViewItem::enableCryptoCBs(
bool on)
03934 {
03935
if( mCBEncrypt ) {
03936 mCBEncryptEnabled = on;
03937 mCBEncrypt->setEnabled( on );
03938 }
03939
if( mCBSign ) {
03940 mCBSignEnabled = on;
03941 mCBSign->setEnabled( on );
03942 }
03943 }
03944
03945
void KMAtmListViewItem::setEncrypt(
bool on)
03946 {
03947
if( mCBEncrypt )
03948 mCBEncrypt->setChecked( on );
03949 }
03950
03951
bool KMAtmListViewItem::isEncrypt()
03952 {
03953
if( mCBEncrypt )
03954
return mCBEncrypt->isChecked();
03955
else
03956
return false;
03957 }
03958
03959
void KMAtmListViewItem::setSign(
bool on)
03960 {
03961
if( mCBSign )
03962 mCBSign->setChecked( on );
03963 }
03964
03965
bool KMAtmListViewItem::isSign()
03966 {
03967
if( mCBSign )
03968
return mCBSign->isChecked();
03969
else
03970
return false;
03971 }
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981 KMLineEdit::KMLineEdit(KMComposeWin* composer,
bool useCompletion,
03982 QWidget *parent,
const char *name)
03983 : KPIM::AddresseeLineEdit(parent,useCompletion,name), mComposer(composer)
03984 {
03985 }
03986
03987
03988
03989
void KMLineEdit::keyPressEvent(
QKeyEvent *e)
03990 {
03991
03992
if ((e->key() == Key_Enter || e->key() == Key_Return) &&
03993 !completionBox()->isVisible())
03994 {
03995 mComposer->focusNextPrevEdit(
this,TRUE);
03996
return;
03997 }
03998
if (e->key() == Key_Up)
03999 {
04000 mComposer->focusNextPrevEdit(
this,FALSE);
04001
return;
04002 }
04003
if (e->key() == Key_Down)
04004 {
04005 mComposer->focusNextPrevEdit(
this,TRUE);
04006
return;
04007 }
04008
04009 AddresseeLineEdit::keyPressEvent(e);
04010 }
04011
04012 QPopupMenu *KMLineEdit::createPopupMenu()
04013 {
04014 QPopupMenu *menu = KPIM::AddresseeLineEdit::createPopupMenu();
04015
if ( !menu )
04016
return 0;
04017
04018 menu->insertSeparator();
04019 menu->insertItem( i18n(
"Edit Recent Addresses..." ),
04020
this, SLOT( editRecentAddresses() ) );
04021
04022
return menu;
04023 }
04024
04025
void KMLineEdit::editRecentAddresses()
04026 {
04027 KRecentAddress::RecentAddressDialog dlg(
this );
04028 dlg.setAddresses( RecentAddresses::self( KMKernel::config() )->addresses() );
04029
if ( dlg.exec() ) {
04030 RecentAddresses::self( KMKernel::config() )->clear();
04031
QStringList addrList = dlg.addresses();
04032 QStringList::Iterator it;
04033
for ( it = addrList.begin(); it != addrList.end(); ++it )
04034 RecentAddresses::self( KMKernel::config() )->add( *it );
04035
04036 loadContacts();
04037 }
04038 }
04039
04040
04041
04042
void KMLineEdit::loadContacts()
04043 {
04044
04045 AddresseeLineEdit::loadContacts();
04046
04047
QStringList recent =
04048 RecentAddresses::self( KMKernel::config() )->addresses();
04049 QStringList::Iterator it = recent.begin();
04050
QString name, email;
04051
for ( ; it != recent.end(); ++it ) {
04052 KABC::Addressee addr;
04053 KPIM::getNameAndMail(*it, name, email);
04054 addr.setNameFromString( name );
04055 addr.insertEmail( email,
true );
04056 addContact( addr, 120 );
04057 }
04058 }
04059
04060
04061 KMLineEditSpell::KMLineEditSpell(KMComposeWin* composer,
bool useCompletion,
04062 QWidget *parent,
const char *name)
04063 : KMLineEdit(composer,useCompletion,parent,name)
04064 {
04065 }
04066
04067
04068
void KMLineEditSpell::highLightWord(
unsigned int length,
unsigned int pos )
04069 {
04070 setSelection ( pos, length );
04071 }
04072
04073
void KMLineEditSpell::spellCheckDone(
const QString &s )
04074 {
04075
if( s != text() )
04076 setText( s );
04077 }
04078
04079
void KMLineEditSpell::spellCheckerMisspelling(
const QString &_text,
const QStringList&,
unsigned int pos)
04080 {
04081 highLightWord( _text.length(),pos );
04082 }
04083
04084
void KMLineEditSpell::spellCheckerCorrected(
const QString &old,
const QString &corr,
unsigned int pos)
04085 {
04086
if( old!= corr )
04087 {
04088 setSelection ( pos, old.length() );
04089 insert( corr );
04090 setSelection ( pos, corr.length() );
04091 emit subjectTextSpellChecked();
04092 }
04093 }
04094
04095
04096
04097
04098
04099
04100
04101 KMEdit::KMEdit(QWidget *parent, KMComposeWin* composer,
04102 KSpellConfig* autoSpellConfig,
04103
const char *name)
04104 : KEdit( parent, name ),
04105 mComposer( composer ),
04106 mKSpell( 0 ),
04107 mSpellingFilter( 0 ),
04108 mExtEditorTempFile( 0 ),
04109 mExtEditorTempFileWatcher( 0 ),
04110 mExtEditorProcess( 0 ),
04111 mUseExtEditor( false ),
04112 mWasModifiedBeforeSpellCheck( false ),
04113 mSpellChecker( 0 ),
04114 mSpellLineEdit( false )
04115 {
04116 installEventFilter(
this);
04117 KCursor::setAutoHideCursor(
this,
true,
true );
04118
04119 initializeAutoSpellChecking( autoSpellConfig );
04120 }
04121
04122
04123
void KMEdit::initializeAutoSpellChecking( KSpellConfig* autoSpellConfig )
04124 {
04125
if ( mSpellChecker )
04126
return;
04127 KConfigGroup readerConfig( KMKernel::config(),
"Reader" );
04128
QColor defaultColor1( 0,0,221 );
04129
QColor defaultColor2( 0,99, 18 );
04130
QColor defaultColor3( 84,0,0 );
04131
QColor defaultForeground( kapp->palette().active().text() );
04132
QColor col1 = readerConfig.readColorEntry(
"ForegroundColor", &defaultForeground );
04133
QColor col2 = readerConfig.readColorEntry(
"QuotedText3", &defaultColor3 );
04134
QColor col3 = readerConfig.readColorEntry(
"QuotedText2", &defaultColor2 );
04135
QColor col4 = readerConfig.readColorEntry(
"QuotedText1", &defaultColor1 );
04136
QColor c = Qt::red;
04137
QColor misspelled = readerConfig.readColorEntry(
"MisspelledColor", &c );
04138
04139 mSpellChecker =
new KDictSpellingHighlighter(
this,
true,
04140
false,
04141 misspelled,
04142
true,
04143 col1, col2, col3, col4,
04144 autoSpellConfig );
04145 connect( mSpellChecker, SIGNAL(activeChanged(
const QString &)),
04146 mComposer, SLOT(slotStatusMessage(
const QString &)));
04147 connect( mSpellChecker, SIGNAL(newSuggestions(
const QString&,
const QStringList&,
unsigned int)),
04148
this, SLOT(addSuggestion(
const QString&,
const QStringList&,
unsigned int)) );
04149 }
04150
04151
04152
void KMEdit::deleteAutoSpellChecking()
04153 {
04154
delete mSpellChecker;
04155 mSpellChecker =0;
04156 }
04157
04158
void KMEdit::addSuggestion(
const QString& text,
const QStringList& lst,
unsigned int )
04159 {
04160 mReplacements[text] = lst;
04161 }
04162
04163
void KMEdit::setSpellCheckingActive(
bool spellCheckingActive)
04164 {
04165
if ( mSpellChecker ) {
04166 mSpellChecker->setActive(spellCheckingActive);
04167 }
04168 }
04169
04170
04171 KMEdit::~KMEdit()
04172 {
04173 removeEventFilter(
this);
04174
04175
delete mKSpell;
04176
delete mSpellChecker;
04177 mSpellChecker = 0;
04178
04179 }
04180
04181
04182
04183
QString KMEdit::brokenText()
04184 {
04185
QString temp, line;
04186
04187
int num_lines = numLines();
04188
for (
int i = 0; i < num_lines; ++i)
04189 {
04190
int lastLine = 0;
04191 line = textLine(i);
04192
for (
int j = 0; j < (
int)line.length(); ++j)
04193 {
04194
if (lineOfChar(i, j) > lastLine)
04195 {
04196 lastLine = lineOfChar(i, j);
04197 temp +=
'\n';
04198 }
04199 temp += line[j];
04200 }
04201
if (i + 1 < num_lines) temp +=
'\n';
04202 }
04203
04204
return temp;
04205 }
04206
04207
04208
bool KMEdit::eventFilter(
QObject*o,
QEvent* e)
04209 {
04210
if (o ==
this)
04211 KCursor::autoHideEventFilter(o, e);
04212
04213
if (e->type() == QEvent::KeyPress)
04214 {
04215
QKeyEvent *k = (
QKeyEvent*)e;
04216
04217
if (mUseExtEditor) {
04218
if (k->key() == Key_Up)
04219 {
04220 mComposer->focusNextPrevEdit(0,
false);
04221
return TRUE;
04222 }
04223
04224
04225
if ( (k->key() == Key_Shift) || (k->key() == Key_Control) ||
04226 (k->key() == Key_Meta) || (k->key() == Key_Alt) )
04227
return true;
04228
if (mExtEditorTempFile)
return TRUE;
04229
QString sysLine = mExtEditor;
04230 mExtEditorTempFile =
new KTempFile();
04231
04232 mExtEditorTempFile->setAutoDelete(
true);
04233
04234 (*mExtEditorTempFile->textStream()) << text();
04235
04236 mExtEditorTempFile->close();
04237
04238 sysLine.replace(
"%f", mExtEditorTempFile->name() );
04239 mExtEditorProcess =
new KProcess();
04240 sysLine +=
" ";
04241
while (!sysLine.isEmpty())
04242 {
04243 *mExtEditorProcess << sysLine.left(sysLine.find(
" ")).local8Bit();
04244 sysLine.remove(0, sysLine.find(
" ") + 1);
04245 }
04246 connect(mExtEditorProcess, SIGNAL(processExited(KProcess*)),
04247 SLOT(slotExternalEditorDone(KProcess*)));
04248
if (!mExtEditorProcess->start())
04249 {
04250 KMessageBox::error( topLevelWidget(),
04251 i18n(
"Unable to start external editor.") );
04252 killExternalEditor();
04253 }
else {
04254 mExtEditorTempFileWatcher =
new KDirWatch(
this,
"mExtEditorTempFileWatcher" );
04255 connect( mExtEditorTempFileWatcher, SIGNAL(dirty(
const QString&)),
04256 SLOT(slotExternalEditorTempFileChanged(
const QString&)) );
04257 mExtEditorTempFileWatcher->addFile( mExtEditorTempFile->name() );
04258 }
04259
return TRUE;
04260 }
else {
04261
04262
04263
if (k->key() == Key_Up && k->state() != ShiftButton && currentLine() == 0
04264 && lineOfChar(0, currentColumn()) == 0)
04265 {
04266 deselect();
04267 mComposer->focusNextPrevEdit(0,
false);
04268
return TRUE;
04269 }
04270
04271
04272
if (k->key() == Key_Backtab && k->state() == ShiftButton)
04273 {
04274 deselect();
04275 mComposer->focusNextPrevEdit(0,
false);
04276
return TRUE;
04277 }
04278
04279 }
04280 }
else if ( e->type() == QEvent::ContextMenu ) {
04281
QContextMenuEvent *event = (
QContextMenuEvent*) e;
04282
04283
int para = 1, charPos, firstSpace, lastSpace;
04284
04285
04286 charPos = charAt( viewportToContents(event->pos()), ¶ );
04287
QString paraText = text( para );
04288
04289
if( !paraText.at(charPos).isSpace() )
04290 {
04291
04292
const QRegExp wordBoundary(
"[\\s\\W]" );
04293 firstSpace = paraText.findRev( wordBoundary, charPos ) + 1;
04294 lastSpace = paraText.find( wordBoundary, charPos );
04295
if( lastSpace == -1 )
04296 lastSpace = paraText.length();
04297
QString word = paraText.mid( firstSpace, lastSpace - firstSpace );
04298
04299
if( !word.isEmpty() && mReplacements.contains( word ) )
04300 {
04301 KPopupMenu p;
04302 p.insertTitle( i18n(
"Suggestions") );
04303
04304
04305
QStringList reps = mReplacements[word];
04306
if( reps.count() > 0 )
04307 {
04308
int listPos = 0;
04309
for ( QStringList::Iterator it = reps.begin(); it != reps.end(); ++it ) {
04310 p.insertItem( *it, listPos );
04311 listPos++;
04312 }
04313 }
04314
else
04315 {
04316 p.insertItem( QString::fromLatin1(
"No Suggestions"), -2 );
04317 }
04318
04319
04320
int id = p.exec( mapToGlobal( event->pos() ) );
04321
04322
if(
id > -1 )
04323 {
04324
04325
int parIdx = 1, txtIdx = 1;
04326 getCursorPosition(&parIdx, &txtIdx);
04327 setSelection(para, firstSpace, para, lastSpace);
04328 insert(mReplacements[word][
id]);
04329
04330
04331
if ( para == parIdx && txtIdx >= lastSpace )
04332 txtIdx += mReplacements[word][
id].length() - word.length();
04333 setCursorPosition(parIdx, txtIdx);
04334 }
04335
04336
return true;
04337 }
04338 }
04339 }
04340
04341
return KEdit::eventFilter(o, e);
04342 }
04343
04344
04345
04346
int KMEdit::autoSpellChecking(
bool on )
04347 {
04348
if ( textFormat() == Qt::RichText ) {
04349
04350
if ( on )
04351 KMessageBox::sorry(
this, i18n(
"Automatic spellchecking is not possible on text with markup."));
04352
return -1;
04353 }
04354
04355
04356 mSpellChecker->setAutomatic( on );
04357 mSpellChecker->setActive( on );
04358
return 1;
04359 }
04360
04361
04362
04363
void KMEdit::slotExternalEditorTempFileChanged(
const QString & fileName ) {
04364
if ( !mExtEditorTempFile )
04365
return;
04366
if ( fileName != mExtEditorTempFile->name() )
04367
return;
04368
04369 setAutoUpdate(
false);
04370 clear();
04371
04372 insertLine(QString::fromLocal8Bit(KPIM::kFileToString( fileName,
true,
false )), -1);
04373 setAutoUpdate(
true);
04374 repaint();
04375 }
04376
04377
void KMEdit::slotExternalEditorDone( KProcess * proc ) {
04378 assert(proc == mExtEditorProcess);
04379
04380 slotExternalEditorTempFileChanged( mExtEditorTempFile->name() );
04381 killExternalEditor();
04382 }
04383
04384
void KMEdit::killExternalEditor() {
04385
delete mExtEditorTempFileWatcher; mExtEditorTempFileWatcher = 0;
04386
delete mExtEditorTempFile; mExtEditorTempFile = 0;
04387
delete mExtEditorProcess; mExtEditorProcess = 0;
04388 }
04389
04390
04391
bool KMEdit::checkExternalEditorFinished() {
04392
if ( !mExtEditorProcess )
04393
return true;
04394
switch ( KMessageBox::warningYesNoCancel( topLevelWidget(),
04395 i18n(
"The external editor is still running.\n"
04396
"Abort the external editor or leave it open?"),
04397 i18n(
"External Editor"),
04398 i18n(
"Abort Editor"), i18n(
"Leave Editor Open") ) ) {
04399
case KMessageBox::Yes:
04400 killExternalEditor();
04401
return true;
04402
case KMessageBox::No:
04403
return true;
04404
default:
04405
return false;
04406 }
04407 }
04408
04409
04410
void KMEdit::spellcheck()
04411 {
04412
if ( mKSpell )
04413
return;
04414 mWasModifiedBeforeSpellCheck = isModified();
04415 mSpellLineEdit = !mSpellLineEdit;
04416
04417
04418
04419
04420
04421
04422
04423 mKSpell =
new KSpell(
this, i18n(
"Spellcheck - KMail"),
this,
04424 SLOT(slotSpellcheck2(KSpell*)));
04425
04426
04427
QStringList l = KSpellingHighlighter::personalWords();
04428
for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
04429 mKSpell->addPersonal( *it );
04430 }
04431 connect (mKSpell, SIGNAL( death()),
04432
this, SLOT (slotSpellDone()));
04433 connect (mKSpell, SIGNAL (misspelling (
const QString &,
const QStringList &,
unsigned int)),
04434
this, SLOT (slotMisspelling (
const QString &,
const QStringList &,
unsigned int)));
04435 connect (mKSpell, SIGNAL (corrected (
const QString &,
const QString &,
unsigned int)),
04436
this, SLOT (slotCorrected (
const QString &,
const QString &,
unsigned int)));
04437 connect (mKSpell, SIGNAL (done(
const QString &)),
04438
this, SLOT (slotSpellResult (
const QString&)));
04439 }
04440
04441
void KMEdit::cut()
04442 {
04443 KEdit::cut();
04444
if ( textFormat() != Qt::RichText )
04445 mSpellChecker->restartBackgroundSpellCheck();
04446 }
04447
04448
void KMEdit::clear()
04449 {
04450 KEdit::clear();
04451
if ( textFormat() != Qt::RichText )
04452 mSpellChecker->restartBackgroundSpellCheck();
04453 }
04454
04455
void KMEdit::del()
04456 {
04457 KEdit::del();
04458
if ( textFormat() != Qt::RichText )
04459 mSpellChecker->restartBackgroundSpellCheck();
04460 }
04461
04462
04463
void KMEdit::slotMisspelling(
const QString &text,
const QStringList &lst,
unsigned int pos)
04464 {
04465 kdDebug(5006)<<
"void KMEdit::slotMisspelling(const QString &text, const QStringList &lst, unsigned int pos) : "<<text <<endl;
04466
if( mSpellLineEdit )
04467 mComposer->sujectLineWidget()->spellCheckerMisspelling( text, lst, pos);
04468
else
04469 misspelling(text, lst, pos);
04470 }
04471
04472
void KMEdit::slotCorrected (
const QString &oldWord,
const QString &newWord,
unsigned int pos)
04473 {
04474 kdDebug(5006)<<
"slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos) : "<<oldWord<<endl;
04475
if( mSpellLineEdit )
04476 mComposer->sujectLineWidget()->spellCheckerCorrected( oldWord, newWord, pos);
04477
else {
04478
unsigned int l = 0;
04479
unsigned int cnt = 0;
04480
bool _bold,_underline,_italic;
04481
QColor _color;
04482
QFont _font;
04483 posToRowCol (pos, l, cnt);
04484 setCursorPosition(l, cnt+1);
04485 _bold = bold();
04486 _underline = underline();
04487 _italic = italic();
04488 _color = color();
04489 _font = currentFont();
04490 corrected(oldWord, newWord, pos);
04491 setSelection (l, cnt, l, cnt+newWord.length());
04492 setBold(_bold);
04493 setItalic(_italic);
04494 setUnderline(_underline);
04495 setColor(_color);
04496 setCurrentFont(_font);
04497 }
04498
04499 }
04500
04501
04502
void KMEdit::slotSpellcheck2(KSpell*)
04503 {
04504
if( !mSpellLineEdit)
04505 {
04506 spellcheck_start();
04507
04508 QString quotePrefix;
04509
if(mComposer && mComposer->msg())
04510 {
04511
04512 KConfig *config=KMKernel::config();
04513 KConfigGroupSaver saver(config,
"General");
04514
04515
int languageNr = config->readNumEntry(
"reply-current-language",0);
04516 config->setGroup( QString(
"KMMessage #%1").arg(languageNr) );
04517
04518 quotePrefix = config->readEntry(
"indent-prefix",
">%_");
04519 quotePrefix = mComposer->msg()->formatString(quotePrefix);
04520 }
04521
04522 kdDebug(5006) <<
"spelling: new SpellingFilter with prefix=\"" << quotePrefix <<
"\"" << endl;
04523
QTextEdit plaintext;
04524 plaintext.setText(text());
04525 plaintext.setTextFormat(Qt::PlainText);
04526 mSpellingFilter =
new SpellingFilter(plaintext.text(), quotePrefix, SpellingFilter::FilterUrls,
04527 SpellingFilter::FilterEmailAddresses);
04528
04529 mKSpell->check(mSpellingFilter->filteredText());
04530 }
04531
else if( mComposer )
04532 mKSpell->check( mComposer->sujectLineWidget()->text());
04533 }
04534
04535
04536
void KMEdit::slotSpellResult(
const QString &s)
04537 {
04538
if( !mSpellLineEdit)
04539 spellcheck_stop();
04540
04541
int dlgResult = mKSpell->dlgResult();
04542
if ( dlgResult == KS_CANCEL )
04543 {
04544
if( mSpellLineEdit)
04545 {
04546
04547 mSpellLineEdit =
false;
04548 QString tmpText( s );
04549 tmpText = tmpText.remove(
'\n');
04550
04551
if( tmpText != mComposer->sujectLineWidget()->text() )
04552 mComposer->sujectLineWidget()->setText( tmpText );
04553 }
04554
else
04555 {
04556 setModified(
true);
04557 }
04558 }
04559 mKSpell->cleanUp();
04560 KDictSpellingHighlighter::dictionaryChanged();
04561
04562 emit spellcheck_done( dlgResult );
04563 }
04564
04565
04566
void KMEdit::slotSpellDone()
04567 {
04568 kdDebug(5006)<<
" void KMEdit::slotSpellDone()\n";
04569 KSpell::spellStatus status = mKSpell->status();
04570
delete mKSpell;
04571 mKSpell = 0;
04572
04573 kdDebug(5006) <<
"spelling: delete SpellingFilter" << endl;
04574
delete mSpellingFilter;
04575 mSpellingFilter = 0;
04576 mComposer->sujectLineWidget()->deselect();
04577
if (status == KSpell::Error)
04578 {
04579 KMessageBox::sorry( topLevelWidget(),
04580 i18n(
"ISpell/Aspell could not be started. Please "
04581
"make sure you have ISpell or Aspell properly "
04582
"configured and in your PATH.") );
04583 emit spellcheck_done( KS_CANCEL );
04584 }
04585
else if (status == KSpell::Crashed)
04586 {
04587 spellcheck_stop();
04588 KMessageBox::sorry( topLevelWidget(),
04589 i18n(
"ISpell/Aspell seems to have crashed.") );
04590 emit spellcheck_done( KS_CANCEL );
04591 }
04592
else
04593 {
04594
if( mSpellLineEdit )
04595 spellcheck();
04596
else if( !mComposer->subjectTextWasSpellChecked() && status == KSpell::FinishedNoMisspellingsEncountered )
04597 KMessageBox::information( topLevelWidget(),
04598 i18n(
"No misspellings encountered.") );
04599 }
04600 }