10 #define REALLY_WANT_KMCOMPOSEWIN_H 11 #include "kmcomposewin.h" 12 #undef REALLY_WANT_KMCOMPOSEWIN_H 15 #include "kmlineeditspell.h" 16 #include "kmatmlistview.h" 18 #include "kmmainwin.h" 19 #include "kmreadermainwin.h" 20 #include "messagesender.h" 21 #include "kmmsgpartdlg.h" 22 #include <kpgpblock.h> 23 #include <kaddrbook.h> 24 #include "kmaddrbook.h" 25 #include "kmmsgdict.h" 26 #include "kmfolderimap.h" 27 #include "kmfoldermgr.h" 28 #include "kmfoldercombobox.h" 29 #include "kmtransport.h" 30 #include "kmcommands.h" 31 #include "kcursorsaver.h" 33 #include "encodingdetector.h" 34 #include "attachmentlistview.h" 35 #include "transportmanager.h" 36 using KMail::AttachmentListView;
37 #include "dictionarycombobox.h" 39 #include "addressesdialog.h" 40 using KPIM::AddressesDialog;
41 #include "addresseeemailselection.h" 42 using KPIM::AddresseeEmailSelection;
43 using KPIM::AddresseeSelectorDialog;
44 #include <maillistdrag.h> 45 using KPIM::MailListDrag;
46 #include "recentaddresses.h" 47 using TDERecentAddress::RecentAddresses;
48 #include "kleo_util.h" 50 #include "recipientseditor.h" 51 #include "editorwatcher.h" 53 #include "attachmentcollector.h" 54 #include "objecttreeparser.h" 56 #include "kmfoldermaildir.h" 58 #include <libkpimidentities/identitymanager.h> 59 #include <libkpimidentities/identitycombo.h> 60 #include <libkpimidentities/identity.h> 61 #include <libtdepim/tdefileio.h> 62 #include <libemailfunctions/email.h> 63 #include <kleo/cryptobackendfactory.h> 64 #include <kleo/exportjob.h> 65 #include <kleo/specialjob.h> 66 #include <ui/progressdialog.h> 67 #include <ui/keyselectiondialog.h> 69 #include <gpgmepp/context.h> 70 #include <gpgmepp/key.h> 72 #include <tdeio/netaccess.h> 74 #include "tdelistboxdialog.h" 76 #include "messagecomposer.h" 77 #include "chiasmuskeyselector.h" 79 #include <kcharsets.h> 80 #include <tdecompletionbox.h> 82 #include <kcombobox.h> 83 #include <tdestdaccel.h> 84 #include <tdepopupmenu.h> 85 #include <kedittoolbar.h> 86 #include <kkeydialog.h> 88 #include <tdefiledialog.h> 90 #include <kinputdialog.h> 91 #include <tdemessagebox.h> 93 #include <tdeio/scheduler.h> 94 #include <tdetempfile.h> 95 #include <tdelocale.h> 96 #include <tdeapplication.h> 97 #include <kstatusbar.h> 98 #include <tdeaction.h> 99 #include <kstdaction.h> 100 #include <kdirwatch.h> 101 #include <kstdguiitem.h> 102 #include <kiconloader.h> 103 #include <kpushbutton.h> 104 #include <kuserprofile.h> 106 #include <ktempdir.h> 107 #include <kstandarddirs.h> 109 #include "globalsettings.h" 110 #include "replyphrases.h" 112 #include <tdespell.h> 113 #include <tdespelldlg.h> 114 #include <spellingfilter.h> 115 #include <ksyntaxhighlighter.h> 116 #include <kcolordialog.h> 118 #include <ksavefile.h> 120 #include <tqtabdialog.h> 121 #include <tqregexp.h> 122 #include <tqbuffer.h> 123 #include <tqtooltip.h> 124 #include <tqtextcodec.h> 125 #include <tqheader.h> 126 #include <tqwhatsthis.h> 127 #include <tqfontdatabase.h> 129 #include <mimelib/mimepp.h> 134 #include <sys/stat.h> 135 #include <sys/types.h> 142 #include "kmcomposewin.moc" 144 #include "snippetwidget.h" 146 KMail::Composer * KMail::makeComposer(
KMMessage * msg, uint identitiy ) {
147 return KMComposeWin::create( msg, identitiy );
150 KMail::Composer * KMComposeWin::create(
KMMessage * msg, uint identitiy ) {
151 return new KMComposeWin( msg, identitiy );
155 KMComposeWin::KMComposeWin(
KMMessage *aMsg, uint
id )
157 mSpellCheckInProgress( false ),
159 mAtmModified( false ),
163 mSigningAndEncryptionExplicitlyDisabled( false ),
165 mUseHTMLEditor( false ),
167 mAttachPK( 0 ), mAttachMPK( 0 ),
168 mAttachRemoveAction( 0 ), mAttachSaveAction( 0 ), mAttachPropertiesAction( 0 ),
169 mAppendSignatureAction( 0 ), mPrependSignatureAction( 0 ), mInsertSignatureAction( 0 ),
170 mSignAction( 0 ), mEncryptAction( 0 ), mRequestMDNAction( 0 ),
171 mUrgentAction( 0 ), mAllFieldsAction( 0 ), mFromAction( 0 ),
172 mReplyToAction( 0 ), mToAction( 0 ), mCcAction( 0 ), mBccAction( 0 ),
174 mIdentityAction( 0 ), mTransportAction( 0 ), mFccAction( 0 ),
175 mWordWrapAction( 0 ), mFixedFontAction( 0 ), mAutoSpellCheckingAction( 0 ),
176 mDictionaryAction( 0 ), mSnippetAction( 0 ),
177 mEncodingAction( 0 ),
178 mCryptoModuleAction( 0 ),
179 mEncryptChiasmusAction( 0 ),
180 mEncryptWithChiasmus( false ),
183 mAutoSaveTimer( 0 ), mLastAutoSaveErrno( 0 ),
184 mSignatureStateIndicator( 0 ), mEncryptionStateIndicator( 0 ),
185 mPreserveUserCursorPosition( false ),
186 mPreventFccOverwrite( false ),
187 mCheckForRecipients( true ),
188 mCheckForForgottenAttachments( true ),
189 mIgnoreStickyFields( false )
191 mClassicalRecipients = GlobalSettings::self()->recipientsEditorType() ==
192 GlobalSettings::EnumRecipientsEditorType::Classic;
194 mSubjectTextWasSpellChecked =
false;
195 if (kmkernel->xmlGuiInstance())
196 setInstance( kmkernel->xmlGuiInstance() );
197 mMainWidget =
new TQWidget(
this);
199 mHeadersToEditorSplitter =
new TQSplitter( Qt::Vertical, mMainWidget,
"mHeadersToEditorSplitter" );
200 mHeadersToEditorSplitter->setChildrenCollapsible(
false );
201 mHeadersArea =
new TQWidget( mHeadersToEditorSplitter );
202 mHeadersArea->setSizePolicy( mHeadersToEditorSplitter->sizePolicy().horData(), TQSizePolicy::Maximum );
203 TQVBoxLayout *v =
new TQVBoxLayout( mMainWidget );
204 v->addWidget( mHeadersToEditorSplitter );
205 mIdentity =
new KPIM::IdentityCombo(kmkernel->identityManager(), mHeadersArea);
206 TQToolTip::add( mIdentity,
207 i18n(
"Select an identity for this message" ) );
210 TQToolTip::add( mDictionaryCombo,
211 i18n(
"Select the dictionary to use when spell-checking this message" ) );
213 mFcc =
new KMFolderComboBox(mHeadersArea);
214 mFcc->showOutboxFolder(
false );
215 TQToolTip::add( mFcc,
216 i18n(
"Select the sent-mail folder where a copy of this message will be saved" ) );
218 mTransport =
new TQComboBox(
true, mHeadersArea);
219 TQToolTip::add( mTransport,
220 i18n(
"Select the outgoing account to use for sending this message" ) );
222 mEdtFrom =
new KMLineEdit(
false,mHeadersArea,
"fromLine");
223 TQToolTip::add( mEdtFrom,
224 i18n(
"Set the \"From:\" email address for this message" ) );
226 mEdtReplyTo =
new KMLineEdit(
true,mHeadersArea,
"replyToLine");
227 TQToolTip::add( mEdtReplyTo,
228 i18n(
"Set the \"Reply-To:\" email address for this message" ) );
229 connect(mEdtReplyTo,TQT_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
230 TQT_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
232 if ( mClassicalRecipients ) {
233 mRecipientsEditor = 0;
235 mEdtTo =
new KMLineEdit(
true,mHeadersArea,
"toLine");
236 mEdtCc =
new KMLineEdit(
true,mHeadersArea,
"ccLine");
237 mEdtBcc =
new KMLineEdit(
true,mHeadersArea,
"bccLine");
239 mLblTo =
new TQLabel(mHeadersArea);
240 mLblCc =
new TQLabel(mHeadersArea);
241 mLblBcc =
new TQLabel(mHeadersArea);
243 mBtnTo =
new TQPushButton(
"...",mHeadersArea);
244 mBtnCc =
new TQPushButton(
"...",mHeadersArea);
245 mBtnBcc =
new TQPushButton(
"...",mHeadersArea);
248 TQString tip = i18n(
"Select email address(es)");
249 TQToolTip::add( mBtnTo, tip );
250 TQToolTip::add( mBtnCc, tip );
251 TQToolTip::add( mBtnBcc, tip );
253 mBtnTo->setFocusPolicy(TQ_NoFocus);
254 mBtnCc->setFocusPolicy(TQ_NoFocus);
255 mBtnBcc->setFocusPolicy(TQ_NoFocus);
258 connect(mBtnTo,TQT_SIGNAL(clicked()),TQT_SLOT(slotAddrBookTo()));
259 connect(mBtnCc,TQT_SIGNAL(clicked()),TQT_SLOT(slotAddrBookTo()));
260 connect(mBtnBcc,TQT_SIGNAL(clicked()),TQT_SLOT(slotAddrBookTo()));
263 connect(mEdtTo,TQT_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
264 TQT_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
265 connect(mEdtCc,TQT_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
266 TQT_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
267 connect(mEdtBcc,TQT_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
268 TQT_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
285 mRecipientsEditor =
new RecipientsEditor( mHeadersArea );
286 connect( mRecipientsEditor,
287 TQT_SIGNAL( completionModeChanged( TDEGlobalSettings::Completion ) ),
288 TQT_SLOT( slotCompletionModeChanged( TDEGlobalSettings::Completion ) ) );
289 connect( mRecipientsEditor, TQT_SIGNAL(sizeHintChanged()), TQT_SLOT(recipientEditorSizeHintChanged()) );
291 mRecipientsEditor->setFocus();
293 mEdtSubject =
new KMLineEditSpell(
false,mHeadersArea,
"subjectLine");
294 TQToolTip::add( mEdtSubject,
295 i18n(
"Set a subject for this message" ) );
297 mLblIdentity =
new TQLabel( i18n(
"&Identity:"), mHeadersArea );
298 mDictionaryLabel =
new TQLabel( i18n(
"&Dictionary:"), mHeadersArea );
299 mLblFcc =
new TQLabel( i18n(
"&Sent-Mail folder:"), mHeadersArea );
300 mLblTransport =
new TQLabel( i18n(
"&Mail transport:"), mHeadersArea );
301 mLblFrom =
new TQLabel( i18n(
"sender address field",
"&From:"), mHeadersArea );
302 mLblReplyTo =
new TQLabel( i18n(
"&Reply to:"), mHeadersArea );
303 mLblSubject =
new TQLabel( i18n(
"S&ubject:"), mHeadersArea );
305 TQString sticky = i18n(
"Sticky");
306 mBtnIdentity =
new TQCheckBox(sticky,mHeadersArea);
307 TQToolTip::add( mBtnIdentity,
308 i18n(
"Use the selected value as your identity for future messages" ) );
309 mBtnFcc =
new TQCheckBox(sticky,mHeadersArea);
310 TQToolTip::add( mBtnFcc,
311 i18n(
"Use the selected value as your sent-mail folder for future messages" ) );
312 mBtnTransport =
new TQCheckBox(sticky,mHeadersArea);
313 TQToolTip::add( mBtnTransport,
314 i18n(
"Use the selected value as your outgoing account for future messages" ) );
315 mBtnDictionary =
new TQCheckBox( sticky, mHeadersArea );
316 TQToolTip::add( mBtnDictionary,
317 i18n(
"Use the selected value as your dictionary for future messages" ) );
320 mHtmlMarkup = GlobalSettings::self()->useHtmlMarkup();
321 mShowHeaders = GlobalSettings::self()->headers();
325 mAtmList.setAutoDelete(
true);
326 mAtmTempList.setAutoDelete(
true);
327 mAtmModified =
false;
328 mAutoDeleteMsg =
false;
331 mFixedFontAction = 0;
334 mSplitter =
new TQSplitter( Qt::Vertical, mHeadersToEditorSplitter,
"mSplitter" );
335 mSplitter->setChildrenCollapsible(
false );
336 mSnippetSplitter =
new TQSplitter( Qt::Horizontal, mSplitter,
"mSnippetSplitter");
337 mSnippetSplitter->setChildrenCollapsible(
false );
339 TQWidget *editorAndCryptoStateIndicators =
new TQWidget( mSnippetSplitter );
340 TQVBoxLayout *vbox =
new TQVBoxLayout( editorAndCryptoStateIndicators );
341 TQHBoxLayout *hbox =
new TQHBoxLayout( vbox );
343 mSignatureStateIndicator =
new TQLabel( editorAndCryptoStateIndicators );
344 mSignatureStateIndicator->setAlignment( TQt::AlignHCenter );
345 hbox->addWidget( mSignatureStateIndicator );
347 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
348 TQPalette p( mSignatureStateIndicator->palette() );
350 TQColor defaultSignedColor( 0x40, 0xFF, 0x40 );
351 TQColor defaultEncryptedColor( 0x00, 0x80, 0xFF );
352 p.setColor( TQColorGroup::Background, reader.readColorEntry(
"PGPMessageOkKeyOk", &defaultSignedColor ) );
353 mSignatureStateIndicator->setPalette( p );
355 mEncryptionStateIndicator =
new TQLabel( editorAndCryptoStateIndicators );
356 mEncryptionStateIndicator->setAlignment( TQt::AlignHCenter );
357 hbox->addWidget( mEncryptionStateIndicator );
358 p.setColor( TQColorGroup::Background, reader.readColorEntry(
"PGPMessageEncr" , &defaultEncryptedColor ) );
359 mEncryptionStateIndicator->setPalette( p );
362 mEditor =
new KMEdit( editorAndCryptoStateIndicators,
this, mDictionaryCombo->spellConfig() );
363 vbox->addWidget( mEditor );
365 mSnippetWidget =
new SnippetWidget( mEditor, actionCollection(), mSnippetSplitter );
366 mSnippetWidget->setShown( GlobalSettings::self()->showSnippetManager() );
369 mSplitter->setOpaqueResize(
true );
371 mEditor->initializeAutoSpellChecking();
372 mEditor->setTextFormat(TQt::PlainText);
373 mEditor->setAcceptDrops(
true );
375 TQWhatsThis::add( mBtnIdentity,
376 GlobalSettings::self()->stickyIdentityItem()->whatsThis() );
377 TQWhatsThis::add( mBtnFcc,
378 GlobalSettings::self()->stickyFccItem()->whatsThis() );
379 TQWhatsThis::add( mBtnTransport,
380 GlobalSettings::self()->stickyTransportItem()->whatsThis() );
381 TQWhatsThis::add( mBtnTransport,
382 GlobalSettings::self()->stickyDictionaryItem()->whatsThis() );
384 mSpellCheckInProgress=
false;
386 setCaption( i18n(
"Composer") );
387 setMinimumSize(200,200);
389 mBtnIdentity->setFocusPolicy(TQ_NoFocus);
390 mBtnFcc->setFocusPolicy(TQ_NoFocus);
391 mBtnTransport->setFocusPolicy(TQ_NoFocus);
392 mBtnDictionary->setFocusPolicy( TQ_NoFocus );
394 mAtmListView =
new AttachmentListView(
this, mSplitter,
395 "attachment list view" );
396 mAtmListView->setSelectionMode( TQListView::Extended );
397 mAtmListView->addColumn( i18n(
"Name"), 200 );
398 mAtmListView->addColumn( i18n(
"Size"), 80 );
399 mAtmListView->addColumn( i18n(
"Encoding"), 120 );
400 int atmColType = mAtmListView->addColumn( i18n(
"Type"), 120 );
402 mAtmListView->header()->setStretchEnabled(
true, atmColType );
403 mAtmEncryptColWidth = 80;
404 mAtmSignColWidth = 80;
405 mAtmCompressColWidth = 100;
406 mAtmColCompress = mAtmListView->addColumn( i18n(
"Compress"),
407 mAtmCompressColWidth );
408 mAtmColEncrypt = mAtmListView->addColumn( i18n(
"Encrypt"),
409 mAtmEncryptColWidth );
410 mAtmColSign = mAtmListView->addColumn( i18n(
"Sign"),
412 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
413 mAtmListView->setColumnWidth( mAtmColSign, 0 );
414 mAtmListView->setAllColumnsShowFocus(
true );
416 connect( mAtmListView,
417 TQT_SIGNAL( doubleClicked( TQListViewItem* ) ),
418 TQT_SLOT( slotAttachEdit() ) );
419 connect( mAtmListView,
420 TQT_SIGNAL( rightButtonPressed( TQListViewItem*,
const TQPoint&,
int ) ),
421 TQT_SLOT( slotAttachPopupMenu( TQListViewItem*,
const TQPoint&,
int ) ) );
422 connect( mAtmListView,
423 TQT_SIGNAL( selectionChanged() ),
424 TQT_SLOT( slotUpdateAttachActions() ) );
425 connect( mAtmListView,
426 TQT_SIGNAL( attachmentDeleted() ),
427 TQT_SLOT( slotAttachRemove() ) );
428 connect( mAtmListView,
429 TQT_SIGNAL( dragStarted() ),
430 TQT_SLOT( slotAttachmentDragStarted() ) );
437 slotUpdateSignatureAndEncrypionStateIndicators();
439 applyMainWindowSettings(KMKernel::config(),
"Composer");
441 connect( mEdtSubject, TQT_SIGNAL( subjectTextSpellChecked() ),
442 TQT_SLOT( slotSubjectTextSpellChecked() ) );
443 connect(mEdtSubject,TQT_SIGNAL(textChanged(
const TQString&)),
444 TQT_SLOT(slotUpdWinTitle(
const TQString&)));
445 connect(mIdentity,TQT_SIGNAL(identityChanged(uint)),
446 TQT_SLOT(slotIdentityChanged(uint)));
447 connect( kmkernel->identityManager(), TQT_SIGNAL(changed(uint)),
448 TQT_SLOT(slotIdentityChanged(uint)));
450 connect(mEdtFrom,TQT_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
451 TQT_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
452 connect(kmkernel->folderMgr(),TQT_SIGNAL(folderRemoved(
KMFolder*)),
453 TQT_SLOT(slotFolderRemoved(
KMFolder*)));
454 connect(kmkernel->imapFolderMgr(),TQT_SIGNAL(folderRemoved(
KMFolder*)),
455 TQT_SLOT(slotFolderRemoved(
KMFolder*)));
456 connect(kmkernel->dimapFolderMgr(),TQT_SIGNAL(folderRemoved(
KMFolder*)),
457 TQT_SLOT(slotFolderRemoved(
KMFolder*)));
458 connect( kmkernel, TQT_SIGNAL( configChanged() ),
459 TQT_TQOBJECT(
this), TQT_SLOT( slotConfigChanged() ) );
461 connect (mEditor, TQT_SIGNAL (spellcheck_done(
int)),
462 this, TQT_SLOT (slotSpellcheckDone (
int)));
463 connect (mEditor, TQT_SIGNAL( attachPNGImageData(
const TQByteArray &) ),
464 this, TQT_SLOT ( slotAttachPNGImageData(
const TQByteArray &) ) );
465 connect (mEditor, TQT_SIGNAL( focusChanged(
bool) ),
466 this, TQT_SLOT (editorFocusChanged(
bool)) );
468 mMainWidget->resize(480,510);
469 setCentralWidget(mMainWidget);
472 if ( !mClassicalRecipients ) {
478 if ( GlobalSettings::self()->useExternalEditor() ) {
479 mEditor->setUseExternalEditor(
true);
480 mEditor->setExternalEditorPath( GlobalSettings::self()->externalEditor() );
484 slotUpdateSignatureActions();
488 fontChanged( mEditor->currentFont() );
494 KMComposeWin::~KMComposeWin()
499 mAutoDeleteMsg =
false;
500 mFolder->addMsg(mMsg);
502 mFolder->unGetMsg( mFolder->count() - 1 );
504 if (mAutoDeleteMsg) {
508 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.begin();
509 while ( it != mMapAtmLoadData.end() )
511 TDEIO::Job *job = it.key();
512 mMapAtmLoadData.remove( it );
514 it = mMapAtmLoadData.begin();
516 deleteAll( mComposedMessages );
518 for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) {
523 void KMComposeWin::setAutoDeleteWindow(
bool f )
526 setWFlags( getWFlags() | WDestructiveClose );
528 setWFlags( getWFlags() & ~WDestructiveClose );
532 void KMComposeWin::send(
int how)
548 void KMComposeWin::addAttachmentsAndSend(
const KURL::List &urls,
const TQString &,
int how)
555 mAttachFilesSend = how;
556 mAttachFilesPending = urls;
557 connect(
this, TQT_SIGNAL(attachmentAdded(
const KURL&,
bool)), TQT_SLOT(slotAttachedFile(
const KURL&)));
558 for( KURL::List::ConstIterator itr = urls.begin(); itr != urls.end(); ++itr ) {
559 if (!addAttach( *itr ))
560 mAttachFilesPending.remove(mAttachFilesPending.find(*itr));
563 if (mAttachFilesPending.isEmpty() && mAttachFilesSend == how)
565 send(mAttachFilesSend);
566 mAttachFilesSend = -1;
570 void KMComposeWin::slotAttachedFile(
const KURL &url)
572 if (mAttachFilesPending.isEmpty())
574 mAttachFilesPending.remove(mAttachFilesPending.find(url));
575 if (mAttachFilesPending.isEmpty())
577 send(mAttachFilesSend);
578 mAttachFilesSend = -1;
583 void KMComposeWin::addAttachment(KURL url,TQString )
589 void KMComposeWin::addAttachment(
const TQString &name,
591 const TQByteArray &data,
592 const TQCString &type,
593 const TQCString &subType,
594 const TQCString ¶mAttr,
595 const TQString ¶mValue,
596 const TQCString &contDisp)
598 if (!data.isEmpty()) {
599 KMMessagePart *msgPart =
new KMMessagePart;
600 msgPart->setName(name);
601 if( type ==
"message" && subType ==
"rfc822" ) {
602 msgPart->setMessageBody( data );
604 TQValueList<int> dummy;
605 msgPart->setBodyAndGuessCte(data, dummy,
606 kmkernel->msgSender()->sendQuotedPrintable());
608 msgPart->setTypeStr(type);
609 msgPart->setSubtypeStr(subType);
610 msgPart->setParameter(paramAttr,paramValue);
611 msgPart->setContentDisposition(contDisp);
617 void KMComposeWin::slotAttachPNGImageData(
const TQByteArray &image)
621 TQString attName = KInputDialog::getText(
"KMail", i18n(
"Name of the attachment:"), TQString(), &ok,
this );
625 if ( !attName.lower().endsWith(
".png") ) attName +=
".png";
627 addAttachment( attName,
"base64", image,
"image",
"png", TQCString(), TQString(), TQCString() );
631 void KMComposeWin::setBody(TQString body)
633 mEditor->setText(body);
637 bool KMComposeWin::event(TQEvent *e)
639 if (e->type() == TQEvent::ApplicationPaletteChange)
643 return KMail::Composer::event(e);
648 void KMComposeWin::readColorConfig(
void)
650 if ( GlobalSettings::self()->useDefaultColors() ) {
651 mForeColor = TQColor(kapp->palette().active().text());
652 mBackColor = TQColor(kapp->palette().active().base());
654 mForeColor = GlobalSettings::self()->foregroundColor();
655 mBackColor = GlobalSettings::self()->backgroundColor();
659 mPalette = kapp->palette();
660 TQColorGroup cgrp = mPalette.active();
661 cgrp.setColor( TQColorGroup::Base, mBackColor);
662 cgrp.setColor( TQColorGroup::Text, mForeColor);
663 mPalette.setDisabled(cgrp);
664 mPalette.setActive(cgrp);
665 mPalette.setInactive(cgrp);
667 mEdtFrom->setPalette(mPalette);
668 mEdtReplyTo->setPalette(mPalette);
669 if ( mClassicalRecipients ) {
670 mEdtTo->setPalette(mPalette);
671 mEdtCc->setPalette(mPalette);
672 mEdtBcc->setPalette(mPalette);
674 mEdtSubject->setPalette(mPalette);
675 mTransport->setPalette(mPalette);
676 mEditor->setPalette(mPalette);
677 mFcc->setPalette(mPalette);
681 void KMComposeWin::readConfig(
bool reload )
684 mBtnIdentity->setChecked( GlobalSettings::self()->stickyIdentity() );
685 if (mBtnIdentity->isChecked()) {
686 mId = (GlobalSettings::self()->previousIdentity()!=0) ?
687 GlobalSettings::self()->previousIdentity() : mId;
689 mBtnFcc->setChecked( GlobalSettings::self()->stickyFcc() );
690 mBtnTransport->setChecked( GlobalSettings::self()->stickyTransport() );
691 mBtnDictionary->setChecked( GlobalSettings::self()->stickyDictionary() );
692 TQStringList transportHistory = GlobalSettings::self()->transportHistory();
693 TQString currentTransport = GlobalSettings::self()->currentTransport();
695 mEdtFrom->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
696 mEdtReplyTo->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
697 if ( mClassicalRecipients ) {
698 mEdtTo->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
699 mEdtCc->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
700 mEdtBcc->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
703 mRecipientsEditor->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
707 if ( GlobalSettings::self()->useDefaultFonts() ) {
708 mBodyFont = TDEGlobalSettings::generalFont();
709 mFixedFont = TDEGlobalSettings::fixedFont();
711 mBodyFont = GlobalSettings::self()->composerFont();
712 mFixedFont = GlobalSettings::self()->fixedFont();
716 mEdtFrom->setFont(mBodyFont);
717 mEdtReplyTo->setFont(mBodyFont);
718 if ( mClassicalRecipients ) {
719 mEdtTo->setFont(mBodyFont);
720 mEdtCc->setFont(mBodyFont);
721 mEdtBcc->setFont(mBodyFont);
723 mEdtSubject->setFont(mBodyFont);
726 TQSize siz = GlobalSettings::self()->composerSize();
727 if (siz.width() < 200) siz.setWidth(200);
728 if (siz.height() < 200) siz.setHeight(200);
731 if ( !GlobalSettings::self()->snippetSplitterPosition().isEmpty() ) {
732 mSnippetSplitter->setSizes( GlobalSettings::self()->snippetSplitterPosition() );
734 TQValueList<int> defaults;
735 defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
736 mSnippetSplitter->setSizes( defaults );
740 mIdentity->setCurrentIdentity( mId );
742 kdDebug(5006) <<
"KMComposeWin::readConfig. " << mIdentity->currentIdentityName() << endl;
743 const KPIM::Identity & ident =
744 kmkernel->identityManager()->identityForUoid( mIdentity->currentIdentity() );
747 mTransport->insertStringList( KMTransportInfo::availableTransports() );
748 while ( transportHistory.count() > (uint)GlobalSettings::self()->maxTransportEntries() )
749 transportHistory.remove( transportHistory.last() );
750 mTransport->insertStringList( transportHistory );
751 mTransport->setCurrentText( GlobalSettings::self()->defaultTransport() );
752 if ( mBtnTransport->isChecked() ) {
753 setTransport( currentTransport );
756 if ( mBtnDictionary->isChecked() ) {
757 mDictionaryCombo->setCurrentByDictionaryName( GlobalSettings::self()->previousDictionary() );
759 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
762 TQString fccName =
"";
763 if ( mBtnFcc->isChecked() ) {
764 fccName = GlobalSettings::self()->previousFcc();
765 }
else if ( !ident.fcc().isEmpty() ) {
766 fccName = ident.fcc();
773 void KMComposeWin::writeConfig(
void)
775 GlobalSettings::self()->setHeaders( mShowHeaders );
776 GlobalSettings::self()->setStickyFcc( mBtnFcc->isChecked() );
777 if ( !mIgnoreStickyFields ) {
778 GlobalSettings::self()->setCurrentTransport( mTransport->currentText() );
779 GlobalSettings::self()->setStickyTransport( mBtnTransport->isChecked() );
780 GlobalSettings::self()->setStickyDictionary( mBtnDictionary->isChecked() );
781 GlobalSettings::self()->setStickyIdentity( mBtnIdentity->isChecked() );
782 GlobalSettings::self()->setPreviousIdentity( mIdentity->currentIdentity() );
784 GlobalSettings::self()->setPreviousFcc( mFcc->getFolder()->idString() );
785 GlobalSettings::self()->setPreviousDictionary( mDictionaryCombo->currentDictionaryName() );
786 GlobalSettings::self()->setAutoSpellChecking(
787 mAutoSpellCheckingAction->isChecked() );
788 TQStringList transportHistory = GlobalSettings::self()->transportHistory();
789 transportHistory.remove(mTransport->currentText());
790 if (KMTransportInfo::availableTransports().findIndex(mTransport
791 ->currentText()) == -1) {
792 transportHistory.prepend(mTransport->currentText());
794 GlobalSettings::self()->setTransportHistory( transportHistory );
795 GlobalSettings::self()->setUseFixedFont( mFixedFontAction->isChecked() );
796 GlobalSettings::self()->setUseHtmlMarkup( mHtmlMarkup );
797 GlobalSettings::self()->setComposerSize( size() );
798 GlobalSettings::self()->setShowSnippetManager( mSnippetAction->isChecked() );
800 TDEConfigGroupSaver saver( KMKernel::config(),
"Geometry" );
801 saveMainWindowSettings( KMKernel::config(),
"Composer" );
802 GlobalSettings::setSnippetSplitterPosition( mSnippetSplitter->sizes() );
805 GlobalSettings::self()->writeConfig();
809 void KMComposeWin::autoSaveMessage()
811 kdDebug(5006) << k_funcinfo << endl;
812 if ( !mMsg || mComposer || mAutoSaveFilename.isEmpty() )
814 kdDebug(5006) << k_funcinfo <<
"autosaving message" << endl;
816 if ( mAutoSaveTimer )
817 mAutoSaveTimer->stop();
819 connect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
820 TQT_TQOBJECT(
this), TQT_SLOT( slotContinueAutoSave() ) );
824 applyChanges(
true,
true );
829 void KMComposeWin::slotContinueAutoSave()
831 disconnect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
832 TQT_TQOBJECT(
this), TQT_SLOT( slotContinueAutoSave() ) );
835 if ( mComposedMessages.isEmpty() ) {
836 kdDebug(5006) <<
"Composing the message failed." << endl;
839 KMMessage *msg = mComposedMessages.first();
843 kdDebug(5006) << k_funcinfo <<
"opening autoSaveFile " << mAutoSaveFilename
845 const TQString filename =
847 KSaveFile autoSaveFile( filename, 0600 );
848 int status = autoSaveFile.status();
849 kdDebug(5006) << k_funcinfo <<
"autoSaveFile.status() = " << status << endl;
851 kdDebug(5006) <<
"autosaving message in " << filename << endl;
852 int fd = autoSaveFile.handle();
854 if ( ::write( fd, msgStr.data(), msgStr.length() ) == -1 )
858 kdDebug(5006) << k_funcinfo <<
"closing autoSaveFile" << endl;
859 autoSaveFile.close();
860 mLastAutoSaveErrno = 0;
863 kdDebug(5006) << k_funcinfo <<
"autosaving failed" << endl;
864 autoSaveFile.abort();
865 if ( status != mLastAutoSaveErrno ) {
867 KMessageBox::queuedMessageBox( 0, KMessageBox::Sorry,
868 i18n(
"Autosaving the message as %1 " 871 .arg( filename, strerror( status ) ),
872 i18n(
"Autosaving Failed") );
873 mLastAutoSaveErrno = status;
877 if ( autoSaveInterval() > 0 )
882 void KMComposeWin::slotView(
void)
891 if (!TQT_TQOBJECT_CONST(sender())->isA(
"TDEToggleAction"))
893 TDEToggleAction *act = (TDEToggleAction *) sender();
895 if (act == mAllFieldsAction)
897 else if (act == mIdentityAction)
899 else if (act == mTransportAction)
901 else if (act == mFromAction)
903 else if (act == mReplyToAction)
905 else if (act == mToAction)
907 else if (act == mCcAction)
909 else if (act == mBccAction)
911 else if (act == mSubjectAction)
913 else if (act == mFccAction)
915 else if ( act == mDictionaryAction )
920 kdDebug(5006) <<
"Something is wrong (Oh, yeah?)" << endl;
927 if (!act->isChecked())
930 if (
id > 0) mShowHeaders = mShowHeaders & ~id;
931 else mShowHeaders = abs(mShowHeaders);
936 if (
id > 0) mShowHeaders |= id;
937 else mShowHeaders = -abs(mShowHeaders);
942 int KMComposeWin::calcColumnWidth(
int which,
long allShowing,
int width)
944 if ( (allShowing & which) == 0 )
948 if ( which == HDR_IDENTITY )
950 else if ( which == HDR_DICTIONARY )
951 w = mDictionaryLabel;
952 else if ( which == HDR_FCC )
954 else if ( which == HDR_TRANSPORT )
956 else if ( which == HDR_FROM )
958 else if ( which == HDR_REPLY_TO )
960 else if ( which == HDR_SUBJECT )
965 w->setBuddy( mEditor );
968 return TQMAX( width, w->sizeHint().width() );
971 void KMComposeWin::rethinkFields(
bool fromSlot)
974 int mask, row, numRows;
977 if (mShowHeaders < 0)
978 showHeaders = HDR_ALL;
980 showHeaders = mShowHeaders;
982 for (mask=1,mNumHeaders=0; mask<=showHeaders; mask<<=1)
983 if ((showHeaders&mask) != 0) mNumHeaders++;
985 numRows = mNumHeaders + 1;
989 mGrid =
new TQGridLayout( mHeadersArea, numRows, 3, KDialogBase::marginHint()/2, KDialogBase::spacingHint());
990 mGrid->setColStretch(0, 1);
991 mGrid->setColStretch(1, 100);
992 mGrid->setColStretch(2, 1);
993 mGrid->setRowStretch( mNumHeaders + 1, 100 );
996 kdDebug(5006) <<
"KMComposeWin::rethinkFields" << endl;
997 if (mRecipientsEditor)
998 mLabelWidth = mRecipientsEditor->setFirstColumnWidth( 0 );
999 mLabelWidth = calcColumnWidth( HDR_IDENTITY, showHeaders, mLabelWidth );
1000 mLabelWidth = calcColumnWidth( HDR_DICTIONARY, showHeaders, mLabelWidth );
1001 mLabelWidth = calcColumnWidth( HDR_FCC, showHeaders, mLabelWidth );
1002 mLabelWidth = calcColumnWidth( HDR_TRANSPORT, showHeaders, mLabelWidth );
1003 mLabelWidth = calcColumnWidth( HDR_FROM, showHeaders, mLabelWidth );
1004 mLabelWidth = calcColumnWidth( HDR_REPLY_TO, showHeaders, mLabelWidth );
1005 mLabelWidth = calcColumnWidth( HDR_SUBJECT, showHeaders, mLabelWidth );
1007 if (!fromSlot) mAllFieldsAction->setChecked(showHeaders==HDR_ALL);
1009 if (!fromSlot) mIdentityAction->setChecked(abs(mShowHeaders)&HDR_IDENTITY);
1010 rethinkHeaderLine(showHeaders,HDR_IDENTITY, row,
1011 mLblIdentity, mIdentity, mBtnIdentity);
1013 if (!fromSlot) mDictionaryAction->setChecked(abs(mShowHeaders)&HDR_DICTIONARY);
1014 rethinkHeaderLine(showHeaders,HDR_DICTIONARY, row,
1015 mDictionaryLabel, mDictionaryCombo, mBtnDictionary );
1017 if (!fromSlot) mFccAction->setChecked(abs(mShowHeaders)&HDR_FCC);
1018 rethinkHeaderLine(showHeaders,HDR_FCC, row,
1019 mLblFcc, mFcc, mBtnFcc);
1021 if (!fromSlot) mTransportAction->setChecked(abs(mShowHeaders)&HDR_TRANSPORT);
1022 rethinkHeaderLine(showHeaders,HDR_TRANSPORT, row,
1023 mLblTransport, mTransport, mBtnTransport);
1025 if (!fromSlot) mFromAction->setChecked(abs(mShowHeaders)&HDR_FROM);
1026 rethinkHeaderLine(showHeaders,HDR_FROM, row,
1027 mLblFrom, mEdtFrom );
1029 TQWidget *prevFocus = mEdtFrom;
1031 if (!fromSlot) mReplyToAction->setChecked(abs(mShowHeaders)&HDR_REPLY_TO);
1032 rethinkHeaderLine(showHeaders,HDR_REPLY_TO,row,
1033 mLblReplyTo, mEdtReplyTo, 0);
1034 if ( showHeaders & HDR_REPLY_TO ) {
1035 prevFocus = connectFocusMoving( prevFocus, mEdtReplyTo );
1038 if ( mClassicalRecipients ) {
1039 if (!fromSlot) mToAction->setChecked(abs(mShowHeaders)&HDR_TO);
1040 rethinkHeaderLine(showHeaders, HDR_TO, row,
1041 mLblTo, mEdtTo, mBtnTo,
1042 i18n(
"Primary Recipients"),
1043 i18n(
"<qt>The email addresses you put " 1044 "in this field receive a copy of the email.</qt>"));
1045 if ( showHeaders & HDR_TO ) {
1046 prevFocus = connectFocusMoving( prevFocus, mEdtTo );
1049 if (!fromSlot) mCcAction->setChecked(abs(mShowHeaders)&HDR_CC);
1050 rethinkHeaderLine(showHeaders, HDR_CC, row,
1051 mLblCc, mEdtCc, mBtnCc,
1052 i18n(
"Additional Recipients"),
1053 i18n(
"<qt>The email addresses you put " 1054 "in this field receive a copy of the email. " 1055 "Technically it is the same thing as putting all the " 1056 "addresses in the <b>To:</b> field but differs in " 1057 "that it usually symbolises the receiver of the " 1058 "Carbon Copy (CC) is a listener, not the main " 1059 "recipient.</qt>"));
1060 if ( showHeaders & HDR_CC ) {
1061 prevFocus = connectFocusMoving( prevFocus, mEdtCc );
1064 if (!fromSlot) mBccAction->setChecked(abs(mShowHeaders)&HDR_BCC);
1065 rethinkHeaderLine(showHeaders,HDR_BCC, row,
1066 mLblBcc, mEdtBcc, mBtnBcc,
1067 i18n(
"Hidden Recipients"),
1068 i18n(
"<qt>Essentially the same thing " 1069 "as the <b>Copy To:</b> field but differs in that " 1070 "all other recipients do not see who receives a " 1071 "blind copy.</qt>"));
1072 if ( showHeaders & HDR_BCC ) {
1073 prevFocus = connectFocusMoving( prevFocus, mEdtBcc );
1076 mGrid->addMultiCellWidget( mRecipientsEditor, row, row, 0, 2 );
1079 if ( showHeaders & HDR_REPLY_TO ) {
1080 connect( mEdtReplyTo, TQT_SIGNAL( focusDown() ), mRecipientsEditor,
1081 TQT_SLOT( setFocusTop() ) );
1083 connect( mEdtFrom, TQT_SIGNAL( focusDown() ), mRecipientsEditor,
1084 TQT_SLOT( setFocusTop() ) );
1086 if ( showHeaders & HDR_REPLY_TO ) {
1087 connect( mRecipientsEditor, TQT_SIGNAL( focusUp() ), mEdtReplyTo, TQT_SLOT( setFocus() ) );
1089 connect( mRecipientsEditor, TQT_SIGNAL( focusUp() ), mEdtFrom, TQT_SLOT( setFocus() ) );
1092 connect( mRecipientsEditor, TQT_SIGNAL( focusDown() ), mEdtSubject,
1093 TQT_SLOT( setFocus() ) );
1094 connect( mEdtSubject, TQT_SIGNAL( focusUp() ), mRecipientsEditor,
1095 TQT_SLOT( setFocusBottom() ) );
1097 prevFocus = mRecipientsEditor;
1099 if (!fromSlot) mSubjectAction->setChecked(abs(mShowHeaders)&HDR_SUBJECT);
1100 rethinkHeaderLine(showHeaders,HDR_SUBJECT, row,
1101 mLblSubject, mEdtSubject);
1102 connectFocusMoving( mEdtSubject, mEditor );
1104 assert(row<=mNumHeaders);
1107 if( !mAtmList.isEmpty() )
1108 mAtmListView->show();
1110 mAtmListView->hide();
1111 resize(this->size());
1114 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
1116 mHeadersArea->show();
1118 slotUpdateAttachActions();
1119 mIdentityAction->setEnabled(!mAllFieldsAction->isChecked());
1120 mDictionaryAction->setEnabled( !mAllFieldsAction->isChecked() );
1121 mTransportAction->setEnabled(!mAllFieldsAction->isChecked());
1122 mFromAction->setEnabled(!mAllFieldsAction->isChecked());
1123 if ( mReplyToAction ) mReplyToAction->setEnabled(!mAllFieldsAction->isChecked());
1124 if ( mToAction ) mToAction->setEnabled(!mAllFieldsAction->isChecked());
1125 if ( mCcAction ) mCcAction->setEnabled(!mAllFieldsAction->isChecked());
1126 if ( mBccAction ) mBccAction->setEnabled(!mAllFieldsAction->isChecked());
1127 mFccAction->setEnabled(!mAllFieldsAction->isChecked());
1128 mSubjectAction->setEnabled(!mAllFieldsAction->isChecked());
1129 if (mRecipientsEditor)
1130 mRecipientsEditor->setFirstColumnWidth( mLabelWidth );
1133 TQWidget *KMComposeWin::connectFocusMoving( TQWidget *prev, TQWidget *next )
1135 connect( prev, TQT_SIGNAL( focusDown() ), next, TQT_SLOT( setFocus() ) );
1136 connect( next, TQT_SIGNAL( focusUp() ), prev, TQT_SLOT( setFocus() ) );
1142 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
1144 TQLineEdit* aEdt, TQPushButton* aBtn,
1145 const TQString &toolTip,
const TQString &whatsThis )
1149 if ( !toolTip.isEmpty() )
1150 TQToolTip::add( aLbl, toolTip );
1151 if ( !whatsThis.isEmpty() )
1152 TQWhatsThis::add( aLbl, whatsThis );
1153 aLbl->setFixedWidth( mLabelWidth );
1154 aLbl->setBuddy(aEdt);
1155 mGrid->addWidget(aLbl, aRow, 0);
1156 aEdt->setBackgroundColor( mBackColor );
1160 mGrid->addWidget(aEdt, aRow, 1);
1162 mGrid->addWidget(aBtn, aRow, 2);
1165 mGrid->addMultiCellWidget(aEdt, aRow, aRow, 1, 2 );
1173 if (aBtn) aBtn->hide();
1178 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
1180 TQComboBox* aCbx, TQCheckBox* aChk)
1185 aLbl->resize((
int)aLbl->sizeHint().width(),aLbl->sizeHint().height() + 6);
1186 aLbl->setMinimumSize(aLbl->size());
1188 aLbl->setBuddy(aCbx);
1189 mGrid->addWidget(aLbl, aRow, 0);
1191 aCbx->setMinimumSize(100, aLbl->height()+2);
1193 mGrid->addWidget(aCbx, aRow, 1);
1195 mGrid->addWidget(aChk, aRow, 2);
1196 aChk->setFixedSize(aChk->sizeHint().width(), aLbl->height());
1211 void KMComposeWin::getTransportMenu()
1213 TQStringList availTransports;
1215 mActNowMenu->clear();
1216 mActLaterMenu->clear();
1218 TQStringList::Iterator it;
1220 for(it = availTransports.begin(); it != availTransports.end() ; ++it,
id++)
1222 mActNowMenu->insertItem((*it).replace(
"&",
"&&"), id);
1223 mActLaterMenu->insertItem((*it).replace(
"&",
"&&"), id);
1229 void KMComposeWin::setupActions(
void)
1231 TDEActionMenu *actActionNowMenu, *actActionLaterMenu;
1233 if (kmkernel->msgSender()->sendImmediate())
1236 ( void )
new TDEAction( i18n(
"&Send Mail"),
"mail-send", CTRL+Key_Return,
1237 TQT_TQOBJECT(
this), TQT_SLOT(slotSendNow()), actionCollection(),
"send_default");
1240 actActionNowMenu =
new TDEActionMenu (i18n(
"&Send Mail Via"),
"mail-send",
1241 actionCollection(),
"send_default_via" );
1243 (void)
new TDEAction (i18n(
"Send &Later"),
"queue", 0, TQT_TQOBJECT(
this),
1244 TQT_SLOT(slotSendLater()), actionCollection(),
"send_alternative");
1245 actActionLaterMenu =
new TDEActionMenu (i18n(
"Send &Later Via"),
"queue",
1246 actionCollection(),
"send_alternative_via" );
1252 (void)
new TDEAction (i18n(
"Send &Later"),
"queue",
1254 TQT_TQOBJECT(
this), TQT_SLOT(slotSendLater()), actionCollection(),
"send_default");
1255 actActionLaterMenu =
new TDEActionMenu (i18n(
"Send &Later Via"),
"queue",
1256 actionCollection(),
"send_default_via" );
1258 ( void )
new TDEAction( i18n(
"&Send Mail"),
"mail-send", 0,
1259 TQT_TQOBJECT(
this), TQT_SLOT(slotSendNow()), actionCollection(),
"send_alternative");
1262 actActionNowMenu =
new TDEActionMenu (i18n(
"&Send Mail Via"),
"mail-send",
1263 actionCollection(),
"send_alternative_via" );
1268 actActionNowMenu->setDelayed(
true);
1269 actActionLaterMenu->setDelayed(
true);
1271 connect( actActionNowMenu, TQT_SIGNAL( activated() ),
this,
1272 TQT_SLOT( slotSendNow() ) );
1273 connect( actActionLaterMenu, TQT_SIGNAL( activated() ),
this,
1274 TQT_SLOT( slotSendLater() ) );
1277 mActNowMenu = actActionNowMenu->popupMenu();
1278 mActLaterMenu = actActionLaterMenu->popupMenu();
1280 connect( mActNowMenu, TQT_SIGNAL( activated(
int ) ),
this,
1281 TQT_SLOT( slotSendNowVia(
int ) ) );
1282 connect( mActNowMenu, TQT_SIGNAL( aboutToShow() ),
this,
1283 TQT_SLOT( getTransportMenu() ) );
1285 connect( mActLaterMenu, TQT_SIGNAL( activated(
int ) ),
this,
1286 TQT_SLOT( slotSendLaterVia(
int ) ) );
1287 connect( mActLaterMenu, TQT_SIGNAL( aboutToShow() ),
this,
1288 TQT_SLOT( getTransportMenu() ) );
1293 (void)
new TDEAction (i18n(
"Save as &Draft"),
"document-save", 0,
1294 TQT_TQOBJECT(
this), TQT_SLOT(slotSaveDraft()),
1295 actionCollection(),
"save_in_drafts");
1296 (void)
new TDEAction (i18n(
"Save as &Template"),
"document-save", 0,
1297 TQT_TQOBJECT(
this), TQT_SLOT(slotSaveTemplate()),
1298 actionCollection(),
"save_in_templates");
1299 (void)
new TDEAction (i18n(
"&Insert File..."),
"document-open", 0,
1300 TQT_TQOBJECT(
this), TQT_SLOT(slotInsertFile()),
1301 actionCollection(),
"insert_file");
1302 mRecentAction =
new TDERecentFilesAction (i18n(
"&Insert File Recent"),
1304 TQT_TQOBJECT(
this), TQT_SLOT(slotInsertRecentFile(
const KURL&)),
1305 actionCollection(),
"insert_file_recent");
1307 mRecentAction->loadEntries( KMKernel::config() );
1309 (void)
new TDEAction (i18n(
"&Address Book"),
"contents",0,
1310 TQT_TQOBJECT(
this), TQT_SLOT(slotAddrBook()),
1311 actionCollection(),
"addressbook");
1312 (void)
new TDEAction (i18n(
"&New Composer"),
"mail-message-new",
1313 TDEStdAccel::shortcut(TDEStdAccel::New),
1314 TQT_TQOBJECT(
this), TQT_SLOT(slotNewComposer()),
1315 actionCollection(),
"new_composer");
1316 (void)
new TDEAction (i18n(
"New Main &Window"),
"window-new", 0,
1317 TQT_TQOBJECT(
this), TQT_SLOT(slotNewMailReader()),
1318 actionCollection(),
"open_mailreader");
1320 if ( !mClassicalRecipients ) {
1321 new TDEAction( i18n(
"Select &Recipients..."), CTRL + Key_L, TQT_TQOBJECT(mRecipientsEditor),
1322 TQT_SLOT( selectRecipients() ), actionCollection(),
"select_recipients" );
1323 new TDEAction( i18n(
"Save &Distribution List..."), 0, TQT_TQOBJECT(mRecipientsEditor),
1324 TQT_SLOT( saveDistributionList() ), actionCollection(),
1325 "save_distribution_list" );
1329 KStdAction::print (TQT_TQOBJECT(
this), TQT_SLOT(slotPrint()), actionCollection());
1330 KStdAction::close (TQT_TQOBJECT(
this), TQT_SLOT(slotClose()), actionCollection());
1332 KStdAction::undo (TQT_TQOBJECT(
this), TQT_SLOT(slotUndo()), actionCollection());
1333 KStdAction::redo (TQT_TQOBJECT(
this), TQT_SLOT(slotRedo()), actionCollection());
1334 KStdAction::cut (TQT_TQOBJECT(
this), TQT_SLOT(slotCut()), actionCollection());
1335 KStdAction::copy (TQT_TQOBJECT(
this), TQT_SLOT(slotCopy()), actionCollection());
1336 KStdAction::pasteText (TQT_TQOBJECT(
this), TQT_SLOT(slotPasteClipboard()), actionCollection());
1337 KStdAction::selectAll (TQT_TQOBJECT(
this), TQT_SLOT(slotMarkAll()), actionCollection());
1339 KStdAction::find (TQT_TQOBJECT(
this), TQT_SLOT(slotFind()), actionCollection());
1340 KStdAction::findNext(TQT_TQOBJECT(
this), TQT_SLOT(slotSearchAgain()), actionCollection());
1342 KStdAction::replace (TQT_TQOBJECT(
this), TQT_SLOT(slotReplace()), actionCollection());
1343 KStdAction::spelling (TQT_TQOBJECT(
this), TQT_SLOT(slotSpellcheck()), actionCollection(),
"tools-check-spelling");
1345 mPasteQuotation =
new TDEAction (i18n(
"Pa&ste as Quotation"),0,TQT_TQOBJECT(
this),TQT_SLOT( slotPasteClipboardAsQuotation()),
1346 actionCollection(),
"paste_quoted");
1348 (void)
new TDEAction (i18n(
"Paste as Attac&hment"),0,TQT_TQOBJECT(
this),TQT_SLOT( slotPasteClipboardAsAttachment()),
1349 actionCollection(),
"paste_att");
1351 TDEAction * addq =
new TDEAction(i18n(
"Add &Quote Characters"), 0, TQT_TQOBJECT(
this),
1352 TQT_SLOT(slotAddQuotes()), actionCollection(),
"tools_quote");
1353 connect( mEditor, TQT_SIGNAL(selectionAvailable(
bool)),
1354 addq, TQT_SLOT(setEnabled(
bool)) );
1356 TDEAction * remq =
new TDEAction(i18n(
"Re&move Quote Characters"), 0, TQT_TQOBJECT(
this),
1357 TQT_SLOT(slotRemoveQuotes()), actionCollection(),
"tools_unquote");
1358 connect( mEditor, TQT_SIGNAL(selectionAvailable(
bool)),
1359 remq, TQT_SLOT(setEnabled(
bool)) );
1362 (void)
new TDEAction (i18n(
"Cl&ean Spaces"), 0, TQT_TQOBJECT(
this), TQT_SLOT(slotCleanSpace()),
1363 actionCollection(),
"clean_spaces");
1365 mFixedFontAction =
new TDEToggleAction( i18n(
"Use Fi&xed Font"), 0, TQT_TQOBJECT(
this),
1366 TQT_SLOT(slotUpdateFont()), actionCollection(),
"toggle_fixedfont" );
1367 mFixedFontAction->setChecked( GlobalSettings::self()->useFixedFont() );
1370 mUrgentAction =
new TDEToggleAction (i18n(
"&Urgent"), 0,
1373 mRequestMDNAction =
new TDEToggleAction ( i18n(
"&Request Disposition Notification"), 0,
1375 "options_request_mdn");
1376 mRequestMDNAction->setChecked(GlobalSettings::self()->requestMDN());
1378 mEncodingAction =
new TDESelectAction( i18n(
"Se&t Encoding" ),
"charset",
1379 0, TQT_TQOBJECT(
this), TQT_SLOT(slotSetCharset() ),
1380 actionCollection(),
"charsets" );
1381 mWordWrapAction =
new TDEToggleAction (i18n(
"&Wordwrap"), 0,
1382 actionCollection(),
"wordwrap");
1383 mWordWrapAction->setChecked(GlobalSettings::self()->wordWrap());
1384 connect(mWordWrapAction, TQT_SIGNAL(toggled(
bool)), TQT_SLOT(slotWordWrapToggled(
bool)));
1386 mSnippetAction =
new TDEToggleAction ( i18n(
"&Snippets"), 0,
1387 actionCollection(),
"snippets");
1388 connect(mSnippetAction, TQT_SIGNAL(toggled(
bool)), mSnippetWidget, TQT_SLOT(setShown(
bool)) );
1389 mSnippetAction->setChecked( GlobalSettings::self()->showSnippetManager() );
1391 mAutoSpellCheckingAction =
1392 new TDEToggleAction( i18n(
"&Automatic Spellchecking" ),
"tools-check-spelling", 0,
1393 actionCollection(),
"options_auto_spellchecking" );
1394 const bool spellChecking = GlobalSettings::self()->autoSpellChecking();
1395 mAutoSpellCheckingAction->setEnabled( !GlobalSettings::self()->useExternalEditor() );
1396 mAutoSpellCheckingAction->setChecked( !GlobalSettings::self()->useExternalEditor() && spellChecking );
1397 slotAutoSpellCheckingToggled( !GlobalSettings::self()->useExternalEditor() && spellChecking );
1398 connect( mAutoSpellCheckingAction, TQT_SIGNAL( toggled(
bool ) ),
1399 TQT_TQOBJECT(
this), TQT_SLOT( slotAutoSpellCheckingToggled(
bool ) ) );
1401 TQStringList encodings = KMMsgBase::supportedEncodings(
true);
1402 encodings.prepend( i18n(
"Auto-Detect"));
1403 mEncodingAction->setItems( encodings );
1404 mEncodingAction->setCurrentItem( -1 );
1407 markupAction =
new TDEToggleAction (i18n(
"Formatting (HTML)"), 0, TQT_TQOBJECT(
this),
1408 TQT_SLOT(slotToggleMarkup()),
1409 actionCollection(),
"html");
1411 mAllFieldsAction =
new TDEToggleAction (i18n(
"&All Fields"), 0, TQT_TQOBJECT(
this),
1412 TQT_SLOT(slotView()),
1413 actionCollection(),
"show_all_fields");
1414 mIdentityAction =
new TDEToggleAction (i18n(
"&Identity"), 0, TQT_TQOBJECT(
this),
1415 TQT_SLOT(slotView()),
1416 actionCollection(),
"show_identity");
1417 mDictionaryAction =
new TDEToggleAction (i18n(
"&Dictionary"), 0, TQT_TQOBJECT(
this),
1418 TQT_SLOT(slotView()),
1419 actionCollection(),
"show_dictionary");
1420 mFccAction =
new TDEToggleAction (i18n(
"&Sent-Mail Folder"), 0, TQT_TQOBJECT(
this),
1421 TQT_SLOT(slotView()),
1422 actionCollection(),
"show_fcc");
1423 mTransportAction =
new TDEToggleAction (i18n(
"&Mail Transport"), 0, TQT_TQOBJECT(
this),
1424 TQT_SLOT(slotView()),
1425 actionCollection(),
"show_transport");
1426 mFromAction =
new TDEToggleAction (i18n(
"&From"), 0, TQT_TQOBJECT(
this),
1427 TQT_SLOT(slotView()),
1428 actionCollection(),
"show_from");
1429 mReplyToAction =
new TDEToggleAction (i18n(
"&Reply To"), 0, TQT_TQOBJECT(
this),
1430 TQT_SLOT(slotView()),
1431 actionCollection(),
"show_reply_to");
1432 if ( mClassicalRecipients ) {
1433 mToAction =
new TDEToggleAction (i18n(
"&To"), 0, TQT_TQOBJECT(
this),
1434 TQT_SLOT(slotView()),
1435 actionCollection(),
"show_to");
1436 mCcAction =
new TDEToggleAction (i18n(
"&CC"), 0, TQT_TQOBJECT(
this),
1437 TQT_SLOT(slotView()),
1438 actionCollection(),
"show_cc");
1439 mBccAction =
new TDEToggleAction (i18n(
"&BCC"), 0, TQT_TQOBJECT(
this),
1440 TQT_SLOT(slotView()),
1441 actionCollection(),
"show_bcc");
1443 mSubjectAction =
new TDEToggleAction (i18n(
"S&ubject"), 0, TQT_TQOBJECT(
this),
1444 TQT_SLOT(slotView()),
1445 actionCollection(),
"show_subject");
1448 mAppendSignatureAction =
new TDEAction (i18n(
"Append S&ignature"), 0, TQT_TQOBJECT(
this),
1449 TQT_SLOT(slotAppendSignature()),
1450 actionCollection(),
"append_signature");
1451 mPrependSignatureAction =
new TDEAction (i18n(
"Prepend S&ignature"), 0, TQT_TQOBJECT(
this),
1452 TQT_SLOT(slotPrependSignature()),
1453 actionCollection(),
"prepend_signature");
1455 mInsertSignatureAction =
new TDEAction (i18n(
"Insert Signature At C&ursor Position"),
"edit", 0, TQT_TQOBJECT(
this),
1456 TQT_SLOT(slotInsertSignatureAtCursor()),
1457 actionCollection(),
"insert_signature_at_cursor_position");
1459 mAttachPK =
new TDEAction (i18n(
"Attach &Public Key..."), 0, TQT_TQOBJECT(
this),
1460 TQT_SLOT(slotInsertPublicKey()),
1461 actionCollection(),
"attach_public_key");
1462 mAttachMPK =
new TDEAction (i18n(
"Attach &My Public Key"), 0, TQT_TQOBJECT(
this),
1463 TQT_SLOT(slotInsertMyPublicKey()),
1464 actionCollection(),
"attach_my_public_key");
1465 (void)
new TDEAction (i18n(
"&Attach File..."),
"attach",
1466 0, TQT_TQOBJECT(
this), TQT_SLOT(slotAttachFile()),
1467 actionCollection(),
"attach");
1468 mAttachRemoveAction =
new TDEAction (i18n(
"&Remove Attachment"), 0, TQT_TQOBJECT(
this),
1469 TQT_SLOT(slotAttachRemove()),
1470 actionCollection(),
"remove");
1471 mAttachSaveAction =
new TDEAction (i18n(
"&Save Attachment As..."),
"document-save",0,
1472 TQT_TQOBJECT(
this), TQT_SLOT(slotAttachSave()),
1473 actionCollection(),
"attach_save");
1474 mAttachPropertiesAction =
new TDEAction (i18n(
"Attachment Pr&operties"), 0, TQT_TQOBJECT(
this),
1475 TQT_SLOT(slotAttachProperties()),
1476 actionCollection(),
"attach_properties");
1478 setStandardToolBarMenuEnabled(
true);
1480 KStdAction::keyBindings(TQT_TQOBJECT(
this), TQT_SLOT(slotEditKeys()), actionCollection());
1481 KStdAction::configureToolbars(TQT_TQOBJECT(
this), TQT_SLOT(slotEditToolbars()), actionCollection());
1482 KStdAction::preferences(kmkernel, TQT_SLOT(slotShowConfigurationDialog()), actionCollection());
1484 (void)
new TDEAction (i18n(
"&Spellchecker..."), 0, TQT_TQOBJECT(
this), TQT_SLOT(slotSpellcheckConfig()),
1485 actionCollection(),
"setup_spellchecker");
1487 if ( Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) ) {
1488 TDEToggleAction * a =
new TDEToggleAction( i18n(
"Encrypt Message with Chiasmus..." ),
1489 "chidecrypted", 0, actionCollection(),
1490 "encrypt_message_chiasmus" );
1491 a->setCheckedState( KGuiItem( i18n(
"Encrypt Message with Chiasmus..." ),
"chiencrypted" ) );
1492 mEncryptChiasmusAction = a;
1493 connect( mEncryptChiasmusAction, TQT_SIGNAL(toggled(
bool)),
1494 TQT_TQOBJECT(
this), TQT_SLOT(slotEncryptChiasmusToggled(
bool)) );
1496 mEncryptChiasmusAction = 0;
1499 mEncryptAction =
new TDEToggleAction (i18n(
"&Encrypt Message"),
1501 actionCollection(),
"encrypt_message");
1502 mSignAction =
new TDEToggleAction (i18n(
"&Sign Message"),
1504 actionCollection(),
"sign_message");
1506 const KPIM::Identity & ident =
1507 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
1510 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1511 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1513 mLastEncryptActionState =
false;
1514 mLastSignActionState = GlobalSettings::self()->pgpAutoSign();
1517 mAttachPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() );
1521 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
1522 !ident.pgpEncryptionKey().isEmpty() );
1524 if ( !Kleo::CryptoBackendFactory::instance()->openpgp() && !Kleo::CryptoBackendFactory::instance()->smime() ) {
1526 mEncryptAction->setEnabled(
false );
1527 setEncryption(
false );
1528 mSignAction->setEnabled(
false );
1529 setSigning(
false );
1531 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
1532 && !ident.pgpSigningKey().isEmpty();
1533 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
1534 && !ident.smimeSigningKey().isEmpty();
1536 setEncryption(
false );
1537 setSigning( ( canOpenPGPSign || canSMIMESign ) && GlobalSettings::self()->pgpAutoSign() );
1540 connect(mEncryptAction, TQT_SIGNAL(toggled(
bool)),
1541 TQT_SLOT(slotEncryptToggled(
bool )));
1542 connect(mSignAction, TQT_SIGNAL(toggled(
bool)),
1543 TQT_SLOT(slotSignToggled(
bool )));
1546 for (
int i = 0 ; i < numCryptoMessageFormats ; ++i )
1547 l.push_back( Kleo::cryptoMessageFormatToLabel( cryptoMessageFormats[i] ) );
1549 mCryptoModuleAction =
new TDESelectAction( i18n(
"&Cryptographic Message Format" ), 0,
1550 TQT_TQOBJECT(
this), TQT_SLOT(slotSelectCryptoModule()),
1551 actionCollection(),
"options_select_crypto" );
1552 mCryptoModuleAction->setItems( l );
1553 mCryptoModuleAction->setCurrentItem( format2cb( ident.preferredCryptoMessageFormat() ) );
1554 mCryptoModuleAction->setToolTip( i18n(
"Select a cryptographic format for this message" ) );
1555 slotSelectCryptoModule(
true );
1557 TQStringList styleItems;
1558 styleItems << i18n(
"Standard" );
1559 styleItems << i18n(
"Bulleted List (Disc)" );
1560 styleItems << i18n(
"Bulleted List (Circle)" );
1561 styleItems << i18n(
"Bulleted List (Square)" );
1562 styleItems << i18n(
"Ordered List (Decimal)" );
1563 styleItems << i18n(
"Ordered List (Alpha lower)" );
1564 styleItems << i18n(
"Ordered List (Alpha upper)" );
1566 listAction =
new TDESelectAction( i18n(
"Select Style" ), 0, actionCollection(),
1568 listAction->setItems( styleItems );
1569 listAction->setToolTip( i18n(
"Select a list style" ) );
1570 connect( listAction, TQT_SIGNAL( activated(
const TQString& ) ),
1571 TQT_SLOT( slotListAction(
const TQString& ) ) );
1572 fontAction =
new TDEFontAction(
"Select Font", 0, actionCollection(),
1574 fontAction->setToolTip( i18n(
"Select a font" ) );
1575 connect( fontAction, TQT_SIGNAL( activated(
const TQString& ) ),
1576 TQT_SLOT( slotFontAction(
const TQString& ) ) );
1577 fontSizeAction =
new TDEFontSizeAction(
"Select Size", 0, actionCollection(),
1579 fontSizeAction->setToolTip( i18n(
"Select a font size" ) );
1580 connect( fontSizeAction, TQT_SIGNAL( fontSizeChanged(
int ) ),
1581 TQT_SLOT( slotSizeAction(
int ) ) );
1583 alignLeftAction =
new TDEToggleAction (i18n(
"Align Left"),
"format-text-direction-ltr", 0,
1584 TQT_TQOBJECT(
this), TQT_SLOT(slotAlignLeft()), actionCollection(),
1586 alignLeftAction->setChecked(
true );
1587 alignRightAction =
new TDEToggleAction (i18n(
"Align Right"),
"format-text-direction-rtl", 0,
1588 TQT_TQOBJECT(
this), TQT_SLOT(slotAlignRight()), actionCollection(),
1590 alignCenterAction =
new TDEToggleAction (i18n(
"Align Center"),
"text_center", 0,
1591 TQT_TQOBJECT(
this), TQT_SLOT(slotAlignCenter()), actionCollection(),
1593 textBoldAction =
new TDEToggleAction( i18n(
"&Bold"),
"format-text-bold", CTRL+Key_B,
1594 TQT_TQOBJECT(
this), TQT_SLOT(slotTextBold()),
1595 actionCollection(),
"format-text-bold");
1596 textItalicAction =
new TDEToggleAction( i18n(
"&Italic"),
"format-text-italic", CTRL+Key_I,
1597 TQT_TQOBJECT(
this), TQT_SLOT(slotTextItalic()),
1598 actionCollection(),
"format-text-italic");
1599 textUnderAction =
new TDEToggleAction( i18n(
"&Underline"),
"format-text-underline", CTRL+Key_U,
1600 TQT_TQOBJECT(
this), TQT_SLOT(slotTextUnder()),
1601 actionCollection(),
"format-text-underline");
1602 actionFormatReset =
new TDEAction( i18n(
"Reset Font Settings" ),
"eraser", 0,
1603 TQT_TQOBJECT(
this), TQT_SLOT( slotFormatReset() ),
1604 actionCollection(),
"format_reset");
1605 actionFormatColor =
new TDEAction( i18n(
"Text Color..." ),
"colorize", 0,
1606 TQT_TQOBJECT(
this), TQT_SLOT( slotTextColor() ),
1607 actionCollection(),
"format_color");
1610 createGUI(
"kmcomposerui.rc");
1612 connect( toolBar(
"htmlToolBar"), TQT_SIGNAL( visibilityChanged(
bool) ),
1613 TQT_TQOBJECT(
this), TQT_SLOT( htmlToolBarVisibilityChanged(
bool) ) );
1617 TDEAction* configureAction = actionCollection()->action(
"options_configure" );
1618 if ( configureAction )
1619 configureAction->setText( i18n(
"Configure KMail..." ) );
1623 void KMComposeWin::setupStatusBar(
void)
1625 statusBar()->insertItem(
"", 0, 1);
1626 statusBar()->setItemAlignment(0, AlignLeft | AlignVCenter);
1628 statusBar()->insertItem(i18n(
" Spellcheck: %1 ").arg(
" " ), 3, 0,
true );
1629 statusBar()->insertItem(i18n(
" Column: %1 ").arg(
" "), 2, 0,
true);
1630 statusBar()->insertItem(i18n(
" Line: %1 ").arg(
" "), 1, 0,
true);
1635 void KMComposeWin::updateCursorPosition()
1639 line = mEditor->currentLine();
1640 col = mEditor->currentColumn();
1641 temp = i18n(
" Line: %1 ").arg(line+1);
1642 statusBar()->changeItem(temp,1);
1643 temp = i18n(
" Column: %1 ").arg(col+1);
1644 statusBar()->changeItem(temp,2);
1649 void KMComposeWin::setupEditor(
void)
1652 mEditor->setModified(
false);
1653 TQFontMetrics fm(mBodyFont);
1654 mEditor->setTabStopWidth(fm.width(TQChar(
' ')) * 8);
1657 slotWordWrapToggled( GlobalSettings::self()->wordWrap() );
1683 updateCursorPosition();
1684 connect(mEditor,TQT_SIGNAL(CursorPositionChanged()),TQT_SLOT(updateCursorPosition()));
1685 connect( mEditor, TQT_SIGNAL( currentFontChanged(
const TQFont & ) ),
1686 TQT_TQOBJECT(
this), TQT_SLOT( fontChanged(
const TQFont & ) ) );
1687 connect( mEditor, TQT_SIGNAL( currentAlignmentChanged(
int ) ),
1688 TQT_TQOBJECT(
this), TQT_SLOT( alignmentChanged(
int ) ) );
1694 static TQString cleanedUpHeaderString(
const TQString & s )
1698 res.replace(
'\r',
"" );
1699 res.replace(
'\n',
" " );
1700 return res.stripWhiteSpace();
1704 TQString KMComposeWin::subject()
const 1706 return cleanedUpHeaderString( mEdtSubject->text() );
1710 TQString KMComposeWin::to()
const 1713 return cleanedUpHeaderString( mEdtTo->text() );
1714 }
else if ( mRecipientsEditor ) {
1715 return mRecipientsEditor->recipientString( Recipient::To );
1722 TQString KMComposeWin::cc()
const 1724 if ( mEdtCc && !mEdtCc->isHidden() ) {
1725 return cleanedUpHeaderString( mEdtCc->text() );
1726 }
else if ( mRecipientsEditor ) {
1727 return mRecipientsEditor->recipientString( Recipient::Cc );
1734 TQString KMComposeWin::bcc()
const 1736 if ( mEdtBcc && !mEdtBcc->isHidden() ) {
1737 return cleanedUpHeaderString( mEdtBcc->text() );
1738 }
else if ( mRecipientsEditor ) {
1739 return mRecipientsEditor->recipientString( Recipient::Bcc );
1746 TQString KMComposeWin::from()
const 1748 return cleanedUpHeaderString( mEdtFrom->text() );
1752 TQString KMComposeWin::replyTo()
const 1754 if ( mEdtReplyTo ) {
1755 return cleanedUpHeaderString( mEdtReplyTo->text() );
1762 void KMComposeWin::verifyWordWrapLengthIsAdequate(
const TQString &body)
1764 int maxLineLength = 0;
1767 if (mEditor->TQTextEdit::wordWrap() == TQTextEdit::FixedColumnWidth) {
1768 for (curPos = 0; curPos < (int)body.length(); ++curPos)
1769 if (body[curPos] ==
'\n') {
1770 if ((curPos - oldPos) > maxLineLength)
1771 maxLineLength = curPos - oldPos;
1774 if ((curPos - oldPos) > maxLineLength)
1775 maxLineLength = curPos - oldPos;
1776 if (mEditor->wrapColumnOrWidth() < maxLineLength)
1777 mEditor->setWrapColumnOrWidth(maxLineLength);
1782 void KMComposeWin::decryptOrStripOffCleartextSignature( TQCString& body )
1784 TQPtrList<Kpgp::Block> pgpBlocks;
1785 TQStrList nonPgpBlocks;
1786 if( Kpgp::Module::prepareMessageForDecryption( body,
1787 pgpBlocks, nonPgpBlocks ) )
1791 if( pgpBlocks.count() == 1 )
1793 Kpgp::Block* block = pgpBlocks.first();
1794 if( ( block->type() == Kpgp::PgpMessageBlock ) ||
1795 ( block->type() == Kpgp::ClearsignedBlock ) )
1797 if( block->type() == Kpgp::PgpMessageBlock )
1804 body = nonPgpBlocks.first()
1806 + nonPgpBlocks.last();
1813 void KMComposeWin::setTransport(
const TQString & transport )
1815 kdDebug(5006) <<
"KMComposeWin::setTransport( \"" << transport <<
"\" )" << endl;
1817 if ( transport.isEmpty() )
1820 bool transportFound =
false;
1821 for (
int i = 0; i < mTransport->count(); ++i ) {
1822 if ( mTransport->text(i) == transport ) {
1823 transportFound =
true;
1824 mTransport->setCurrentItem(i);
1825 kdDebug(5006) <<
"transport found, it's no. " << i <<
" in the list" << endl;
1829 if ( !transportFound ) {
1830 kdDebug(5006) <<
"unknown transport \"" << transport <<
"\"" << endl;
1831 if ( transport.startsWith(
"smtp://") || transport.startsWith(
"smtps://") ||
1832 transport.startsWith(
"file://") ) {
1834 mTransport->setEditText( transport );
1838 mTransport->setCurrentText( GlobalSettings::self()->defaultTransport() );
1844 void KMComposeWin::setMsg(
KMMessage* newMsg,
bool mayAutoSign,
1845 bool allowDecryption,
bool isModified)
1850 kdDebug(5006) <<
"KMComposeWin::setMsg() : newMsg == 0!" << endl;
1854 KPIM::IdentityManager * im = kmkernel->identityManager();
1856 mEdtFrom->setText(mMsg->from());
1857 mEdtReplyTo->setText(mMsg->replyTo());
1858 if ( mClassicalRecipients ) {
1859 mEdtTo->setText(mMsg->to());
1860 mEdtCc->setText(mMsg->cc());
1861 mEdtBcc->setText(mMsg->bcc());
1863 mRecipientsEditor->setRecipientString( mMsg->to(), Recipient::To );
1864 mRecipientsEditor->setRecipientString( mMsg->cc(), Recipient::Cc );
1865 mRecipientsEditor->setRecipientString( mMsg->bcc(), Recipient::Bcc );
1866 mRecipientsEditor->setFocusBottom();
1868 mEdtSubject->setText(mMsg->subject());
1870 const bool stickyIdentity = mBtnIdentity->isChecked() && !mIgnoreStickyFields;
1871 const bool messageHasIdentity = !newMsg->
headerField(
"X-KMail-Identity").isEmpty();
1872 if (!stickyIdentity && messageHasIdentity)
1873 mId = newMsg->
headerField(
"X-KMail-Identity").stripWhiteSpace().toUInt();
1877 if ( !stickyIdentity ) {
1878 disconnect(mIdentity,TQT_SIGNAL(identityChanged(uint)),
1879 TQT_TQOBJECT(
this), TQT_SLOT(slotIdentityChanged(uint)));
1882 mIdentity->setCurrentIdentity( mId );
1883 const uint idToApply = mId;
1884 if ( !stickyIdentity ) {
1885 connect(mIdentity,TQT_SIGNAL(identityChanged(uint)),
1886 TQT_TQOBJECT(
this), TQT_SLOT(slotIdentityChanged(uint)));
1891 if ( messageHasIdentity )
1892 mId = newMsg->
headerField(
"X-KMail-Identity").stripWhiteSpace().toUInt();
1894 mId = im->defaultIdentity().uoid();
1899 slotIdentityChanged( idToApply );
1901 const KPIM::Identity & ident = im->identityForUoid( mIdentity->currentIdentity() );
1905 TQString mdnAddr = newMsg->
headerField(
"Disposition-Notification-To");
1906 mRequestMDNAction->setChecked( ( !mdnAddr.isEmpty() &&
1907 im->thatIsMe( mdnAddr ) ) ||
1908 GlobalSettings::self()->requestMDN() );
1911 mUrgentAction->setChecked( newMsg->
isUrgent() );
1913 if (!ident.isXFaceEnabled() || ident.xface().isEmpty())
1914 mMsg->removeHeaderField(
"X-Face");
1917 TQString xface = ident.xface();
1918 if (!xface.isEmpty())
1920 int numNL = ( xface.length() - 1 ) / 70;
1921 for (
int i = numNL; i > 0; --i )
1922 xface.insert( i*70,
"\n\t" );
1923 mMsg->setHeaderField(
"X-Face", xface);
1928 switch ( mMsg->encryptionState() ) {
1929 case KMMsgFullyEncrypted:
1930 case KMMsgPartiallyEncrypted:
1931 mLastEncryptActionState =
true;
1933 case KMMsgNotEncrypted:
1934 mLastEncryptActionState =
false;
1941 switch ( mMsg->signatureState() ) {
1942 case KMMsgFullySigned:
1943 case KMMsgPartiallySigned:
1944 mLastSignActionState =
true;
1946 case KMMsgNotSigned:
1947 mLastSignActionState =
false;
1954 if ( mMsg->headers().FindField(
"X-KMail-SignatureActionEnabled" ) )
1955 mLastSignActionState = (mMsg->headerField(
"X-KMail-SignatureActionEnabled" ) ==
"true");
1956 if ( mMsg->headers().FindField(
"X-KMail-EncryptActionEnabled" ) )
1957 mLastEncryptActionState = (mMsg->headerField(
"X-KMail-EncryptActionEnabled" ) ==
"true");
1958 if ( mMsg->headers().FindField(
"X-KMail-CryptoMessageFormat" ) )
1959 mCryptoModuleAction->setCurrentItem( format2cb( static_cast<Kleo::CryptoMessageFormat>(
1960 mMsg->headerField(
"X-KMail-CryptoMessageFormat" ).toInt() ) ) );
1962 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1963 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1965 if ( Kleo::CryptoBackendFactory::instance()->openpgp() || Kleo::CryptoBackendFactory::instance()->smime() ) {
1966 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
1967 && !ident.pgpSigningKey().isEmpty();
1968 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
1969 && !ident.smimeSigningKey().isEmpty();
1971 setEncryption( mLastEncryptActionState );
1972 setSigning( ( canOpenPGPSign || canSMIMESign ) && mLastSignActionState );
1974 slotUpdateSignatureAndEncrypionStateIndicators();
1978 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
1979 !ident.pgpEncryptionKey().isEmpty() );
1981 TQString transport = newMsg->
headerField(
"X-KMail-Transport");
1982 const bool stickyTransport = mBtnTransport->isChecked() && !mIgnoreStickyFields;
1983 if (!stickyTransport && !transport.isEmpty()) {
1984 setTransport( transport );
1989 if (transport.isEmpty() && !mMsg->originatingAccountName().isEmpty()) {
1990 TQString transportCandidate = mMsg->originatingAccountName();
1991 bool transportFound =
false;
1992 for (
int i = 0; i < mTransport->count(); ++i ) {
1993 if ( mTransport->text(i) == transportCandidate ) {
1994 transportFound =
true;
1995 setTransport(transportCandidate);
2001 if (!mBtnFcc->isChecked())
2003 if (!mMsg->fcc().isEmpty())
2004 setFcc(mMsg->fcc());
2006 setFcc(ident.fcc());
2009 const bool stickyDictionary = mBtnDictionary->isChecked() && !mIgnoreStickyFields;
2010 if ( !stickyDictionary ) {
2011 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
2014 partNode * root = partNode::fromMessage( mMsg );
2016 KMail::ObjectTreeParser otp;
2017 otp.parseObjectTree( root );
2019 KMail::AttachmentCollector ac;
2020 ac.collectAttachmentsFrom( root );
2022 for ( std::vector<partNode*>::const_iterator it = ac.attachments().begin() ; it != ac.attachments().end() ; ++it )
2023 addAttach(
new KMMessagePart( (*it)->msgPart() ) );
2025 mEditor->setText( otp.textualContent() );
2026 mCharset = otp.textualContentCharset();
2027 if ( partNode * n = root->findType( DwMime::kTypeText, DwMime::kSubtypeHtml ) )
2028 if ( partNode * p = n->parentNode() )
2029 if ( p->hasType( DwMime::kTypeMultipart ) &&
2030 p->hasSubType( DwMime::kSubtypeAlternative ) )
2031 if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" ) {
2032 toggleMarkup(
true );
2035 mCharset = n->msgPart().charset();
2036 TQCString bodyDecoded = n->msgPart().bodyDecoded();
2039 const TQTextCodec *codec = KMMsgBase::codecForName( mCharset );
2041 mEditor->setText( codec->toUnicode( bodyDecoded ) );
2043 mEditor->setText( TQString::fromLocal8Bit( bodyDecoded ) );
2047 if ( mCharset.isEmpty() )
2048 mCharset = mMsg->charset();
2049 if ( mCharset.isEmpty() )
2050 mCharset = mDefCharset;
2051 setCharset( mCharset );
2054 if ( mMsg->numBodyParts() == 0 && otp.textualContent().isEmpty() ) {
2055 mCharset=mMsg->charset();
2056 if ( mCharset.isEmpty() || mCharset ==
"default" )
2057 mCharset = mDefCharset;
2059 TQCString bodyDecoded = mMsg->bodyDecoded();
2061 if( allowDecryption )
2062 decryptOrStripOffCleartextSignature( bodyDecoded );
2064 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2066 mEditor->setText(codec->toUnicode(bodyDecoded));
2068 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2070 #ifdef BROKEN_FOR_OPAQUE_SIGNED_OR_ENCRYPTED_MAILS 2071 const int num = mMsg->numBodyParts();
2072 kdDebug(5006) <<
"KMComposeWin::setMsg() mMsg->numBodyParts=" 2073 << mMsg->numBodyParts() << endl;
2076 KMMessagePart bodyPart;
2077 int firstAttachment = 0;
2079 mMsg->bodyPart(1, &bodyPart);
2080 if ( bodyPart.typeStr().lower() ==
"text" &&
2081 bodyPart.subtypeStr().lower() ==
"html" ) {
2083 partNode *root = partNode::fromMessage( mMsg );
2084 partNode *node = root->findType( DwMime::kTypeText,
2085 DwMime::kSubtypeHtml );
2086 if ( node && node->parentNode() &&
2087 node->parentNode()->hasType( DwMime::kTypeMultipart ) &&
2088 node->parentNode()->hasSubType( DwMime::kSubtypeAlternative ) ) {
2090 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/html found" << endl;
2091 firstAttachment = 2;
2092 if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" )
2093 toggleMarkup(
true );
2095 delete root; root = 0;
2097 if ( firstAttachment == 0 ) {
2098 mMsg->bodyPart(0, &bodyPart);
2099 if ( bodyPart.typeStr().lower() ==
"text" ) {
2101 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/* found" << endl;
2102 firstAttachment = 1;
2106 if ( firstAttachment != 0 )
2108 mCharset = bodyPart.charset();
2109 if ( mCharset.isEmpty() || mCharset ==
"default" )
2110 mCharset = mDefCharset;
2112 TQCString bodyDecoded = bodyPart.bodyDecoded();
2114 if( allowDecryption )
2115 decryptOrStripOffCleartextSignature( bodyDecoded );
2123 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2125 mEditor->setText(codec->toUnicode(bodyDecoded));
2127 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2129 }
else mEditor->setText(
"");
2130 for(
int i = firstAttachment; i < num; ++i )
2132 KMMessagePart *msgPart =
new KMMessagePart;
2133 mMsg->bodyPart(i, msgPart);
2134 TQCString mimeType = msgPart->typeStr().lower() +
'/' 2135 + msgPart->subtypeStr().lower();
2138 if( mimeType !=
"application/pgp-signature" ) {
2143 mCharset=mMsg->charset();
2144 if ( mCharset.isEmpty() || mCharset ==
"default" )
2145 mCharset = mDefCharset;
2147 TQCString bodyDecoded = mMsg->bodyDecoded();
2149 if( allowDecryption )
2150 decryptOrStripOffCleartextSignature( bodyDecoded );
2152 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2154 mEditor->setText(codec->toUnicode(bodyDecoded));
2156 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2159 setCharset(mCharset);
2160 #endif // BROKEN_FOR_OPAQUE_SIGNED_OR_ENCRYPTED_MAILS 2162 if( (GlobalSettings::self()->autoTextSignature()==
"auto") && mayAutoSign ) {
2170 if ( GlobalSettings::self()->prependSignature() ) {
2171 TQTimer::singleShot( 0,
this, TQT_SLOT(slotPrependSignature()) );
2173 TQTimer::singleShot( 0,
this, TQT_SLOT(slotAppendSignature()) );
2177 if ( mMsg->getCursorPos() > 0 ) {
2180 mPreserveUserCursorPosition =
true;
2182 setModified( isModified );
2185 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
2188 mPreventFccOverwrite = ( !newMsg->
fcc().isEmpty() && ident.fcc() != newMsg->
fcc() );
2193 void KMComposeWin::setFcc(
const TQString &idString )
2196 if ( ! idString.isEmpty() && kmkernel->findFolderById( idString ) ) {
2197 mFcc->setFolder( idString );
2199 mFcc->setFolder( kmkernel->sentFolder() );
2205 bool KMComposeWin::isModified()
const 2207 return ( mEditor->isModified() ||
2208 mEdtFrom->edited() ||
2209 ( mEdtReplyTo && mEdtReplyTo->edited() ) ||
2210 ( mEdtTo && mEdtTo->edited() ) ||
2211 ( mEdtCc && mEdtCc->edited() ) ||
2212 ( mEdtBcc && mEdtBcc->edited() ) ||
2213 ( mRecipientsEditor && mRecipientsEditor->isModified() ) ||
2214 mEdtSubject->edited() ||
2216 ( mTransport->lineEdit() && mTransport->lineEdit()->edited() ) );
2221 void KMComposeWin::setModified(
bool modified )
2223 mEditor->setModified( modified );
2225 mEdtFrom->setEdited(
false );
2226 if ( mEdtReplyTo ) mEdtReplyTo->setEdited(
false );
2227 if ( mEdtTo ) mEdtTo->setEdited(
false );
2228 if ( mEdtCc ) mEdtCc->setEdited(
false );
2229 if ( mEdtBcc ) mEdtBcc->setEdited(
false );
2230 if ( mRecipientsEditor ) mRecipientsEditor->clearModified();
2231 mEdtSubject->setEdited(
false );
2232 mAtmModified = false ;
2233 if ( mTransport->lineEdit() )
2234 mTransport->lineEdit()->setEdited(
false );
2240 bool KMComposeWin::queryClose ()
2242 if ( !mEditor->checkExternalEditorFinished() )
2244 if ( kmkernel->shuttingDown() || kapp->sessionSaving() )
2246 if ( mComposer && mComposer->isPerformingSignOperation() )
2249 if ( isModified() ) {
2250 bool istemplate = ( mFolder!=0 && mFolder->isTemplates() );
2251 const TQString savebut = ( istemplate ?
2252 i18n(
"Re&save as Template") :
2253 i18n(
"&Save as Draft") );
2254 const TQString savetext = ( istemplate ?
2255 i18n(
"Resave this message in the Templates folder. " 2256 "It can then be used at a later time.") :
2257 i18n(
"Save this message in the Drafts folder. " 2258 "It can then be edited and sent at a later time.") );
2260 const int rc = KMessageBox::warningYesNoCancel(
this,
2261 i18n(
"Do you want to save the message for later or discard it?"),
2262 i18n(
"Close Composer"),
2263 KGuiItem(savebut,
"document-save", TQString(), savetext),
2264 KStdGuiItem::discard() );
2265 if ( rc == KMessageBox::Cancel )
2267 else if ( rc == KMessageBox::Yes ) {
2282 bool KMComposeWin::userForgotAttachment()
2284 bool checkForForgottenAttachments =
2285 mCheckForForgottenAttachments && GlobalSettings::self()->showForgottenAttachmentWarning();
2287 if ( !checkForForgottenAttachments || ( mAtmList.count() > 0 ) )
2291 TQStringList attachWordsList = GlobalSettings::self()->attachmentKeywords();
2293 if ( attachWordsList.isEmpty() ) {
2295 attachWordsList << TQString::fromLatin1(
"attachment")
2296 << TQString::fromLatin1(
"attached");
2297 if ( TQString::fromLatin1(
"attachment") != i18n(
"attachment") )
2298 attachWordsList << i18n(
"attachment");
2299 if ( TQString::fromLatin1(
"attached") != i18n(
"attached") )
2300 attachWordsList << i18n(
"attached");
2303 TQRegExp rx ( TQString::fromLatin1(
"\\b") +
2304 attachWordsList.join(
"\\b|\\b") +
2305 TQString::fromLatin1(
"\\b") );
2306 rx.setCaseSensitive(
false );
2308 bool gotMatch =
false;
2312 TQString subj = subject();
2313 gotMatch = ( KMMessage::stripOffPrefixes( subj ) == subj )
2314 && ( rx.search( subj ) >= 0 );
2319 TQRegExp quotationRx (
"^([ \\t]*([|>:}#]|[A-Za-z]+>))+");
2320 for (
int i = 0; i < mEditor->numLines(); ++i ) {
2321 TQString line = mEditor->textLine( i );
2322 gotMatch = ( quotationRx.search( line ) < 0 )
2323 && ( rx.search( line ) >= 0 );
2332 int rc = KMessageBox::warningYesNoCancel(
this,
2333 i18n(
"The message you have composed seems to refer to an " 2334 "attached file but you have not attached anything.\n" 2335 "Do you want to attach a file to your message?"),
2336 i18n(
"File Attachment Reminder"),
2337 i18n(
"&Attach File..."),
2338 i18n(
"&Send as Is") );
2339 if ( rc == KMessageBox::Cancel )
2341 if ( rc == KMessageBox::Yes ) {
2350 void KMComposeWin::applyChanges(
bool dontSignNorEncrypt,
bool dontDisable )
2352 kdDebug(5006) <<
"entering KMComposeWin::applyChanges" << endl;
2354 if(!mMsg || mComposer) {
2355 kdDebug(5006) <<
"KMComposeWin::applyChanges() : mMsg == 0!\n" << endl;
2356 emit applyChangesDone(
false );
2361 mComposer =
new MessageComposer(
this );
2362 connect( mComposer, TQT_SIGNAL( done(
bool ) ),
2363 TQT_TQOBJECT(
this), TQT_SLOT( slotComposerDone(
bool ) ) );
2368 if ( !dontDisable ) setEnabled(
false );
2370 mComposer->setDisableBreaking( mDisableBreaking );
2371 mComposer->applyChanges( dontSignNorEncrypt );
2374 void KMComposeWin::slotComposerDone(
bool rc )
2376 deleteAll( mComposedMessages );
2377 mComposedMessages = mComposer->composedMessageList();
2378 emit applyChangesDone( rc );
2386 const KPIM::Identity & KMComposeWin::identity()
const {
2387 return kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
2390 uint KMComposeWin::identityUid()
const {
2391 return mIdentity->currentIdentity();
2394 Kleo::CryptoMessageFormat KMComposeWin::cryptoMessageFormat()
const {
2395 if ( !mCryptoModuleAction )
2396 return Kleo::AutoFormat;
2397 return cb2format( mCryptoModuleAction->currentItem() );
2400 bool KMComposeWin::encryptToSelf()
const {
2402 TDEConfigGroup group( KMKernel::config(),
"Composer" );
2403 return group.readBoolEntry(
"crypto-encrypt-to-self",
true );
2406 bool KMComposeWin::queryExit ()
2412 bool KMComposeWin::addAttach(
const KURL aUrl)
2414 if ( !aUrl.isValid() ) {
2415 KMessageBox::sorry(
this, i18n(
"<qt><p>KMail could not recognize the location of the attachment (%1);</p>" 2416 "<p>you have to specify the full path if you wish to attach a file.</p></qt>" )
2417 .arg( aUrl.prettyURL() ) );
2421 const int maxAttachmentSize = GlobalSettings::maximumAttachmentSize();
2422 const uint maximumAttachmentSizeInByte = maxAttachmentSize*1024*1024;
2423 if ( aUrl.isLocalFile() && TQFileInfo( aUrl.pathOrURL() ).size() > maximumAttachmentSizeInByte ) {
2424 KMessageBox::sorry(
this, i18n(
"<qt><p>Your administrator has disallowed attaching files bigger than %1 MB.</p>" ).arg( maxAttachmentSize ) );
2428 TDEIO::TransferJob *job = TDEIO::get(aUrl);
2429 TDEIO::Scheduler::scheduleJob( job );
2432 ld.data = TQByteArray();
2434 if( !aUrl.fileEncoding().isEmpty() )
2435 ld.encoding = aUrl.fileEncoding().latin1();
2437 mMapAtmLoadData.insert(job, ld);
2438 mAttachJobs[job] = aUrl;
2439 connect(job, TQT_SIGNAL(result(TDEIO::Job *)),
2440 TQT_TQOBJECT(
this), TQT_SLOT(slotAttachFileResult(TDEIO::Job *)));
2441 connect(job, TQT_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
2442 TQT_TQOBJECT(
this), TQT_SLOT(slotAttachFileData(TDEIO::Job *,
const TQByteArray &)));
2448 void KMComposeWin::addAttach(
const KMMessagePart* msgPart)
2450 mAtmList.append(msgPart);
2453 if (mAtmList.count()==1)
2455 mAtmListView->resize(mAtmListView->width(), 50);
2456 mAtmListView->show();
2461 KMAtmListViewItem *lvi =
new KMAtmListViewItem( mAtmListView );
2462 msgPartToItem(msgPart, lvi);
2463 mAtmItemList.append(lvi);
2466 if ( mTempDir != 0 ) {
2471 connect( lvi, TQT_SIGNAL( compress(
int ) ),
2472 TQT_TQOBJECT(
this), TQT_SLOT( compressAttach(
int ) ) );
2473 connect( lvi, TQT_SIGNAL( uncompress(
int ) ),
2474 TQT_TQOBJECT(
this), TQT_SLOT( uncompressAttach(
int ) ) );
2476 slotUpdateAttachActions();
2481 void KMComposeWin::slotUpdateAttachActions()
2483 int selectedCount = 0;
2484 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it ) {
2485 if ( (*it)->isSelected() ) {
2490 mAttachRemoveAction->setEnabled( selectedCount >= 1 );
2491 mAttachSaveAction->setEnabled( selectedCount == 1 );
2492 mAttachPropertiesAction->setEnabled( selectedCount == 1 );
2498 TQString KMComposeWin::prettyMimeType(
const TQString& type )
2500 TQString t = type.lower();
2501 KServiceType::Ptr st = KServiceType::serviceType( t );
2502 return st ? st->comment() : t;
2505 void KMComposeWin::msgPartToItem(
const KMMessagePart* msgPart,
2506 KMAtmListViewItem *lvi,
bool loadDefaults)
2508 assert(msgPart != 0);
2510 if (!msgPart->fileName().isEmpty())
2511 lvi->setText(0, msgPart->fileName());
2513 lvi->setText(0, msgPart->name());
2514 lvi->setText(1, TDEIO::convertSize( msgPart->decodedSize()));
2515 lvi->setText(2, msgPart->contentTransferEncodingStr());
2516 lvi->setText(3, prettyMimeType(msgPart->typeStr() +
"/" + msgPart->subtypeStr()));
2517 lvi->setAttachmentSize(msgPart->decodedSize());
2519 if ( loadDefaults ) {
2520 if( canSignEncryptAttachments() ) {
2521 lvi->enableCryptoCBs(
true );
2522 lvi->setEncrypt( mEncryptAction->isChecked() );
2523 lvi->setSign( mSignAction->isChecked() );
2525 lvi->enableCryptoCBs(
false );
2532 void KMComposeWin::removeAttach(
const TQString &aUrl)
2535 KMMessagePart* msgPart;
2536 for(idx=0,msgPart=mAtmList.first(); msgPart;
2537 msgPart=mAtmList.next(),idx++) {
2538 if (msgPart->name() == aUrl) {
2547 void KMComposeWin::removeAttach(
int idx)
2549 mAtmModified =
true;
2551 KMAtmListViewItem *item =
static_cast<KMAtmListViewItem*
>( mAtmItemList.at( idx ) );
2552 if ( item->itemBelow() )
2553 mAtmSelectNew = item->itemBelow();
2554 else if ( item->itemAbove() )
2555 mAtmSelectNew = item->itemAbove();
2557 mAtmList.remove(idx);
2558 delete mAtmItemList.take(idx);
2560 if( mAtmList.isEmpty() )
2562 mAtmListView->hide();
2563 mAtmListView->setMinimumSize(0, 0);
2570 bool KMComposeWin::encryptFlagOfAttachment(
int idx)
2572 return (
int)(mAtmItemList.count()) > idx
2573 ? static_cast<KMAtmListViewItem*>( mAtmItemList.at( idx ) )->isEncrypt()
2579 bool KMComposeWin::signFlagOfAttachment(
int idx)
2581 return (
int)(mAtmItemList.count()) > idx
2582 ? ((KMAtmListViewItem*)(mAtmItemList.at( idx )))->isSign()
2588 void KMComposeWin::addrBookSelInto()
2590 if ( mClassicalRecipients ) {
2591 if ( GlobalSettings::self()->addresseeSelectorType() ==
2592 GlobalSettings::EnumAddresseeSelectorType::New ) {
2593 addrBookSelIntoNew();
2595 addrBookSelIntoOld();
2598 kdWarning() <<
"To be implemented: call recipients picker." << endl;
2602 void KMComposeWin::addrBookSelIntoOld()
2604 AddressesDialog dlg(
this );
2609 if ( !txt.isEmpty() ) {
2610 lst = KPIM::splitEmailAddrList( txt );
2611 dlg.setSelectedTo( lst );
2614 txt = mEdtCc->text();
2615 if ( !txt.isEmpty() ) {
2616 lst = KPIM::splitEmailAddrList( txt );
2617 dlg.setSelectedCC( lst );
2620 txt = mEdtBcc->text();
2621 if ( !txt.isEmpty() ) {
2622 lst = KPIM::splitEmailAddrList( txt );
2623 dlg.setSelectedBCC( lst );
2626 dlg.setRecentAddresses( RecentAddresses::self( KMKernel::config() )->tdeabcAddresses() );
2628 if (dlg.exec()==TQDialog::Rejected)
return;
2630 mEdtTo->setText( dlg.to().join(
", ") );
2631 mEdtTo->setEdited(
true );
2633 mEdtCc->setText( dlg.cc().join(
", ") );
2634 mEdtCc->setEdited(
true );
2636 mEdtBcc->setText( dlg.bcc().join(
", ") );
2637 mEdtBcc->setEdited(
true );
2640 if ( !mEdtBcc->text().isEmpty() ) {
2641 mShowHeaders |= HDR_BCC;
2642 rethinkFields(
false );
2646 void KMComposeWin::addrBookSelIntoNew()
2648 AddresseeEmailSelection selection;
2650 AddresseeSelectorDialog dlg( &selection );
2656 if ( !txt.isEmpty() ) {
2657 lst = KPIM::splitEmailAddrList( txt );
2658 selection.setSelectedTo( lst );
2661 txt = mEdtCc->text();
2662 if ( !txt.isEmpty() ) {
2663 lst = KPIM::splitEmailAddrList( txt );
2664 selection.setSelectedCC( lst );
2667 txt = mEdtBcc->text();
2668 if ( !txt.isEmpty() ) {
2669 lst = KPIM::splitEmailAddrList( txt );
2670 selection.setSelectedBCC( lst );
2673 if (dlg.exec()==TQDialog::Rejected)
return;
2675 TQStringList list = selection.to() + selection.toDistributionLists();
2676 mEdtTo->setText( list.join(
", ") );
2677 mEdtTo->setEdited(
true );
2679 list = selection.cc() + selection.ccDistributionLists();
2680 mEdtCc->setText( list.join(
", ") );
2681 mEdtCc->setEdited(
true );
2683 list = selection.bcc() + selection.bccDistributionLists();
2684 mEdtBcc->setText( list.join(
", ") );
2685 mEdtBcc->setEdited(
true );
2688 if ( !mEdtBcc->text().isEmpty() ) {
2689 mShowHeaders |= HDR_BCC;
2690 rethinkFields(
false );
2696 void KMComposeWin::setCharset(
const TQCString& aCharset,
bool forceDefault)
2698 if ((forceDefault && GlobalSettings::self()->forceReplyCharset()) || aCharset.isEmpty())
2699 mCharset = mDefCharset;
2701 mCharset = aCharset.lower();
2703 if ( mCharset.isEmpty() || mCharset ==
"default" )
2704 mCharset = mDefCharset;
2708 mEncodingAction->setCurrentItem( 0 );
2712 TQStringList encodings = mEncodingAction->items();
2714 bool charsetFound =
false;
2715 for ( TQStringList::Iterator it = encodings.begin(); it != encodings.end();
2718 if (i > 0 && ((mCharset ==
"us-ascii" && i == 1) ||
2719 (i != 1 && TDEGlobal::charsets()->codecForName(
2720 TDEGlobal::charsets()->encodingForName(*it))
2721 == TDEGlobal::charsets()->codecForName(mCharset))))
2723 mEncodingAction->setCurrentItem( i );
2725 charsetFound =
true;
2729 if (!aCharset.isEmpty() && !charsetFound) setCharset(
"",
true);
2734 void KMComposeWin::slotAddrBook()
2736 KAddrBookExternal::openAddressBook(
this);
2741 void KMComposeWin::slotAddrBookFrom()
2748 void KMComposeWin::slotAddrBookReplyTo()
2755 void KMComposeWin::slotAddrBookTo()
2761 void KMComposeWin::slotAttachFile()
2769 KURL recentURL = KFileDialog::getStartURL( TQString(), recent );
2770 if ( !recentURL.url().isEmpty() &&
2771 !TDEIO::NetAccess::exists( recentURL,
true,
this ) ) {
2772 recentURL = KURL( TQDir::homeDirPath() );
2775 KFileDialog fdlg( recentURL.url(), TQString(),
this, 0, true );
2776 fdlg.setOperationMode( KFileDialog::Other );
2777 fdlg.setCaption( i18n(
"Attach File" ) );
2778 fdlg.okButton()->setGuiItem( KGuiItem( i18n(
"&Attach" ),
"document-open" ) );
2779 fdlg.setMode( KFile::Files );
2781 KURL::List files = fdlg.selectedURLs();
2783 for (KURL::List::Iterator it = files.begin(); it != files.end(); ++it)
2789 void KMComposeWin::slotAttachFileData(TDEIO::Job *job,
const TQByteArray &data)
2791 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
2792 assert(it != mMapAtmLoadData.end());
2793 TQBuffer buff((*it).data);
2794 buff.open(IO_WriteOnly | IO_Append);
2795 buff.writeBlock(data.data(), data.size());
2801 void KMComposeWin::slotAttachFileResult(TDEIO::Job *job)
2803 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
2804 assert(it != mMapAtmLoadData.end());
2806 TQMap<TDEIO::Job*, KURL>::iterator jit = mAttachJobs.find(job);
2807 bool attachURLfound = (jit != mAttachJobs.end());
2810 attachURL = jit.data();
2811 mAttachJobs.remove(jit);
2815 mMapAtmLoadData.remove(it);
2816 job->showErrorDialog();
2818 emit attachmentAdded(attachURL,
false);
2823 (*it).data.resize((*it).data.size() + 1);
2824 (*it).data[(*it).data.size() - 1] =
'\0';
2825 if (
const TQTextCodec * codec = TDEGlobal::charsets()->codecForName((*it).encoding) )
2826 mEditor->insert( codec->toUnicode( (*it).data ) );
2828 mEditor->insert( TQString::fromLocal8Bit( (*it).data ) );
2829 mMapAtmLoadData.remove(it);
2831 emit attachmentAdded(attachURL,
true);
2834 TQCString partCharset;
2835 if ( !( *it ).url.fileEncoding().isEmpty() ) {
2836 partCharset = TQCString( ( *it ).url.fileEncoding().latin1() );
2839 TDELocale *loc = TDEGlobal::locale();
2840 ed.setAutoDetectLanguage( EncodingDetector::scriptForLanguageCode ( loc->language() ) );
2843 if ( partCharset.isEmpty() )
2844 partCharset = mCharset;
2847 KMMessagePart* msgPart;
2850 TQString name( (*it).url.fileName() );
2852 TQString mimeType =
static_cast<TDEIO::MimetypeJob*
>(job)->mimetype();
2854 if ( name.isEmpty() ) {
2857 if( mimeType ==
"text/html" )
2858 name =
"index.html";
2861 TQStringList patterns( KMimeType::mimeType( mimeType )->patterns() );
2863 if( !patterns.isEmpty() ) {
2865 int i = ext.findRev(
'.' );
2871 name = TQString(
"unknown") += ext;
2875 name.truncate( 256 );
2877 TQCString encoding = KMMsgBase::autoDetectCharset(partCharset,
2879 if ( encoding.isEmpty() )
2883 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
2884 encName = KMMsgBase::encodeRFC2047String( name, encoding );
2886 encName = KMMsgBase::encodeRFC2231String( name, encoding );
2887 bool RFC2231encoded =
false;
2888 if ( !GlobalSettings::self()->outlookCompatibleAttachments() )
2889 RFC2231encoded = name != TQString( encName );
2892 msgPart =
new KMMessagePart;
2893 msgPart->setName(name);
2894 TQValueList<int> allowedCTEs;
2895 if ( mimeType ==
"message/rfc822" ) {
2896 msgPart->setMessageBody( (*it).data );
2897 allowedCTEs << DwMime::kCte7bit;
2898 allowedCTEs << DwMime::kCte8bit;
2900 msgPart->setBodyAndGuessCte((*it).data, allowedCTEs,
2901 !kmkernel->msgSender()->sendQuotedPrintable());
2902 kdDebug(5006) <<
"autodetected cte: " << msgPart->cteStr() << endl;
2904 int slash = mimeType.find(
'/' );
2906 slash = mimeType.length();
2907 msgPart->setTypeStr( mimeType.left( slash ).latin1() );
2908 msgPart->setSubtypeStr( mimeType.mid( slash + 1 ).latin1() );
2909 msgPart->setContentDisposition(TQCString(
"attachment;\n\tfilename")
2910 + ( RFC2231encoded ?
"*=" + encName :
"=\"" + encName +
'"' ) );
2912 mMapAtmLoadData.remove(it);
2914 if ( msgPart->typeStr().lower() ==
"text" ) {
2915 msgPart->setCharset(partCharset);
2919 TDEConfigGroup composer(KMKernel::config(),
"Composer");
2920 if ( GlobalSettings::self()->showMessagePartDialogOnAttach() ) {
2924 for ( TQValueListConstIterator<int> it = allowedCTEs.begin() ;
2925 it != allowedCTEs.end() ; ++it )
2927 case DwMime::kCteBase64: encodings |= KMMsgPartDialog::Base64;
break;
2928 case DwMime::kCteQp: encodings |= KMMsgPartDialog::QuotedPrintable;
break;
2929 case DwMime::kCte7bit: encodings |= KMMsgPartDialog::SevenBit;
break;
2930 case DwMime::kCte8bit: encodings |= KMMsgPartDialog::EightBit;
break;
2933 dlg.setShownEncodings( encodings );
2934 dlg.setMsgPart(msgPart);
2939 emit attachmentAdded(attachURL,
false);
2943 mAtmModified =
true;
2949 emit attachmentAdded(attachURL,
true);
2954 void KMComposeWin::slotInsertFile()
2956 KFileDialog fdlg(TQString(), TQString(),
this, 0,
true);
2957 fdlg.setOperationMode( KFileDialog::Opening );
2958 fdlg.okButton()->setText(i18n(
"&Insert"));
2959 fdlg.setCaption(i18n(
"Insert File"));
2960 fdlg.toolBar()->insertCombo(KMMsgBase::supportedEncodings(
false), 4711,
2962 KComboBox *combo = fdlg.toolBar()->getCombo(4711);
2963 for (
int i = 0; i < combo->count(); i++)
2964 if (TDEGlobal::charsets()->codecForName(TDEGlobal::charsets()->
2965 encodingForName(combo->text(i)))
2966 == TQTextCodec::codecForLocale()) combo->setCurrentItem(i);
2967 if (!fdlg.exec())
return;
2969 KURL u = fdlg.selectedURL();
2970 mRecentAction->addURL(u);
2973 TDEConfig *config = KMKernel::config();
2974 TDEConfigGroupSaver saver( config,
"Composer" );
2975 TQString encoding = TDEGlobal::charsets()->encodingForName(combo->currentText()).latin1();
2976 TQStringList urls = config->readListEntry(
"recent-urls" );
2977 TQStringList encodings = config->readListEntry(
"recent-encodings" );
2980 uint mMaxRecentFiles = 30;
2981 while (urls.count() > mMaxRecentFiles)
2982 urls.erase( urls.fromLast() );
2983 while (encodings.count() > mMaxRecentFiles)
2984 encodings.erase( encodings.fromLast() );
2986 if (urls.count() != encodings.count()) {
2990 urls.prepend( u.prettyURL() );
2991 encodings.prepend( encoding );
2992 config->writeEntry(
"recent-urls", urls );
2993 config->writeEntry(
"recent-encodings", encodings );
2994 mRecentAction->saveEntries( config );
2996 slotInsertRecentFile(u);
3001 void KMComposeWin::slotInsertRecentFile(
const KURL& u)
3003 if (u.fileName().isEmpty())
return;
3005 TDEIO::Job *job = TDEIO::get(u);
3008 ld.data = TQByteArray();
3012 TDEConfig *config = KMKernel::config();
3013 TDEConfigGroupSaver saver( config,
"Composer" );
3014 TQStringList urls = config->readListEntry(
"recent-urls" );
3015 TQStringList encodings = config->readListEntry(
"recent-encodings" );
3016 int index = urls.findIndex( u.prettyURL() );
3018 TQString encoding = encodings[ index ];
3019 ld.encoding = encoding.latin1();
3022 mMapAtmLoadData.insert(job, ld);
3023 connect(job, TQT_SIGNAL(result(TDEIO::Job *)),
3024 TQT_TQOBJECT(
this), TQT_SLOT(slotAttachFileResult(TDEIO::Job *)));
3025 connect(job, TQT_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
3026 TQT_TQOBJECT(
this), TQT_SLOT(slotAttachFileData(TDEIO::Job *,
const TQByteArray &)));
3031 void KMComposeWin::slotSetCharset()
3033 if (mEncodingAction->currentItem() == 0)
3035 mAutoCharset =
true;
3038 mAutoCharset =
false;
3040 mCharset = TDEGlobal::charsets()->encodingForName( mEncodingAction->
3041 currentText() ).latin1();
3046 void KMComposeWin::slotSelectCryptoModule(
bool init )
3049 setModified(
true );
3051 if( canSignEncryptAttachments() ) {
3053 if( 0 == mAtmListView->columnWidth( mAtmColEncrypt ) ) {
3056 if( !mAtmList.isEmpty() ) {
3057 for( KMAtmListViewItem* lvi = static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
3059 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3060 lvi->setSign( mSignAction->isChecked() );
3061 lvi->setEncrypt( mEncryptAction->isChecked() );
3066 for(
int col=0; col < mAtmColEncrypt; col++ )
3067 totalWidth += mAtmListView->columnWidth( col );
3068 int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
3073 for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
3074 int newWidth = mAtmListView->columnWidth( col ) * reducedTotalWidth
3076 mAtmListView->setColumnWidth( col, newWidth );
3077 usedWidth += newWidth;
3082 mAtmListView->setColumnWidth( mAtmColEncrypt-1,
3083 reducedTotalWidth - usedWidth );
3084 mAtmListView->setColumnWidth( mAtmColEncrypt, mAtmEncryptColWidth );
3085 mAtmListView->setColumnWidth( mAtmColSign, mAtmSignColWidth );
3086 for( KMAtmListViewItem* lvi = static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
3088 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3089 lvi->enableCryptoCBs(
true );
3094 if( 0 != mAtmListView->columnWidth( mAtmColEncrypt ) ) {
3095 mAtmEncryptColWidth = mAtmListView->columnWidth( mAtmColEncrypt );
3096 mAtmSignColWidth = mAtmListView->columnWidth( mAtmColSign );
3099 for(
int col=0; col < mAtmListView->columns(); col++ )
3100 totalWidth += mAtmListView->columnWidth( col );
3101 int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
3106 for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
3107 int newWidth = mAtmListView->columnWidth( col ) * totalWidth
3108 / reducedTotalWidth;
3109 mAtmListView->setColumnWidth( col, newWidth );
3110 usedWidth += newWidth;
3115 mAtmListView->setColumnWidth( mAtmColEncrypt-1, totalWidth - usedWidth );
3116 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
3117 mAtmListView->setColumnWidth( mAtmColSign, 0 );
3118 for( KMAtmListViewItem* lvi = static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
3120 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3121 lvi->enableCryptoCBs(
false );
3127 static void showExportError( TQWidget * w,
const GpgME::Error & err ) {
3129 const TQString msg = i18n(
"<qt><p>An error occurred while trying to export " 3130 "the key from the backend:</p>" 3131 "<p><b>%1</b></p></qt>")
3132 .arg( TQString::fromLocal8Bit( err.asString() ) );
3133 KMessageBox::error( w, msg, i18n(
"Key Export Failed") );
3138 void KMComposeWin::slotInsertMyPublicKey()
3142 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() ).pgpEncryptionKey();
3143 if ( !mFingerprint.isEmpty() )
3144 startPublicKeyExport();
3147 void KMComposeWin::startPublicKeyExport() {
3148 if ( mFingerprint.isEmpty() || !Kleo::CryptoBackendFactory::instance()->openpgp() )
3150 Kleo::ExportJob * job = Kleo::CryptoBackendFactory::instance()->openpgp()->publicKeyExportJob(
true );
3153 connect( job, TQT_SIGNAL(result(
const GpgME::Error&,
const TQByteArray&)),
3154 this, TQT_SLOT(slotPublicKeyExportResult(
const GpgME::Error&,
const TQByteArray&)) );
3156 const GpgME::Error err = job->start( mFingerprint );
3158 showExportError(
this, err );
3160 (
void)
new Kleo::ProgressDialog( job, i18n(
"Exporting key..."),
this );
3163 void KMComposeWin::slotPublicKeyExportResult(
const GpgME::Error & err,
const TQByteArray & keydata ) {
3165 showExportError(
this, err );
3170 KMMessagePart * msgPart =
new KMMessagePart();
3171 msgPart->setName( i18n(
"OpenPGP key 0x%1").arg( mFingerprint ) );
3172 msgPart->setTypeStr(
"application");
3173 msgPart->setSubtypeStr(
"pgp-keys");
3174 TQValueList<int> dummy;
3175 msgPart->setBodyAndGuessCte(keydata, dummy,
false);
3176 msgPart->setContentDisposition(
"attachment;\n\tfilename=0x" + TQCString( mFingerprint.latin1() ) +
".asc" );
3184 void KMComposeWin::slotInsertPublicKey()
3186 Kleo::KeySelectionDialog dlg( i18n(
"Attach Public OpenPGP Key"),
3187 i18n(
"Select the public key which should " 3189 std::vector<GpgME::Key>(),
3190 Kleo::KeySelectionDialog::PublicKeys|Kleo::KeySelectionDialog::OpenPGPKeys,
3193 this,
"attach public key selection dialog" );
3194 if ( dlg.exec() != TQDialog::Accepted )
3197 mFingerprint = dlg.fingerprint();
3198 startPublicKeyExport();
3203 void KMComposeWin::slotAttachPopupMenu(TQListViewItem *,
const TQPoint &,
int)
3207 mAttachMenu =
new TQPopupMenu(
this);
3209 mOpenId = mAttachMenu->insertItem(i18n(
"to open",
"Open"),
this,
3210 TQT_SLOT(slotAttachOpen()));
3211 mOpenWithId = mAttachMenu->insertItem(i18n(
"Open With..."),
this,
3212 TQT_SLOT(slotAttachOpenWith()));
3213 mViewId = mAttachMenu->insertItem(i18n(
"to view",
"View"),
this,
3214 TQT_SLOT(slotAttachView()));
3215 mEditId = mAttachMenu->insertItem( i18n(
"Edit"),
this, TQT_SLOT(slotAttachEdit()) );
3216 mEditWithId = mAttachMenu->insertItem( i18n(
"Edit With..."),
this,
3217 TQT_SLOT(slotAttachEditWith()) );
3218 mRemoveId = mAttachMenu->insertItem(i18n(
"Remove"),
this, TQT_SLOT(slotAttachRemove()));
3219 mSaveAsId = mAttachMenu->insertItem( SmallIconSet(
"document-save-as"), i18n(
"Save As..."),
this,
3220 TQT_SLOT( slotAttachSave() ) );
3221 mPropertiesId = mAttachMenu->insertItem( i18n(
"Properties"),
this,
3222 TQT_SLOT( slotAttachProperties() ) );
3223 mAttachMenu->insertSeparator();
3224 mAttachMenu->insertItem(i18n(
"Add Attachment..."),
this, TQT_SLOT(slotAttachFile()));
3227 int selectedCount = 0;
3228 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it ) {
3229 if ( (*it)->isSelected() ) {
3234 mAttachMenu->setItemEnabled( mOpenId, selectedCount > 0 );
3235 mAttachMenu->setItemEnabled( mOpenWithId, selectedCount > 0 );
3236 mAttachMenu->setItemEnabled( mViewId, selectedCount > 0 );
3237 mAttachMenu->setItemEnabled( mEditId, selectedCount == 1 );
3238 mAttachMenu->setItemEnabled( mEditWithId, selectedCount == 1 );
3239 mAttachMenu->setItemEnabled( mRemoveId, selectedCount > 0 );
3240 mAttachMenu->setItemEnabled( mSaveAsId, selectedCount == 1 );
3241 mAttachMenu->setItemEnabled( mPropertiesId, selectedCount == 1 );
3243 mAttachMenu->popup(TQCursor::pos());
3247 int KMComposeWin::currentAttachmentNum()
3250 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i )
3251 if ( *it == mAtmListView->currentItem() )
3257 void KMComposeWin::slotAttachProperties()
3259 int idx = currentAttachmentNum();
3261 if (idx < 0)
return;
3263 KMMessagePart* msgPart = mAtmList.at(idx);
3266 dlg.setMsgPart(msgPart);
3267 KMAtmListViewItem* listItem = (KMAtmListViewItem*)(mAtmItemList.at(idx));
3268 if( canSignEncryptAttachments() && listItem ) {
3269 dlg.setCanSign(
true );
3270 dlg.setCanEncrypt(
true );
3271 dlg.setSigned( listItem->isSign() );
3272 dlg.setEncrypted( listItem->isEncrypt() );
3274 dlg.setCanSign(
false );
3275 dlg.setCanEncrypt(
false );
3279 mAtmModified =
true;
3282 msgPartToItem(msgPart, listItem);
3283 if( canSignEncryptAttachments() ) {
3284 listItem->setSign( dlg.isSigned() );
3285 listItem->setEncrypt( dlg.isEncrypted() );
3289 if (msgPart->typeStr().lower() !=
"text") msgPart->setCharset(TQCString());
3293 void KMComposeWin::compressAttach(
int idx )
3295 if (idx < 0)
return;
3298 for ( i = 0; i < mAtmItemList.count(); ++i )
3299 if ( mAtmItemList.at( i )->itemPos() == idx )
3302 if ( i > mAtmItemList.count() )
3305 KMMessagePart* msgPart;
3306 msgPart = mAtmList.at( i );
3308 TQBuffer dev( array );
3309 KZip zip( &TQT_TQIODEVICE_OBJECT(dev) );
3310 TQByteArray decoded = msgPart->bodyDecodedBinary();
3311 if ( ! zip.open( IO_WriteOnly ) ) {
3312 KMessageBox::sorry(0, i18n(
"KMail could not compress the file.") );
3313 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3317 zip.setCompression( KZip::DeflateCompression );
3318 if ( ! zip.writeFile( msgPart->name(),
"",
"", decoded.size(),
3319 decoded.data() ) ) {
3320 KMessageBox::sorry(0, i18n(
"KMail could not compress the file.") );
3321 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3325 if ( array.size() >= decoded.size() ) {
3326 if ( KMessageBox::questionYesNo(
this, i18n(
"The compressed file is larger " 3327 "than the original. Do you want to keep the original one?" ), TQString(), i18n(
"Keep"), i18n(
"Compress") )
3328 == KMessageBox::Yes ) {
3329 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3333 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setUncompressedCodec(
3334 msgPart->cteStr() );
3336 msgPart->setCteStr(
"base64" );
3337 msgPart->setBodyEncodedBinary( array );
3338 TQString name = msgPart->name() +
".zip";
3340 msgPart->setName( name );
3342 TQCString cDisp =
"attachment;";
3343 TQCString encoding = KMMsgBase::autoDetectCharset( msgPart->charset(),
3345 kdDebug(5006) <<
"encoding: " << encoding << endl;
3346 if ( encoding.isEmpty() ) encoding =
"utf-8";
3347 kdDebug(5006) <<
"encoding after: " << encoding << endl;
3349 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
3350 encName = KMMsgBase::encodeRFC2047String( name, encoding );
3352 encName = KMMsgBase::encodeRFC2231String( name, encoding );
3354 cDisp +=
"\n\tfilename";
3355 if ( name != TQString( encName ) )
3356 cDisp +=
"*=" + encName;
3358 cDisp +=
"=\"" + encName +
'"';
3359 msgPart->setContentDisposition( cDisp );
3361 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setUncompressedMimeType(
3362 msgPart->typeStr(), msgPart->subtypeStr() );
3363 msgPart->setTypeStr(
"application" );
3364 msgPart->setSubtypeStr(
"x-zip" );
3366 KMAtmListViewItem* listItem =
static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) );
3367 msgPartToItem( msgPart, listItem,
false );
3372 void KMComposeWin::uncompressAttach(
int idx )
3374 if (idx < 0)
return;
3377 for ( i = 0; i < mAtmItemList.count(); ++i )
3378 if ( mAtmItemList.at( i )->itemPos() == idx )
3381 if ( i > mAtmItemList.count() )
3384 KMMessagePart* msgPart;
3385 msgPart = mAtmList.at( i );
3387 TQBuffer dev( msgPart->bodyDecodedBinary() );
3388 KZip zip( &TQT_TQIODEVICE_OBJECT(dev) );
3389 TQByteArray decoded;
3391 decoded = msgPart->bodyDecodedBinary();
3392 if ( ! zip.open( IO_ReadOnly ) ) {
3393 KMessageBox::sorry(0, i18n(
"KMail could not uncompress the file.") );
3394 static_cast<KMAtmListViewItem *
>( mAtmItemList.at( i ) )->setCompress(
true );
3397 const KArchiveDirectory *dir = zip.directory();
3399 KZipFileEntry *entry;
3400 if ( dir->entries().count() != 1 ) {
3401 KMessageBox::sorry(0, i18n(
"KMail could not uncompress the file.") );
3402 static_cast<KMAtmListViewItem *
>( mAtmItemList.at( i ) )->setCompress(
true );
3405 entry = (KZipFileEntry*)dir->entry( dir->entries()[0] );
3408 static_cast<KMAtmListViewItem*>( mAtmItemList.at(i) )->uncompressedCodec() );
3410 msgPart->setBodyEncodedBinary( entry->data() );
3411 TQString name = entry->name();
3412 msgPart->setName( name );
3416 TQCString cDisp =
"attachment;";
3417 TQCString encoding = KMMsgBase::autoDetectCharset( msgPart->charset(),
3419 if ( encoding.isEmpty() ) encoding =
"utf-8";
3422 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
3423 encName = KMMsgBase::encodeRFC2047String( name, encoding );
3425 encName = KMMsgBase::encodeRFC2231String( name, encoding );
3427 cDisp +=
"\n\tfilename";
3428 if ( name != TQString( encName ) )
3429 cDisp +=
"*=" + encName;
3431 cDisp +=
"=\"" + encName +
'"';
3432 msgPart->setContentDisposition( cDisp );
3434 TQCString type, subtype;
3435 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->uncompressedMimeType( type,
3438 msgPart->setTypeStr( type );
3439 msgPart->setSubtypeStr( subtype );
3441 KMAtmListViewItem* listItem =
static_cast<KMAtmListViewItem*
>(mAtmItemList.at( i ));
3442 msgPartToItem( msgPart, listItem,
false );
3447 void KMComposeWin::slotAttachView()
3450 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3451 if ( (*it)->isSelected() ) {
3457 void KMComposeWin::slotAttachOpen()
3460 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3461 if ( (*it)->isSelected() ) {
3462 openAttach( i,
false );
3468 void KMComposeWin::slotAttachOpenWith()
3471 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3472 if ( (*it)->isSelected() ) {
3473 openAttach( i,
true );
3478 void KMComposeWin::slotAttachEdit()
3481 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3482 if ( (*it)->isSelected() ) {
3483 editAttach( i,
false );
3488 void KMComposeWin::slotAttachEditWith()
3491 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3492 if ( (*it)->isSelected() ) {
3493 editAttach( i,
true );
3499 bool KMComposeWin::inlineSigningEncryptionSelected() {
3500 if ( !mSignAction->isChecked() && !mEncryptAction->isChecked() )
3502 return cryptoMessageFormat() == Kleo::InlineOpenPGPFormat;
3506 void KMComposeWin::viewAttach(
int index )
3509 KMMessagePart* msgPart;
3510 msgPart = mAtmList.at(index);
3511 pname = msgPart->name().stripWhiteSpace();
3512 if (pname.isEmpty()) pname=msgPart->contentDescription();
3513 if (pname.isEmpty()) pname=
"unnamed";
3515 KTempFile* atmTempFile =
new KTempFile();
3516 mAtmTempList.append( atmTempFile );
3517 atmTempFile->setAutoDelete(
true );
3518 KPIM::kByteArrayToFile(msgPart->bodyDecodedBinary(), atmTempFile->name(),
false,
false,
3520 KMReaderMainWin *win =
new KMReaderMainWin(msgPart,
false,
3521 atmTempFile->name(), pname, mCharset );
3526 void KMComposeWin::openAttach(
int index,
bool with )
3528 KMMessagePart* msgPart = mAtmList.at(index);
3529 const TQString contentTypeStr =
3530 ( msgPart->typeStr() +
'/' + msgPart->subtypeStr() ).lower();
3532 KMimeType::Ptr mimetype;
3533 mimetype = KMimeType::mimeType( contentTypeStr );
3535 KTempFile* atmTempFile =
new KTempFile();
3536 mAtmTempList.append( atmTempFile );
3537 const bool autoDelete =
true;
3538 atmTempFile->setAutoDelete( autoDelete );
3541 url.setPath( atmTempFile->name() );
3543 KPIM::kByteArrayToFile( msgPart->bodyDecodedBinary(), atmTempFile->name(),
false,
false,
3545 if ( ::chmod( TQFile::encodeName( atmTempFile->name() ), S_IRUSR ) != 0) {
3546 TQFile::remove(url.path());
3550 KService::Ptr offer =
3551 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
3553 if ( with || !offer || mimetype->name() ==
"application/octet-stream" ) {
3554 if ( ( !KRun::displayOpenWithDialog( url, autoDelete ) ) && autoDelete ) {
3555 TQFile::remove(url.path());
3559 if ( ( !KRun::run( *offer, url, autoDelete ) ) && autoDelete ) {
3560 TQFile::remove( url.path() );
3565 void KMComposeWin::editAttach(
int index,
bool openWith)
3567 KMMessagePart* msgPart = mAtmList.at(index);
3568 const TQString contentTypeStr =
3569 ( msgPart->typeStr() +
'/' + msgPart->subtypeStr() ).lower();
3571 KTempFile* atmTempFile =
new KTempFile();
3572 mAtmTempList.append( atmTempFile );
3573 atmTempFile->setAutoDelete(
true );
3574 atmTempFile->file()->writeBlock( msgPart->bodyDecodedBinary() );
3575 atmTempFile->file()->flush();
3580 TQT_TQOBJECT(
this), this );
3582 if ( watcher->start() ) {
3583 mEditorMap.insert( watcher, msgPart );
3584 mEditorTempFiles.insert( watcher, atmTempFile );
3589 void KMComposeWin::slotAttachSave()
3591 KMMessagePart* msgPart;
3592 TQString fileName, pname;
3593 int idx = currentAttachmentNum();
3595 if (idx < 0)
return;
3597 msgPart = mAtmList.at(idx);
3598 pname = msgPart->name();
3599 if (pname.isEmpty()) pname=
"unnamed";
3601 KURL url = KFileDialog::getSaveURL(pname, TQString(), 0, i18n(
"Save Attachment As"));
3606 kmkernel->byteArrayToRemoteFile(msgPart->bodyDecodedBinary(), url);
3611 void KMComposeWin::slotAttachRemove()
3614 bool attachmentRemoved =
false;
3616 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ) {
3617 if ( (*it)->isSelected() ) {
3619 attachmentRemoved =
true;
3627 if ( attachmentRemoved ) {
3628 setModified(
true );
3629 slotUpdateAttachActions();
3630 if ( mAtmSelectNew ) {
3631 mAtmListView->setSelected( mAtmSelectNew,
true );
3632 mAtmListView->setCurrentItem( mAtmSelectNew );
3638 void KMComposeWin::slotFind()
3643 void KMComposeWin::slotSearchAgain()
3645 mEditor->repeatSearch();
3649 void KMComposeWin::slotReplace()
3655 void KMComposeWin::slotUpdateFont()
3657 kdDebug() <<
"KMComposeWin::slotUpdateFont " << endl;
3658 if ( ! mFixedFontAction ) {
3661 mEditor->setFont( mFixedFontAction->isChecked() ? mFixedFont : mBodyFont );
3664 TQString KMComposeWin::quotePrefixName()
const 3669 int languageNr = GlobalSettings::self()->replyCurrentLanguage();
3670 ReplyPhrases replyPhrases( TQString::number(languageNr) );
3671 replyPhrases.readConfig();
3672 TQString quotePrefix = msg()->formatString(
3673 replyPhrases.indentPrefix() );
3675 quotePrefix = msg()->formatString(quotePrefix);
3679 void KMComposeWin::slotPasteClipboardAsQuotation()
3681 if( mEditor->hasFocus() && msg() )
3683 TQString s = TQApplication::clipboard()->text();
3685 mEditor->insert(addQuotesToText(s));
3689 void KMComposeWin::slotPasteClipboardAsAttachment()
3691 KURL url( TQApplication::clipboard()->text( TQClipboard::Clipboard ) );
3692 if ( url.isValid() ) {
3693 addAttach(TQApplication::clipboard()->text( TQClipboard::Clipboard ) );
3697 TQMimeSource *mimeSource = TQApplication::clipboard()->data();
3698 if ( TQImageDrag::canDecode(mimeSource) ) {
3699 slotAttachPNGImageData(mimeSource->encodedData(
"image/png"));
3703 TQString attName = KInputDialog::getText(
"KMail", i18n(
"Name of the attachment:"), TQString(), &ok,
this );
3706 KMMessagePart *msgPart =
new KMMessagePart;
3707 msgPart->setName(attName);
3708 TQValueList<int> dummy;
3709 msgPart->setBodyAndGuessCte(TQCString(TQApplication::clipboard()->text().latin1()), dummy,
3710 kmkernel->msgSender()->sendQuotedPrintable());
3715 void KMComposeWin::slotAddQuotes()
3717 if( mEditor->hasFocus() && msg() )
3723 if ( mEditor->hasMarkedText() ) {
3724 TQString s = mEditor->markedText();
3726 mEditor->insert(addQuotesToText(s));
3728 int l = mEditor->currentLine();
3729 int c = mEditor->currentColumn();
3730 TQString s = mEditor->textLine(l);
3731 s.prepend(quotePrefixName());
3732 mEditor->insertLine(s,l);
3733 mEditor->removeLine(l+1);
3734 mEditor->setCursorPosition(l,c+2);
3739 TQString KMComposeWin::addQuotesToText(
const TQString &inputText)
3741 TQString answer = TQString( inputText );
3742 TQString indentStr = quotePrefixName();
3743 answer.replace(
'\n',
'\n' + indentStr);
3744 answer.prepend( indentStr );
3749 TQString KMComposeWin::removeQuotesFromText(
const TQString &inputText)
3751 TQString s = inputText;
3754 TQString quotePrefix =
'^' + quotePrefixName();
3755 TQRegExp rx(quotePrefix);
3759 quotePrefix =
'\n' + quotePrefixName();
3761 s.replace(rx,
"\n");
3766 void KMComposeWin::slotRemoveQuotes()
3768 if( mEditor->hasFocus() && msg() )
3774 if ( mEditor->hasMarkedText() ) {
3775 TQString s = mEditor->markedText();
3776 mEditor->insert(removeQuotesFromText(s));
3778 int l = mEditor->currentLine();
3779 int c = mEditor->currentColumn();
3780 TQString s = mEditor->textLine(l);
3781 mEditor->insertLine(removeQuotesFromText(s),l);
3782 mEditor->removeLine(l+1);
3783 mEditor->setCursorPosition(l,c-2);
3789 void KMComposeWin::slotUndo()
3791 TQWidget* fw = focusWidget();
3794 if ( ::tqqt_cast<KEdit*>(fw) )
3795 static_cast<TQTextEdit*
>(fw)->undo();
3796 else if (::tqqt_cast<TQLineEdit*>(fw))
3797 static_cast<TQLineEdit*>(fw)->undo();
3800 void KMComposeWin::slotRedo()
3802 TQWidget* fw = focusWidget();
3805 if (::tqqt_cast<KEdit*>(fw))
3806 static_cast<KEdit*
>(fw)->redo();
3807 else if (::tqqt_cast<TQLineEdit*>(fw))
3808 static_cast<TQLineEdit*>(fw)->redo();
3812 void KMComposeWin::slotCut()
3814 TQWidget* fw = focusWidget();
3817 if (::tqqt_cast<KEdit*>(fw))
3818 static_cast<KEdit*
>(fw)->cut();
3819 else if (::tqqt_cast<TQLineEdit*>(fw))
3820 static_cast<TQLineEdit*>(fw)->cut();
3825 void KMComposeWin::slotCopy()
3827 TQWidget* fw = focusWidget();
3834 TQKeyEvent k(TQEvent::KeyPress, Key_C, 0, ControlButton);
3835 kapp->notify(TQT_TQOBJECT(fw), TQT_TQEVENT(&k));
3840 void KMComposeWin::slotPasteClipboard()
3842 paste( TQClipboard::Clipboard );
3845 void KMComposeWin::paste( TQClipboard::Mode mode )
3847 TQWidget* fw = focusWidget();
3850 TQMimeSource *mimeSource = TQApplication::clipboard()->data( mode );
3851 if ( mimeSource->provides(
"image/png") ) {
3852 slotAttachPNGImageData(mimeSource->encodedData(
"image/png"));
3853 }
else if ( KURLDrag::canDecode( mimeSource ) ) {
3855 if( KURLDrag::decode( mimeSource, urlList ) ) {
3856 const TQString asText = i18n(
"Add as Text");
3857 const TQString asAttachment = i18n(
"Add as Attachment");
3858 const TQString text = i18n(
"Please select whether you want to insert the content as text into the editor, " 3859 "or append the referenced file as an attachment.");
3860 const TQString caption = i18n(
"Paste as text or attachment?");
3862 int id = KMessageBox::questionYesNoCancel(
this, text, caption,
3863 KGuiItem( asText ), KGuiItem( asAttachment) );
3865 case KMessageBox::Yes:
3866 for ( KURL::List::Iterator it = urlList.begin();
3867 it != urlList.end(); ++it ) {
3868 mEditor->insert( (*it).url() );
3871 case KMessageBox::No:
3872 for ( KURL::List::Iterator it = urlList.begin();
3873 it != urlList.end(); ++it ) {
3879 }
else if ( TQTextDrag::canDecode( mimeSource ) ) {
3881 if ( TQTextDrag::decode( mimeSource, s ) )
3882 mEditor->insert( s );
3888 void KMComposeWin::slotMarkAll()
3890 TQWidget* fw = focusWidget();
3893 if (::tqqt_cast<TQLineEdit*>(fw))
3894 static_cast<TQLineEdit*
>(fw)->selectAll();
3895 else if (::tqqt_cast<KEdit*>(fw))
3896 static_cast<KEdit*>(fw)->selectAll();
3901 void KMComposeWin::slotClose()
3908 void KMComposeWin::slotNewComposer()
3914 win =
new KMComposeWin(msg);
3920 void KMComposeWin::slotNewMailReader()
3922 KMMainWin *kmmwin =
new KMMainWin(0);
3929 void KMComposeWin::slotUpdWinTitle(
const TQString& text)
3935 setCaption(
"("+i18n(
"unnamed")+
")");
3936 else setCaption( s.replace( TQChar(
'\n'),
' ' ) );
3941 void KMComposeWin::slotEncryptToggled(
bool on)
3943 setEncryption( on,
true );
3944 slotUpdateSignatureAndEncrypionStateIndicators();
3949 void KMComposeWin::setEncryption(
bool encrypt,
bool setByUser )
3951 bool wasModified = isModified();
3953 setModified(
true );
3954 if ( !mEncryptAction->isEnabled() )
3958 else if ( encrypt && encryptToSelf() && !mLastIdentityHasEncryptionKey ) {
3960 KMessageBox::sorry(
this,
3961 i18n(
"<qt><p>You have requested that messages be " 3962 "encrypted to yourself, but the currently selected " 3963 "identity does not define an (OpenPGP or S/MIME) " 3964 "encryption key to use for this.</p>" 3965 "<p>Please select the key(s) to use " 3966 "in the identity configuration.</p>" 3968 i18n(
"Undefined Encryption Key") );
3969 setModified( wasModified );
3975 mEncryptAction->setChecked( encrypt );
3979 mEncryptAction->setIcon(
"encrypted");
3981 mEncryptAction->setIcon(
"decrypted");
3984 if ( canSignEncryptAttachments() ) {
3985 for ( KMAtmListViewItem* entry =
3986 static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
3988 entry =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) )
3989 entry->setEncrypt( encrypt );
3995 void KMComposeWin::slotSignToggled(
bool on)
3997 setSigning( on,
true );
3998 slotUpdateSignatureAndEncrypionStateIndicators();
4003 void KMComposeWin::setSigning(
bool sign,
bool setByUser )
4005 bool wasModified = isModified();
4007 setModified(
true );
4008 if ( !mSignAction->isEnabled() )
4012 if ( sign && !mLastIdentityHasSigningKey ) {
4014 KMessageBox::sorry(
this,
4015 i18n(
"<qt><p>In order to be able to sign " 4016 "this message you first have to " 4017 "define the (OpenPGP or S/MIME) signing key " 4019 "<p>Please select the key to use " 4020 "in the identity configuration.</p>" 4022 i18n(
"Undefined Signing Key") );
4023 setModified( wasModified );
4029 mSignAction->setChecked( sign );
4032 if ( canSignEncryptAttachments() ) {
4033 for ( KMAtmListViewItem* entry =
4034 static_cast<KMAtmListViewItem*>( mAtmItemList.first() );
4036 entry =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) )
4037 entry->setSign( sign );
4043 void KMComposeWin::slotWordWrapToggled(
bool on)
4047 mEditor->setWordWrap( TQTextEdit::FixedColumnWidth );
4048 mEditor->setWrapColumnOrWidth( GlobalSettings::self()->lineWrapWidth() );
4052 mEditor->setWordWrap( TQTextEdit::WidgetWidth );
4057 void KMComposeWin::disableWordWrap()
4059 mEditor->setWordWrap( TQTextEdit::NoWrap );
4062 void KMComposeWin::disableRecipientNumberCheck()
4064 mCheckForRecipients =
false;
4067 void KMComposeWin::disableForgottenAttachmentsCheck()
4069 mCheckForForgottenAttachments =
false;
4072 void KMComposeWin::ignoreStickyFields()
4074 mIgnoreStickyFields =
true;
4075 mBtnTransport->setChecked(
false );
4076 mBtnDictionary->setChecked(
false );
4077 mBtnIdentity->setChecked(
false );
4078 mBtnTransport->setEnabled(
false );
4079 mBtnDictionary->setEnabled(
false );
4080 mBtnIdentity->setEnabled(
false );
4084 void KMComposeWin::slotPrint()
4086 mMessageWasModified = isModified();
4087 connect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
4088 TQT_TQOBJECT(
this), TQT_SLOT( slotContinuePrint(
bool ) ) );
4089 applyChanges(
true );
4092 void KMComposeWin::slotContinuePrint(
bool rc )
4094 disconnect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
4095 TQT_TQOBJECT(
this), TQT_SLOT( slotContinuePrint(
bool ) ) );
4098 if ( mComposedMessages.isEmpty() ) {
4099 kdDebug(5006) <<
"Composing the message failed." << endl;
4102 KMCommand *command =
new KMPrintCommand(
this, mComposedMessages.first() );
4104 setModified( mMessageWasModified );
4109 bool KMComposeWin::validateAddresses( TQWidget * parent,
const TQString & addresses )
4111 TQString brokenAddress;
4113 if ( !( errorCode == KPIM::AddressOk || errorCode == KPIM::AddressEmpty ) ) {
4114 TQString errorMsg(
"<qt><p><b>" + brokenAddress +
4115 "</b></p><p>" + KPIM::emailParseResultToString( errorCode ) +
4117 KMessageBox::sorry( parent, errorMsg, i18n(
"Invalid Email Address") );
4124 void KMComposeWin::doSend( KMail::MessageSender::SendMethod method,
4125 KMComposeWin::SaveIn saveIn )
4127 if ( method != KMail::MessageSender::SendLater && kmkernel->isOffline() ) {
4128 KMessageBox::information(
this,
4129 i18n(
"KMail is currently in offline mode," 4130 "your messages will be kept in the outbox until you go online."),
4131 i18n(
"Online/Offline"),
"kmailIsOffline" );
4132 mSendMethod = KMail::MessageSender::SendLater;
4134 mSendMethod = method;
4138 if ( saveIn == KMComposeWin::None ) {
4139 if ( KPIM::getFirstEmailAddress( from() ).isEmpty() ) {
4140 if ( !( mShowHeaders & HDR_FROM ) ) {
4141 mShowHeaders |= HDR_FROM;
4142 rethinkFields(
false );
4144 mEdtFrom->setFocus();
4145 KMessageBox::sorry(
this,
4146 i18n(
"You must enter your email address in the " 4147 "From: field. You should also set your email " 4148 "address for all identities, so that you do " 4149 "not have to enter it for each message.") );
4152 if ( to().isEmpty() )
4154 if ( cc().isEmpty() && bcc().isEmpty()) {
4155 if ( mEdtTo ) mEdtTo->setFocus();
4156 KMessageBox::information(
this,
4157 i18n(
"You must specify at least one receiver," 4158 "either in the To: field or as CC or as BCC.") );
4162 if ( mEdtTo ) mEdtTo->setFocus();
4164 KMessageBox::questionYesNo(
this,
4165 i18n(
"To field is missing." 4166 "Send message anyway?"),
4167 i18n(
"No To: specified") );
4168 if ( rc == KMessageBox::No ){
4175 if ( !validateAddresses(
this, to().stripWhiteSpace() ) ) {
4179 if ( !validateAddresses(
this, cc().stripWhiteSpace() ) ) {
4183 if ( !validateAddresses(
this, bcc().stripWhiteSpace() ) ) {
4187 if (subject().isEmpty())
4189 mEdtSubject->setFocus();
4191 KMessageBox::questionYesNo(
this,
4192 i18n(
"You did not specify a subject. " 4193 "Send message anyway?"),
4194 i18n(
"No Subject Specified"),
4195 i18n(
"S&end as Is"),
4196 i18n(
"&Specify the Subject"),
4197 "no_subject_specified" );
4198 if( rc == KMessageBox::No )
4204 if ( userForgotAttachment() )
4209 mMsg->setDateToday();
4216 TQString hf = mMsg->headerField(
"X-KMail-Transport");
4217 if ((mTransport->currentText() != mTransport->text(0)) ||
4218 (!hf.isEmpty() && (hf != mTransport->text(0))))
4219 mMsg->setHeaderField(
"X-KMail-Transport", mTransport->currentText());
4221 mDisableBreaking = ( saveIn != KMComposeWin::None );
4223 const bool neverEncrypt = ( mDisableBreaking && GlobalSettings::self()->neverEncryptDrafts() )
4224 || mSigningAndEncryptionExplicitlyDisabled;
4225 connect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
4226 TQT_SLOT( slotContinueDoSend(
bool ) ) );
4228 if ( mEditor->textFormat() == TQt::RichText )
4229 mMsg->setHeaderField(
"X-KMail-Markup",
"true" );
4231 mMsg->removeHeaderField(
"X-KMail-Markup" );
4232 if ( mEditor->textFormat() == TQt::RichText && inlineSigningEncryptionSelected() ) {
4233 TQString keepBtnText = mEncryptAction->isChecked() ?
4234 mSignAction->isChecked() ? i18n(
"&Keep markup, do not sign/encrypt" )
4235 : i18n(
"&Keep markup, do not encrypt" )
4236 : i18n(
"&Keep markup, do not sign" );
4237 TQString yesBtnText = mEncryptAction->isChecked() ?
4238 mSignAction->isChecked() ? i18n(
"Sign/Encrypt (delete markup)")
4239 : i18n(
"Encrypt (delete markup)" )
4240 : i18n(
"Sign (delete markup)" );
4241 int ret = KMessageBox::warningYesNoCancel(
this,
4242 i18n(
"<qt><p>Inline signing/encrypting of HTML messages is not possible;</p>" 4243 "<p>do you want to delete your markup?</p></qt>"),
4244 i18n(
"Sign/Encrypt Message?"),
4245 KGuiItem( yesBtnText ),
4246 KGuiItem( keepBtnText ) );
4247 if ( KMessageBox::Cancel == ret )
4249 if ( KMessageBox::No == ret ) {
4250 mEncryptAction->setChecked(
false);
4251 mSignAction->setChecked(
false);
4254 toggleMarkup(
false);
4258 if (neverEncrypt && saveIn != KMComposeWin::None ) {
4261 mMsg->setHeaderField(
"X-KMail-SignatureActionEnabled", mSignAction->isChecked()?
"true":
"false" );
4262 mMsg->setHeaderField(
"X-KMail-EncryptActionEnabled", mEncryptAction->isChecked()?
"true":
"false" );
4263 mMsg->setHeaderField(
"X-KMail-CryptoMessageFormat", TQString::number( cryptoMessageFormat() ) );
4265 mMsg->removeHeaderField(
"X-KMail-SignatureActionEnabled" );
4266 mMsg->removeHeaderField(
"X-KMail-EncryptActionEnabled" );
4267 mMsg->removeHeaderField(
"X-KMail-CryptoMessageFormat" );
4271 kdDebug(5006) <<
"KMComposeWin::doSend() - calling applyChanges()" 4273 applyChanges( neverEncrypt );
4276 bool KMComposeWin::saveDraftOrTemplate(
const TQString &folderName,
4279 KMFolder *theFolder = 0, *imapTheFolder = 0;
4281 if ( !folderName.isEmpty() ) {
4282 theFolder = kmkernel->folderMgr()->findIdString( folderName );
4283 if ( theFolder == 0 )
4286 theFolder = kmkernel->dimapFolderMgr()->findIdString( folderName );
4287 if ( theFolder == 0 )
4288 imapTheFolder = kmkernel->imapFolderMgr()->findIdString( folderName );
4289 if ( !theFolder && !imapTheFolder ) {
4290 const KPIM::Identity &
id = kmkernel->identityManager()
4291 ->identityForUoidOrDefault( msg->
headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
4292 KMessageBox::information( 0,
4293 i18n(
"The custom drafts or templates folder for " 4294 "identify \"%1\" does not exist (anymore); " 4295 "therefore, the default drafts or templates " 4296 "folder will be used.")
4297 .arg(
id.identityName() ) );
4300 if ( imapTheFolder && imapTheFolder->noContent() )
4303 bool didOpen =
false;
4304 if ( theFolder == 0 ) {
4305 theFolder = ( mSaveIn==KMComposeWin::Drafts ?
4306 kmkernel->draftsFolder() : kmkernel->templatesFolder() );
4309 theFolder->
open(
"composer" );
4312 kdDebug(5006) << k_funcinfo <<
"theFolder=" << theFolder->name() << endl;
4313 if ( imapTheFolder )
4314 kdDebug(5006) << k_funcinfo <<
"imapTheFolder=" << imapTheFolder->name() << endl;
4316 bool sentOk = !( theFolder->
addMsg( msg ) );
4320 msg = theFolder->
getMsg( theFolder->
count() - 1 );
4323 if ( imapTheFolder ) {
4325 imapTheFolder->moveMsg( msg );
4326 (
static_cast<KMFolderImap*
>( imapTheFolder->storage() ))->getFolder();
4330 theFolder->
close(
"composer" );
4334 void KMComposeWin::slotContinueDoSend(
bool sentOk )
4336 kdDebug(5006) <<
"KMComposeWin::slotContinueDoSend( " << sentOk <<
" )" 4338 disconnect(
this, TQT_SIGNAL( applyChangesDone(
bool ) ),
4339 TQT_TQOBJECT(
this), TQT_SLOT( slotContinueDoSend(
bool ) ) );
4342 mDisableBreaking =
false;
4346 for ( TQValueVector<KMMessage*>::iterator it = mComposedMessages.begin() ; it != mComposedMessages.end() ; ++it ) {
4349 (*it)->cleanupHeader();
4352 (*it)->setComplete(
true );
4354 if ( mSaveIn==KMComposeWin::Drafts ) {
4355 sentOk = saveDraftOrTemplate( (*it)->drafts(), (*it) );
4356 }
else if ( mSaveIn==KMComposeWin::Templates ) {
4357 sentOk = saveDraftOrTemplate( (*it)->templates(), (*it) );
4361 if( !mComposer->originalBCC().isEmpty() )
4363 TQString recips = (*it)->headerField(
"X-KMail-Recipients" );
4364 if( !recips.isEmpty() ) {
4367 (*it)->cleanupHeader();
4368 sentOk = kmkernel->msgSender()->send((*it), mSendMethod);
4377 RecentAddresses::self( KMKernel::config() )->add( bcc() );
4378 RecentAddresses::self( KMKernel::config() )->add( cc() );
4379 RecentAddresses::self( KMKernel::config() )->add( to() );
4381 setModified(
false );
4382 mAutoDeleteMsg =
false;
4389 bool KMComposeWin::checkTransport()
const 4392 KMessageBox::information( mMainWidget,
4393 i18n(
"Please create an account for sending and try again.") );
4401 void KMComposeWin::slotSendLater()
4403 if ( !checkTransport() )
4405 if ( !checkRecipientNumber() )
4407 if ( mEditor->checkExternalEditorFinished() )
4408 doSend( KMail::MessageSender::SendLater );
4413 void KMComposeWin::slotSaveDraft() {
4414 if ( mEditor->checkExternalEditorFinished() )
4415 doSend( KMail::MessageSender::SendLater, KMComposeWin::Drafts );
4419 void KMComposeWin::slotSaveTemplate() {
4420 if ( mEditor->checkExternalEditorFinished() )
4421 doSend( KMail::MessageSender::SendLater, KMComposeWin::Templates );
4425 void KMComposeWin::slotSendNowVia(
int item )
4428 TQString customTransport = availTransports[ item ];
4430 mTransport->setCurrentText( customTransport );
4435 void KMComposeWin::slotSendLaterVia(
int item )
4438 TQString customTransport = availTransports[ item ];
4440 mTransport->setCurrentText( customTransport );
4446 void KMComposeWin::slotSendNow() {
4447 if ( !mEditor->checkExternalEditorFinished() )
4449 if ( !checkTransport() )
4451 if ( !checkRecipientNumber() )
4453 if ( GlobalSettings::self()->confirmBeforeSend() )
4455 int rc = KMessageBox::warningYesNoCancel( mMainWidget,
4456 i18n(
"About to send email..."),
4457 i18n(
"Send Confirmation"),
4459 i18n(
"Send &Later") );
4461 if ( rc == KMessageBox::Yes )
4462 doSend( KMail::MessageSender::SendImmediate );
4463 else if ( rc == KMessageBox::No )
4464 doSend( KMail::MessageSender::SendLater );
4467 doSend( KMail::MessageSender::SendImmediate );
4472 bool KMComposeWin::checkRecipientNumber()
const 4474 uint thresHold = GlobalSettings::self()->recipientThreshold();
4475 if ( mCheckForRecipients &&
4476 GlobalSettings::self()->tooManyRecipients() &&
4477 mRecipientsEditor->recipients().count() > thresHold ) {
4478 if ( KMessageBox::questionYesNo( mMainWidget,
4479 i18n(
"You are trying to send the mail to more than %1 recipients. Send message anyway?").arg(thresHold),
4480 i18n(
"Too many receipients"),
4481 i18n(
"&Send as Is"),
4482 i18n(
"&Edit Recipients")) == KMessageBox::No ) {
4491 void KMComposeWin::slotAppendSignature()
4497 void KMComposeWin::slotPrependSignature()
4499 insertSignature( Prepend );
4503 void KMComposeWin::slotInsertSignatureAtCursor()
4505 insertSignature( AtCursor );
4509 void KMComposeWin::insertSignature( SignaturePlacement placement )
4511 bool mod = mEditor->isModified();
4513 const KPIM::Identity &ident =
4514 kmkernel->identityManager()->
4515 identityForUoidOrDefault( mIdentity->currentIdentity() );
4517 mOldSigText = GlobalSettings::self()->prependSignature()? ident.signature().rawText() : ident.signatureText();
4519 if( !mOldSigText.isEmpty() )
4522 int paragraph, index;
4523 mEditor->getCursorPosition( ¶graph, &index );
4524 index = mEditor->indexOfCurrentLineStart( paragraph, index );
4526 switch( placement ) {
4528 mEditor->setText( mEditor->text() + mOldSigText );
4531 mOldSigText =
"\n\n" + mOldSigText +
"\n";
4532 mEditor->insertAt( mOldSigText, paragraph, index );
4539 if ( mEditor->paragraphLength( paragraph ) > 0 )
4540 mOldSigText = mOldSigText +
"\n";
4541 if ( mOldSigText.startsWith(
"\n" ) )
4542 mOldSigText = mOldSigText.remove( 0, 1 );
4547 mOldSigText =
"\n" + mOldSigText;
4549 mEditor->insertAt( mOldSigText, paragraph, index );
4553 mEditor->setModified(mod);
4555 if ( mPreserveUserCursorPosition ) {
4556 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
4561 mPreserveUserCursorPosition =
false;
4566 mEditor->setCursorPosition( paragraph, 0 );
4569 mEditor->setCursorPosition( paragraph + 1, 0 );
4571 if ( placement == Prepend || placement == Append )
4572 mEditor->setContentsPos( 0, 0 );
4579 void KMComposeWin::slotHelp()
4585 void KMComposeWin::slotCleanSpace()
4596 if ( mEditor->hasMarkedText() ) {
4597 s = mEditor->markedText();
4601 s = mEditor->text();
4606 bool restore =
false;
4607 const KPIM::Identity & ident =
4608 kmkernel->identityManager()->identityForUoid( mId );
4609 if ( !ident.isNull() ) {
4610 sig = ident.signatureText();
4611 if( !sig.isEmpty() ) {
4612 if( s.endsWith( sig ) ) {
4613 s.truncate( s.length() - sig.length() );
4620 TQRegExp squeeze(
"[\t ]+" );
4621 s.replace( squeeze, TQChar(
' ' ) );
4624 TQRegExp trailing(
"\\s+$" );
4625 s.replace( trailing, TQChar(
'\n' ) );
4628 TQRegExp singleSpace(
"[\n]{2,}" );
4629 s.replace( singleSpace, TQChar(
'\n' ) );
4642 if ( !mEditor->hasMarkedText() )
4644 mEditor->insert( s );
4648 void KMComposeWin::slotToggleMarkup()
4650 if ( markupAction->isChecked() ) {
4652 toolBar(
"htmlToolBar")->show();
4654 fontChanged( mEditor->currentFont() );
4655 mSaveFont = mEditor->currentFont();
4658 toggleMarkup(
false);
4662 void KMComposeWin::toggleMarkup(
bool markup)
4665 if ( !mUseHTMLEditor ) {
4666 kdDebug(5006) <<
"setting RichText editor" << endl;
4667 mUseHTMLEditor =
true;
4671 int paraFrom, indexFrom, paraTo, indexTo;
4672 mEditor->getSelection ( ¶From, &indexFrom, ¶To, &indexTo);
4673 mEditor->selectAll();
4675 bool _bold = textBoldAction->isChecked();
4676 bool _italic = textItalicAction->isChecked();
4677 mEditor->setColor(TQColor(0,0,0));
4678 textBoldAction->setChecked(_bold);
4679 textItalicAction->setChecked(_italic);
4680 mEditor->setSelection ( paraFrom, indexFrom, paraTo, indexTo);
4682 mEditor->setTextFormat(TQt::RichText);
4683 mEditor->setModified(
true);
4684 markupAction->setChecked(
true);
4685 toolBar(
"htmlToolBar" )->show();
4686 mEditor->deleteAutoSpellChecking();
4687 mAutoSpellCheckingAction->setChecked(
false);
4688 slotAutoSpellCheckingToggled(
false);
4691 kdDebug(5006) <<
"setting PlainText editor" << endl;
4692 mHtmlMarkup =
false;
4693 toolBar(
"htmlToolBar")->hide();
4694 if ( mUseHTMLEditor ) {
4695 mUseHTMLEditor =
false;
4696 mEditor->setTextFormat(TQt::PlainText);
4697 TQString text = mEditor->text();
4698 mEditor->setText(text);
4699 mEditor->setModified(
true);
4700 slotAutoSpellCheckingToggled(
true);
4705 void KMComposeWin::htmlToolBarVisibilityChanged(
bool visible )
4709 markupAction->setChecked(
false );
4710 toggleMarkup(
false );
4714 void KMComposeWin::slotSubjectTextSpellChecked()
4716 mSubjectTextWasSpellChecked =
true;
4720 void KMComposeWin::slotAutoSpellCheckingToggled(
bool on )
4722 if ( mEditor->autoSpellChecking(on) == -1 ) {
4723 mAutoSpellCheckingAction->setChecked(
false);
4728 temp = i18n(
"Spellcheck: on" );
4730 temp = i18n(
"Spellcheck: off" );
4731 statusBar()->changeItem( temp, 3 );
4734 void KMComposeWin::slotSpellcheck()
4736 if (mSpellCheckInProgress)
return;
4737 mSubjectTextWasSpellChecked =
false;
4738 mSpellCheckInProgress=
true;
4744 mEditor->spellcheck();
4747 void KMComposeWin::slotUpdateSignatureActions()
4751 const KPIM::Identity & ident =
4752 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
4753 TQString sig = ident.signatureText();
4755 if ( sig.isEmpty() ) {
4756 mAppendSignatureAction->setEnabled(
false );
4757 mPrependSignatureAction->setEnabled(
false );
4758 mInsertSignatureAction->setEnabled(
false );
4761 mAppendSignatureAction->setEnabled(
true );
4762 mPrependSignatureAction->setEnabled(
true );
4763 mInsertSignatureAction->setEnabled(
true );
4767 void KMComposeWin::polish()
4770 markupAction->setChecked(mHtmlMarkup);
4772 toolBar(
"htmlToolBar")->show();
4774 toolBar(
"htmlToolBar")->hide();
4775 KMail::Composer::polish();
4779 void KMComposeWin::slotSpellcheckDone(
int result)
4781 kdDebug(5006) <<
"spell check complete: result = " << result << endl;
4782 mSpellCheckInProgress=
false;
4787 statusBar()->changeItem(i18n(
" Spell check canceled."),0);
4790 statusBar()->changeItem(i18n(
" Spell check stopped."),0);
4793 statusBar()->changeItem(i18n(
" Spell check complete."),0);
4796 TQTimer::singleShot( 2000,
this, TQT_SLOT(slotSpellcheckDoneClearStatus()) );
4799 void KMComposeWin::slotSpellcheckDoneClearStatus()
4801 statusBar()->changeItem(
"", 0);
4806 void KMComposeWin::slotIdentityChanged( uint uoid )
4808 const KPIM::Identity & ident =
4809 kmkernel->identityManager()->identityForUoid( uoid );
4810 if( ident.isNull() )
return;
4813 slotUpdateSignatureActions();
4815 if( !ident.fullEmailAddr().isNull() )
4816 mEdtFrom->setText(ident.fullEmailAddr());
4818 if ( KPIM::getFirstEmailAddress( from() ).isEmpty() )
4819 mShowHeaders |= HDR_FROM;
4820 if ( mEdtReplyTo ) mEdtReplyTo->setText(ident.replyToAddr());
4822 if ( mRecipientsEditor ) {
4824 const KPIM::Identity & oldIdentity =
4825 kmkernel->identityManager()->identityForUoidOrDefault( mId );
4826 if ( oldIdentity.bcc() != ident.bcc() ) {
4827 mRecipientsEditor->removeRecipient( oldIdentity.bcc(), Recipient::Bcc );
4828 mRecipientsEditor->addRecipient( ident.bcc(), Recipient::Bcc );
4829 mRecipientsEditor->setFocusBottom();
4835 if( mEdtBcc && !mEdtBcc->edited() && !ident.bcc().isEmpty() ) {
4838 if( !mEdtBcc->text().isEmpty() && mEdtBcc->text() != ident.bcc() && !mEdtBcc->edited() ) {
4839 mEdtBcc->setText( ident.bcc() );
4844 if ( mEdtBcc->text() != ident.bcc() && !mEdtBcc->text().isEmpty() ) {
4845 TQString temp_string( mEdtBcc->text() + TQString::fromLatin1(
",") + ident.bcc() );
4846 mEdtBcc->setText( temp_string );
4850 mEdtBcc->setText( ident.bcc() );
4857 if( mEdtBcc && mEdtBcc->edited() && !ident.bcc().isEmpty() ) {
4858 if( !mEdtBcc->text().isEmpty() ) {
4859 TQString temp_string ( mEdtBcc->text() + TQString::fromLatin1(
",") + ident.bcc() );
4860 mEdtBcc->setText( temp_string );
4862 mEdtBcc->setText( ident.bcc() );
4868 if( mEdtBcc && !mEdtBcc->edited() && ident.bcc().isEmpty() ) {
4869 mEdtBcc->setText( ident.bcc() );
4872 if ( !ident.bcc().isEmpty() ) {
4873 mShowHeaders |= HDR_BCC;
4876 if ( ident.organization().isEmpty() )
4877 mMsg->removeHeaderField(
"Organization");
4879 mMsg->setHeaderField(
"Organization", ident.organization());
4881 if (!ident.isXFaceEnabled() || ident.xface().isEmpty())
4882 mMsg->removeHeaderField(
"X-Face");
4885 TQString xface = ident.xface();
4886 if (!xface.isEmpty())
4888 int numNL = ( xface.length() - 1 ) / 70;
4889 for (
int i = numNL; i > 0; --i )
4890 xface.insert( i*70,
"\n\t" );
4891 mMsg->setHeaderField(
"X-Face", xface);
4895 if ( !mBtnTransport->isChecked() && !mIgnoreStickyFields ) {
4896 TQString transp = ident.transport();
4897 if ( transp.isEmpty() )
4899 mMsg->removeHeaderField(
"X-KMail-Transport");
4900 transp = GlobalSettings::self()->defaultTransport();
4903 mMsg->setHeaderField(
"X-KMail-Transport", transp);
4904 setTransport( transp );
4907 if ( !mBtnDictionary->isChecked() && !mIgnoreStickyFields ) {
4908 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
4911 if ( !mBtnFcc->isChecked() && !mPreventFccOverwrite ) {
4912 setFcc( ident.fcc() );
4915 TQString edtText = mEditor->text();
4917 if ( mOldSigText.isEmpty() ) {
4918 const KPIM::Identity &
id =
4921 identityForUoidOrDefault( mMsg->headerField(
"X-KMail-Identity" ).
4922 stripWhiteSpace().toUInt() );
4923 mOldSigText = GlobalSettings::self()->prependSignature() ?
id.signature().rawText() :
id.signatureText();
4927 if ( !GlobalSettings::prependSignature() ) {
4930 while ( !edtText.isEmpty() && edtText[edtText.length()-1].isSpace() )
4931 edtText.truncate( edtText.length() - 1 );
4933 while ( !mOldSigText.isEmpty() && mOldSigText[mOldSigText.length()-1].isSpace() )
4934 mOldSigText.truncate( mOldSigText.length() - 1 );
4936 if ( edtText.endsWith( mOldSigText ) )
4937 edtText.truncate( edtText.length() - mOldSigText.length() );
4940 mOldSigText = ident.signatureText();
4941 if( ( !mOldSigText.isEmpty() ) &&
4942 ( GlobalSettings::self()->autoTextSignature() ==
"auto" ) ) {
4943 edtText.append( mOldSigText );
4945 mEditor->setText( edtText );
4947 const int pos = edtText.find( mOldSigText );
4948 if ( pos >= 0 && !mOldSigText.isEmpty() ) {
4949 const int oldLength = mOldSigText.length();
4950 mOldSigText =
"\n\n"+ ident.signature().rawText() +
"\n";
4951 edtText = edtText.replace( pos, oldLength, mOldSigText );
4952 mEditor->setText( edtText );
4954 insertSignature( Append );
4960 bool bNewIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
4961 bool bNewIdentityHasEncryptionKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
4962 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
4963 !ident.pgpEncryptionKey().isEmpty() );
4965 if ( !bNewIdentityHasEncryptionKey && mLastIdentityHasEncryptionKey ) {
4966 mLastEncryptActionState = mEncryptAction->isChecked();
4967 setEncryption(
false );
4969 if ( !bNewIdentityHasSigningKey && mLastIdentityHasSigningKey ) {
4970 mLastSignActionState = mSignAction->isChecked();
4971 setSigning(
false );
4974 if ( bNewIdentityHasEncryptionKey && !mLastIdentityHasEncryptionKey )
4975 setEncryption( mLastEncryptActionState );
4976 if ( bNewIdentityHasSigningKey && !mLastIdentityHasSigningKey )
4977 setSigning( mLastSignActionState );
4979 mLastIdentityHasSigningKey = bNewIdentityHasSigningKey;
4980 mLastIdentityHasEncryptionKey = bNewIdentityHasEncryptionKey;
4982 setModified(
true );
4986 rethinkFields(
false );
4990 void KMComposeWin::slotSpellcheckConfig()
4992 KDialogBase dlg(KDialogBase::Plain, i18n(
"Spellchecker"),
4993 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok,
4994 TQT_TQWIDGET(
this), 0,
true,
true );
4996 TQTabDialog qtd (
this,
"tabdialog",
true);
4997 KSpellConfig mKSpellConfig (&qtd);
4998 mKSpellConfig.layout()->setMargin( KDialog::marginHint() );
5000 qtd.addTab (&mKSpellConfig, i18n(
"Spellchecker"));
5001 qtd.setCancelButton ();
5003 twin.setIcons (qtd.winId(), kapp->icon(), kapp->miniIcon());
5004 qtd.setCancelButton(KStdGuiItem::cancel().text());
5005 qtd.setOkButton(KStdGuiItem::ok().text());
5008 mKSpellConfig.writeGlobalSettings();
5012 void KMComposeWin::slotStatusMessage(
const TQString &message)
5014 statusBar()->changeItem( message, 0 );
5017 void KMComposeWin::slotEditToolbars()
5019 saveMainWindowSettings(KMKernel::config(),
"Composer");
5020 KEditToolbar dlg(guiFactory(),
this);
5022 connect( &dlg, TQT_SIGNAL(newToolbarConfig()),
5023 TQT_SLOT(slotUpdateToolbars()) );
5028 void KMComposeWin::slotUpdateToolbars()
5030 createGUI(
"kmcomposerui.rc");
5031 applyMainWindowSettings(KMKernel::config(),
"Composer");
5034 void KMComposeWin::slotEditKeys()
5036 KKeyDialog::configure( actionCollection(),
5041 void KMComposeWin::setReplyFocus(
bool hasMessage )
5043 mEditor->setFocus();
5045 if( mMsg->getCursorPos() ) {
5046 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
5048 mEditor->setCursorPosition( 1, 0 );
5053 void KMComposeWin::setFocusToSubject()
5055 mEdtSubject->setFocus();
5058 int KMComposeWin::autoSaveInterval()
const 5060 return GlobalSettings::self()->autosaveInterval() * 1000 * 60;
5063 void KMComposeWin::initAutoSave()
5065 kdDebug(5006) << k_funcinfo << endl;
5068 if ( mAutoSaveFilename.isEmpty() ) {
5069 mAutoSaveFilename = KMFolderMaildir::constructValidFileName();
5075 void KMComposeWin::updateAutoSave()
5077 if ( autoSaveInterval() == 0 ) {
5078 delete mAutoSaveTimer; mAutoSaveTimer = 0;
5081 if ( !mAutoSaveTimer ) {
5082 mAutoSaveTimer =
new TQTimer(
this,
"mAutoSaveTimer" );
5083 connect( mAutoSaveTimer, TQT_SIGNAL( timeout() ),
5084 TQT_TQOBJECT(
this), TQT_SLOT( autoSaveMessage() ) );
5086 mAutoSaveTimer->start( autoSaveInterval() );
5090 void KMComposeWin::setAutoSaveFilename(
const TQString & filename )
5092 mAutoSaveFilename = filename;
5095 void KMComposeWin::cleanupAutoSave()
5097 delete mAutoSaveTimer; mAutoSaveTimer = 0;
5098 if ( !mAutoSaveFilename.isEmpty() ) {
5099 kdDebug(5006) << k_funcinfo <<
"deleting autosave file " 5100 << mAutoSaveFilename << endl;
5102 mAutoSaveFilename );
5103 mAutoSaveFilename = TQString();
5107 void KMComposeWin::slotCompletionModeChanged( TDEGlobalSettings::Completion mode)
5109 GlobalSettings::self()->setCompletionMode( (
int) mode );
5112 mEdtFrom->setCompletionMode( mode );
5113 mEdtReplyTo->setCompletionMode( mode );
5114 if ( mClassicalRecipients ) {
5115 mEdtTo->setCompletionMode( mode );
5116 mEdtCc->setCompletionMode( mode );
5117 mEdtBcc->setCompletionMode( mode );
5119 mRecipientsEditor->setCompletionMode( mode );
5122 void KMComposeWin::slotConfigChanged()
5127 slotWordWrapToggled( mWordWrapAction->isChecked() );
5134 void KMComposeWin::slotFolderRemoved(
KMFolder* folder)
5137 if ( (mFolder) && (folder->
idString() == mFolder->idString()) )
5139 mFolder = kmkernel->draftsFolder();
5140 kdDebug(5006) <<
"restoring drafts to " << mFolder->idString() << endl;
5142 if (mMsg) mMsg->setParent(0);
5146 void KMComposeWin::editorFocusChanged(
bool gained)
5148 mPasteQuotation->setEnabled(gained);
5151 void KMComposeWin::slotSetAlwaysSend(
bool bAlways )
5153 mAlwaysSend = bAlways;
5156 void KMComposeWin::slotListAction(
const TQString& style )
5159 if ( style == i18n(
"Standard" ) )
5160 mEditor->setParagType( TQStyleSheetItem::DisplayBlock, TQStyleSheetItem::ListDisc );
5161 else if ( style == i18n(
"Bulleted List (Disc)" ) )
5162 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDisc );
5163 else if ( style == i18n(
"Bulleted List (Circle)" ) )
5164 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListCircle );
5165 else if ( style == i18n(
"Bulleted List (Square)" ) )
5166 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListSquare );
5167 else if ( style == i18n(
"Ordered List (Decimal)" ))
5168 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDecimal );
5169 else if ( style == i18n(
"Ordered List (Alpha lower)" ) )
5170 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListLowerAlpha );
5171 else if ( style == i18n(
"Ordered List (Alpha upper)" ) )
5172 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListUpperAlpha );
5173 mEditor->viewport()->setFocus();
5176 void KMComposeWin::slotFontAction(
const TQString& font)
5179 mEditor->TQTextEdit::setFamily( font );
5180 mEditor->viewport()->setFocus();
5183 void KMComposeWin::slotSizeAction(
int size )
5186 mEditor->setPointSize( size );
5187 mEditor->viewport()->setFocus();
5190 void KMComposeWin::slotAlignLeft()
5193 mEditor->TQTextEdit::setAlignment( AlignLeft );
5196 void KMComposeWin::slotAlignCenter()
5199 mEditor->TQTextEdit::setAlignment( AlignHCenter );
5202 void KMComposeWin::slotAlignRight()
5205 mEditor->TQTextEdit::setAlignment( AlignRight );
5208 void KMComposeWin::slotTextBold()
5211 mEditor->TQTextEdit::setBold( textBoldAction->isChecked() );
5214 void KMComposeWin::slotTextItalic()
5217 mEditor->TQTextEdit::setItalic( textItalicAction->isChecked() );
5220 void KMComposeWin::slotTextUnder()
5223 mEditor->TQTextEdit::setUnderline( textUnderAction->isChecked() );
5226 void KMComposeWin::slotFormatReset()
5228 mEditor->setColor(mForeColor);
5229 mEditor->setCurrentFont( mSaveFont );
5231 void KMComposeWin::slotTextColor()
5233 TQColor color = mEditor->color();
5235 if ( KColorDialog::getColor( color,
this ) ) {
5237 mEditor->setColor( color );
5241 void KMComposeWin::fontChanged(
const TQFont &f )
5243 TQFont fontTemp = f;
5244 fontTemp.setBold(
true );
5245 fontTemp.setItalic(
true );
5246 TQFontInfo fontInfo( fontTemp );
5248 if ( fontInfo.bold() ) {
5249 textBoldAction->setChecked( f.bold() );
5250 textBoldAction->setEnabled(
true ) ;
5252 textBoldAction->setEnabled(
false );
5255 if ( fontInfo.italic() ) {
5256 textItalicAction->setChecked( f.italic() );
5257 textItalicAction->setEnabled(
true ) ;
5259 textItalicAction->setEnabled(
false );
5262 textUnderAction->setChecked( f.underline() );
5264 fontAction->setFont( f.family() );
5265 fontSizeAction->setFontSize( f.pointSize() );
5268 void KMComposeWin::alignmentChanged(
int a )
5271 alignLeftAction->setChecked( ( a == AlignAuto ) || ( a & AlignLeft ) );
5272 alignCenterAction->setChecked( ( a & AlignHCenter ) );
5273 alignRightAction->setChecked( ( a & AlignRight ) );
5277 class TDEToggleActionResetter {
5278 TDEToggleAction * mAction;
5281 TDEToggleActionResetter( TDEToggleAction * action,
bool on )
5282 : mAction( action ), mOn( on ) {}
5283 ~TDEToggleActionResetter() {
5285 mAction->setChecked( mOn );
5287 void disable() { mAction = 0; }
5291 void KMComposeWin::slotEncryptChiasmusToggled(
bool on ) {
5292 mEncryptWithChiasmus =
false;
5297 TDEToggleActionResetter resetter( mEncryptChiasmusAction,
false );
5299 const Kleo::CryptoBackend::Protocol * chiasmus =
5300 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" );
5303 const TQString msg = Kleo::CryptoBackendFactory::instance()->knowsAboutProtocol(
"Chiasmus" )
5304 ? i18n(
"Please configure a Crypto Backend to use for " 5305 "Chiasmus encryption first.\n" 5306 "You can do this in the Crypto Backends tab of " 5307 "the configure dialog's Security page." )
5308 : i18n(
"It looks as though libkleopatra was compiled without " 5309 "Chiasmus support. You might want to recompile " 5310 "libkleopatra with --enable-chiasmus.");
5311 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Backend Configured" ) );
5315 STD_NAMESPACE_PREFIX auto_ptr<Kleo::SpecialJob> job( chiasmus->specialJob(
"x-obtain-keys", TQMap<TQString,TQVariant>() ) );
5317 const TQString msg = i18n(
"Chiasmus backend does not offer the " 5318 "\"x-obtain-keys\" function. Please report this bug." );
5319 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
5323 if ( job->exec() ) {
5324 job->showErrorDialog(
this, i18n(
"Chiasmus Backend Error" ) );
5328 const TQVariant result = job->property(
"result" );
5329 if ( result.type() != TQVariant::StringList ) {
5330 const TQString msg = i18n(
"Unexpected return value from Chiasmus backend: " 5331 "The \"x-obtain-keys\" function did not return a " 5332 "string list. Please report this bug." );
5333 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
5337 const TQStringList keys = result.toStringList();
5338 if ( keys.empty() ) {
5339 const TQString msg = i18n(
"No keys have been found. Please check that a " 5340 "valid key path has been set in the Chiasmus " 5342 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Keys Found" ) );
5346 ChiasmusKeySelector selectorDlg(
this, i18n(
"Chiasmus Encryption Key Selection" ),
5347 keys, GlobalSettings::chiasmusKey(),
5348 GlobalSettings::chiasmusOptions() );
5349 if ( selectorDlg.exec() != TQDialog::Accepted )
5352 GlobalSettings::setChiasmusOptions( selectorDlg.options() );
5353 GlobalSettings::setChiasmusKey( selectorDlg.key() );
5354 assert( !GlobalSettings::chiasmusKey().isEmpty() );
5355 mEncryptWithChiasmus =
true;
5361 kdDebug(5006) << k_funcinfo << endl;
5362 KMMessagePart *part = mEditorMap[ watcher ];
5363 KTempFile *tf = mEditorTempFiles[ watcher ];
5364 mEditorMap.remove( watcher );
5365 mEditorTempFiles.remove( watcher );
5366 if ( !watcher->fileChanged() )
5369 tf->file()->reset();
5370 TQByteArray data = tf->file()->readAll();
5371 part->setBodyEncodedBinary( data );
5375 void KMComposeWin::slotUpdateSignatureAndEncrypionStateIndicators()
5377 const bool showIndicatorsAlways =
false;
5378 mSignatureStateIndicator->setText( mSignAction->isChecked()? i18n(
"Message will be signed") : i18n(
"Message will not be signed") );
5379 mEncryptionStateIndicator->setText( mEncryptAction->isChecked()? i18n(
"Message will be encrypted") : i18n(
"Message will not be encrypted") );
5380 if ( !showIndicatorsAlways ) {
5381 mSignatureStateIndicator->setShown( mSignAction->isChecked() );
5382 mEncryptionStateIndicator->setShown( mEncryptAction->isChecked() );
5386 void KMComposeWin::slotAttachmentDragStarted()
5388 kdDebug(5006) << k_funcinfo << endl;
5390 TQStringList filenames;
5391 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++idx ) {
5392 if ( (*it)->isSelected() ) {
5393 KMMessagePart* msgPart = mAtmList.at(idx);
5394 KTempDir * tempDir =
new KTempDir();
5395 tempDir->setAutoDelete(
true );
5396 mTempDirs.insert( tempDir );
5397 const TQString fileName = tempDir->name() +
"/" + msgPart->name();
5398 KPIM::kByteArrayToFile(msgPart->bodyDecodedBinary(),
5400 false,
false,
false);
5402 url.setPath( fileName );
5403 filenames << url.path();
5406 if ( filenames.isEmpty() )
return;
5408 TQUriDrag *drag =
new TQUriDrag( mAtmListView );
5409 drag->setFileNames( filenames );
5413 void KMComposeWin::recipientEditorSizeHintChanged()
5415 TQTimer::singleShot( 1,
this, TQT_SLOT(setMaximumHeaderSize()) );
5418 void KMComposeWin::setMaximumHeaderSize()
5420 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
static TQCString defaultCharset()
Get the default message charset.
static TQString smartQuote(const TQString &msg, int maxLineLength)
Given argument msg add quoting characters and relayout for max width maxLength.
const char * encoding() const
Convenience method.
void initHeader(uint identity=0)
Initialize header fields.
static KPIM::EmailParseResult isValidEmailAddressList(const TQString &aStr, TQString &brokenAddress)
Validate a list of email addresses, and also allow aliases and distribution lists to be expanded befo...
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
Provides encoding detection capabilities.
static TQString localDataPath()
Returns the full path of the user's local data directory for KMail.
TQString idString() const
Returns a string that can be used to identify this folder.
static TQString expandAliases(const TQString &recipients)
Expands aliases (distribution lists and nick names) and appends a domain part to all email addresses ...
DCOP interface for mail composer window.
int count(bool cache=false) const
Number of messages in this folder.
TQString fcc() const
Get or set the 'Fcc' header field.
Starts an editor for the given URL and emits an signal when editing has been finished.
KMMessage * getMsg(int idx)
Read message at given index.
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
void close(const char *owner, bool force=false)
Close folder.
static const TQStringList & preferredCharsets()
Get a list of preferred message charsets.
A combo box for selecting the dictionary used for spell checking.
static TQStringList transportNames()
Returns the list for transport names.
bool analyze(const char *data, int len)
Analyze text data.
int open(const char *owner)
Open folder for access.
KMMsgInfo * unGetMsg(int idx)
Replace KMMessage with KMMsgInfo and delete KMMessage.
The attachment dialog with convenience backward compatible methods.
int addMsg(KMMessage *msg, int *index_return=0)
Add the given message to the folder.
const DwString & asDwString() const
Return the entire message contents in the DwString.