9 #define REALLY_WANT_KMCOMPOSEWIN_H
10 #include "kmcomposewin.h"
11 #undef REALLY_WANT_KMCOMPOSEWIN_H
14 #include "kmlineeditspell.h"
15 #include "kmatmlistview.h"
17 #include "kmmainwin.h"
18 #include "kmreadermainwin.h"
19 #include "messagesender.h"
20 #include "kmmsgpartdlg.h"
21 #include <kpgpblock.h>
22 #include <kaddrbook.h>
23 #include "kmaddrbook.h"
24 #include "kmmsgdict.h"
25 #include "kmfolderimap.h"
26 #include "kmfoldermgr.h"
27 #include "kmfoldercombobox.h"
28 #include "kmtransport.h"
29 #include "kmcommands.h"
30 #include "kcursorsaver.h"
32 #include "encodingdetector.h"
33 #include "attachmentlistview.h"
34 #include "transportmanager.h"
35 using KMail::AttachmentListView;
36 #include "dictionarycombobox.h"
38 #include "addressesdialog.h"
39 using KPIM::AddressesDialog;
40 #include "addresseeemailselection.h"
41 using KPIM::AddresseeEmailSelection;
42 using KPIM::AddresseeSelectorDialog;
43 #include <maillistdrag.h>
44 using KPIM::MailListDrag;
45 #include "recentaddresses.h"
46 using TDERecentAddress::RecentAddresses;
47 #include "kleo_util.h"
49 #include "recipientseditor.h"
50 #include "editorwatcher.h"
52 #include "attachmentcollector.h"
53 #include "objecttreeparser.h"
55 #include "kmfoldermaildir.h"
57 #include <libkpimidentities/identitymanager.h>
58 #include <libkpimidentities/identitycombo.h>
59 #include <libkpimidentities/identity.h>
60 #include <libtdepim/tdefileio.h>
61 #include <libemailfunctions/email.h>
62 #include <kleo/cryptobackendfactory.h>
63 #include <kleo/exportjob.h>
64 #include <kleo/specialjob.h>
65 #include <ui/progressdialog.h>
66 #include <ui/keyselectiondialog.h>
68 #include <gpgmepp/context.h>
69 #include <gpgmepp/key.h>
71 #include <tdeio/netaccess.h>
73 #include "tdelistboxdialog.h"
75 #include "messagecomposer.h"
76 #include "chiasmuskeyselector.h"
78 #include <kcharsets.h>
79 #include <tdecompletionbox.h>
81 #include <kcombobox.h>
82 #include <tdestdaccel.h>
83 #include <tdepopupmenu.h>
84 #include <kedittoolbar.h>
85 #include <kkeydialog.h>
87 #include <tdefiledialog.h>
89 #include <kinputdialog.h>
90 #include <tdemessagebox.h>
92 #include <tdeio/scheduler.h>
93 #include <tdetempfile.h>
94 #include <tdelocale.h>
95 #include <tdeapplication.h>
96 #include <kstatusbar.h>
97 #include <tdeaction.h>
98 #include <kstdaction.h>
99 #include <kdirwatch.h>
100 #include <kstdguiitem.h>
101 #include <kiconloader.h>
102 #include <kpushbutton.h>
103 #include <kuserprofile.h>
105 #include <ktempdir.h>
106 #include <kstandarddirs.h>
108 #include "globalsettings.h"
109 #include "replyphrases.h"
111 #include <tdespell.h>
112 #include <tdespelldlg.h>
113 #include <spellingfilter.h>
114 #include <ksyntaxhighlighter.h>
115 #include <kcolordialog.h>
117 #include <ksavefile.h>
119 #include <tqtabdialog.h>
120 #include <tqregexp.h>
121 #include <tqbuffer.h>
122 #include <tqtooltip.h>
123 #include <tqtextcodec.h>
124 #include <tqheader.h>
125 #include <tqwhatsthis.h>
126 #include <tqfontdatabase.h>
128 #include <mimelib/mimepp.h>
133 #include <sys/stat.h>
134 #include <sys/types.h>
141 #include "kmcomposewin.moc"
143 #include "snippetwidget.h"
145 KMail::Composer * KMail::makeComposer(
KMMessage * msg, uint identitiy ) {
146 return KMComposeWin::create( msg, identitiy );
149 KMail::Composer * KMComposeWin::create(
KMMessage * msg, uint identitiy ) {
150 return new KMComposeWin( msg, identitiy );
154 KMComposeWin::KMComposeWin(
KMMessage *aMsg, uint
id )
156 mSpellCheckInProgress( false ),
158 mAtmModified( false ),
162 mSigningAndEncryptionExplicitlyDisabled( false ),
164 mUseHTMLEditor( false ),
166 mAttachPK( 0 ), mAttachMPK( 0 ),
167 mAttachRemoveAction( 0 ), mAttachSaveAction( 0 ), mAttachPropertiesAction( 0 ),
168 mAppendSignatureAction( 0 ), mPrependSignatureAction( 0 ), mInsertSignatureAction( 0 ),
169 mSignAction( 0 ), mEncryptAction( 0 ), mRequestMDNAction( 0 ),
170 mUrgentAction( 0 ), mAllFieldsAction( 0 ), mFromAction( 0 ),
171 mReplyToAction( 0 ), mToAction( 0 ), mCcAction( 0 ), mBccAction( 0 ),
173 mIdentityAction( 0 ), mTransportAction( 0 ), mFccAction( 0 ),
174 mWordWrapAction( 0 ), mFixedFontAction( 0 ), mAutoSpellCheckingAction( 0 ),
175 mDictionaryAction( 0 ), mSnippetAction( 0 ),
176 mEncodingAction( 0 ),
177 mCryptoModuleAction( 0 ),
178 mEncryptChiasmusAction( 0 ),
179 mEncryptWithChiasmus( false ),
182 mAutoSaveTimer( 0 ), mLastAutoSaveErrno( 0 ),
183 mSignatureStateIndicator( 0 ), mEncryptionStateIndicator( 0 ),
184 mPreserveUserCursorPosition( false ),
185 mPreventFccOverwrite( false ),
186 mCheckForRecipients( true ),
187 mCheckForForgottenAttachments( true ),
188 mIgnoreStickyFields( false )
190 mClassicalRecipients = GlobalSettings::self()->recipientsEditorType() ==
191 GlobalSettings::EnumRecipientsEditorType::Classic;
193 mSubjectTextWasSpellChecked =
false;
194 if (kmkernel->xmlGuiInstance())
195 setInstance( kmkernel->xmlGuiInstance() );
196 mMainWidget =
new TQWidget(
this);
198 mHeadersToEditorSplitter =
new TQSplitter( TQt::Vertical, mMainWidget,
"mHeadersToEditorSplitter" );
199 mHeadersToEditorSplitter->setChildrenCollapsible(
false );
200 mHeadersArea =
new TQWidget( mHeadersToEditorSplitter );
201 mHeadersArea->setSizePolicy( mHeadersToEditorSplitter->sizePolicy().horData(), TQSizePolicy::Maximum );
202 TQVBoxLayout *v =
new TQVBoxLayout( mMainWidget );
203 v->addWidget( mHeadersToEditorSplitter );
204 mIdentity =
new KPIM::IdentityCombo(kmkernel->identityManager(), mHeadersArea);
205 TQToolTip::add( mIdentity,
206 i18n(
"Select an identity for this message" ) );
209 TQToolTip::add( mDictionaryCombo,
210 i18n(
"Select the dictionary to use when spell-checking this message" ) );
212 mFcc =
new KMFolderComboBox(mHeadersArea);
213 mFcc->showOutboxFolder(
false );
214 TQToolTip::add( mFcc,
215 i18n(
"Select the sent-mail folder where a copy of this message will be saved" ) );
217 mTransport =
new TQComboBox(
true, mHeadersArea);
218 TQToolTip::add( mTransport,
219 i18n(
"Select the outgoing account to use for sending this message" ) );
221 mEdtFrom =
new KMLineEdit(
false,mHeadersArea,
"fromLine");
222 TQToolTip::add( mEdtFrom,
223 i18n(
"Set the \"From:\" email address for this message" ) );
225 mEdtReplyTo =
new KMLineEdit(
true,mHeadersArea,
"replyToLine");
226 TQToolTip::add( mEdtReplyTo,
227 i18n(
"Set the \"Reply-To:\" email address for this message" ) );
228 connect(mEdtReplyTo,TQ_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
229 TQ_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
231 if ( mClassicalRecipients ) {
232 mRecipientsEditor = 0;
234 mEdtTo =
new KMLineEdit(
true,mHeadersArea,
"toLine");
235 mEdtCc =
new KMLineEdit(
true,mHeadersArea,
"ccLine");
236 mEdtBcc =
new KMLineEdit(
true,mHeadersArea,
"bccLine");
238 mLblTo =
new TQLabel(mHeadersArea);
239 mLblCc =
new TQLabel(mHeadersArea);
240 mLblBcc =
new TQLabel(mHeadersArea);
242 mBtnTo =
new TQPushButton(
"...",mHeadersArea);
243 mBtnCc =
new TQPushButton(
"...",mHeadersArea);
244 mBtnBcc =
new TQPushButton(
"...",mHeadersArea);
247 TQString tip = i18n(
"Select email address(es)");
248 TQToolTip::add( mBtnTo, tip );
249 TQToolTip::add( mBtnCc, tip );
250 TQToolTip::add( mBtnBcc, tip );
252 mBtnTo->setFocusPolicy(TQWidget::NoFocus);
253 mBtnCc->setFocusPolicy(TQWidget::NoFocus);
254 mBtnBcc->setFocusPolicy(TQWidget::NoFocus);
257 connect(mBtnTo,TQ_SIGNAL(clicked()),TQ_SLOT(slotAddrBookTo()));
258 connect(mBtnCc,TQ_SIGNAL(clicked()),TQ_SLOT(slotAddrBookTo()));
259 connect(mBtnBcc,TQ_SIGNAL(clicked()),TQ_SLOT(slotAddrBookTo()));
262 connect(mEdtTo,TQ_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
263 TQ_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
264 connect(mEdtCc,TQ_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
265 TQ_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
266 connect(mEdtBcc,TQ_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
267 TQ_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
284 mRecipientsEditor =
new RecipientsEditor( mHeadersArea );
285 connect( mRecipientsEditor,
286 TQ_SIGNAL( completionModeChanged( TDEGlobalSettings::Completion ) ),
287 TQ_SLOT( slotCompletionModeChanged( TDEGlobalSettings::Completion ) ) );
288 connect( mRecipientsEditor, TQ_SIGNAL(sizeHintChanged()), TQ_SLOT(recipientEditorSizeHintChanged()) );
290 mRecipientsEditor->setFocus();
292 mEdtSubject =
new KMLineEditSpell(
false,mHeadersArea,
"subjectLine");
293 TQToolTip::add( mEdtSubject,
294 i18n(
"Set a subject for this message" ) );
296 mLblIdentity =
new TQLabel( i18n(
"&Identity:"), mHeadersArea );
297 mDictionaryLabel =
new TQLabel( i18n(
"&Dictionary:"), mHeadersArea );
298 mLblFcc =
new TQLabel( i18n(
"&Sent-Mail folder:"), mHeadersArea );
299 mLblTransport =
new TQLabel( i18n(
"&Mail transport:"), mHeadersArea );
300 mLblFrom =
new TQLabel( i18n(
"sender address field",
"&From:"), mHeadersArea );
301 mLblReplyTo =
new TQLabel( i18n(
"&Reply to:"), mHeadersArea );
302 mLblSubject =
new TQLabel( i18n(
"S&ubject:"), mHeadersArea );
304 TQString sticky = i18n(
"Sticky");
305 mBtnIdentity =
new TQCheckBox(sticky,mHeadersArea);
306 TQToolTip::add( mBtnIdentity,
307 i18n(
"Use the selected value as your identity for future messages" ) );
308 mBtnFcc =
new TQCheckBox(sticky,mHeadersArea);
309 TQToolTip::add( mBtnFcc,
310 i18n(
"Use the selected value as your sent-mail folder for future messages" ) );
311 mBtnTransport =
new TQCheckBox(sticky,mHeadersArea);
312 TQToolTip::add( mBtnTransport,
313 i18n(
"Use the selected value as your outgoing account for future messages" ) );
314 mBtnDictionary =
new TQCheckBox( sticky, mHeadersArea );
315 TQToolTip::add( mBtnDictionary,
316 i18n(
"Use the selected value as your dictionary for future messages" ) );
319 mHtmlMarkup = GlobalSettings::self()->useHtmlMarkup();
320 mShowHeaders = GlobalSettings::self()->headers();
324 mAtmList.setAutoDelete(
true);
325 mAtmTempList.setAutoDelete(
true);
326 mAtmModified =
false;
327 mAutoDeleteMsg =
false;
330 mFixedFontAction = 0;
333 mSplitter =
new TQSplitter( TQt::Vertical, mHeadersToEditorSplitter,
"mSplitter" );
334 mSplitter->setChildrenCollapsible(
false );
335 mSnippetSplitter =
new TQSplitter( TQt::Horizontal, mSplitter,
"mSnippetSplitter");
336 mSnippetSplitter->setChildrenCollapsible(
false );
338 TQWidget *editorAndCryptoStateIndicators =
new TQWidget( mSnippetSplitter );
339 TQVBoxLayout *vbox =
new TQVBoxLayout( editorAndCryptoStateIndicators );
340 TQHBoxLayout *hbox =
new TQHBoxLayout( vbox );
342 mSignatureStateIndicator =
new TQLabel( editorAndCryptoStateIndicators );
343 mSignatureStateIndicator->setAlignment( TQt::AlignHCenter );
344 hbox->addWidget( mSignatureStateIndicator );
346 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
347 TQPalette p( mSignatureStateIndicator->palette() );
349 TQColor defaultSignedColor( 0x40, 0xFF, 0x40 );
350 TQColor defaultEncryptedColor( 0x00, 0x80, 0xFF );
351 p.setColor( TQColorGroup::Background, reader.readColorEntry(
"PGPMessageOkKeyOk", &defaultSignedColor ) );
352 mSignatureStateIndicator->setPalette( p );
354 mEncryptionStateIndicator =
new TQLabel( editorAndCryptoStateIndicators );
355 mEncryptionStateIndicator->setAlignment( TQt::AlignHCenter );
356 hbox->addWidget( mEncryptionStateIndicator );
357 p.setColor( TQColorGroup::Background, reader.readColorEntry(
"PGPMessageEncr" , &defaultEncryptedColor ) );
358 mEncryptionStateIndicator->setPalette( p );
361 mEditor =
new KMEdit( editorAndCryptoStateIndicators,
this, mDictionaryCombo->spellConfig() );
362 vbox->addWidget( mEditor );
364 mSnippetWidget =
new SnippetWidget( mEditor, actionCollection(), mSnippetSplitter );
365 mSnippetWidget->setShown( GlobalSettings::self()->showSnippetManager() );
368 mSplitter->setOpaqueResize(
true );
370 mEditor->initializeAutoSpellChecking();
371 mEditor->setTextFormat(TQt::PlainText);
372 mEditor->setAcceptDrops(
true );
374 TQWhatsThis::add( mBtnIdentity,
375 GlobalSettings::self()->stickyIdentityItem()->whatsThis() );
376 TQWhatsThis::add( mBtnFcc,
377 GlobalSettings::self()->stickyFccItem()->whatsThis() );
378 TQWhatsThis::add( mBtnTransport,
379 GlobalSettings::self()->stickyTransportItem()->whatsThis() );
380 TQWhatsThis::add( mBtnTransport,
381 GlobalSettings::self()->stickyDictionaryItem()->whatsThis() );
383 mSpellCheckInProgress=
false;
385 setCaption( i18n(
"Composer") );
386 setMinimumSize(200,200);
388 mBtnIdentity->setFocusPolicy(TQWidget::NoFocus);
389 mBtnFcc->setFocusPolicy(TQWidget::NoFocus);
390 mBtnTransport->setFocusPolicy(TQWidget::NoFocus);
391 mBtnDictionary->setFocusPolicy( TQWidget::NoFocus );
393 mAtmListView =
new AttachmentListView(
this, mSplitter,
394 "attachment list view" );
395 mAtmListView->setSelectionMode( TQListView::Extended );
396 mAtmListView->addColumn( i18n(
"Name"), 200 );
397 mAtmListView->addColumn( i18n(
"Size"), 80 );
398 mAtmListView->addColumn( i18n(
"Encoding"), 120 );
399 int atmColType = mAtmListView->addColumn( i18n(
"Type"), 120 );
401 mAtmListView->header()->setStretchEnabled(
true, atmColType );
402 mAtmEncryptColWidth = 80;
403 mAtmSignColWidth = 80;
404 mAtmCompressColWidth = 100;
405 mAtmColCompress = mAtmListView->addColumn( i18n(
"Compress"),
406 mAtmCompressColWidth );
407 mAtmColEncrypt = mAtmListView->addColumn( i18n(
"Encrypt"),
408 mAtmEncryptColWidth );
409 mAtmColSign = mAtmListView->addColumn( i18n(
"Sign"),
411 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
412 mAtmListView->setColumnWidth( mAtmColSign, 0 );
413 mAtmListView->setAllColumnsShowFocus(
true );
415 connect( mAtmListView,
416 TQ_SIGNAL( doubleClicked( TQListViewItem* ) ),
417 TQ_SLOT( slotAttachEdit() ) );
418 connect( mAtmListView,
419 TQ_SIGNAL( rightButtonPressed( TQListViewItem*,
const TQPoint&,
int ) ),
420 TQ_SLOT( slotAttachPopupMenu( TQListViewItem*,
const TQPoint&,
int ) ) );
421 connect( mAtmListView,
422 TQ_SIGNAL( selectionChanged() ),
423 TQ_SLOT( slotUpdateAttachActions() ) );
424 connect( mAtmListView,
425 TQ_SIGNAL( attachmentDeleted() ),
426 TQ_SLOT( slotAttachRemove() ) );
427 connect( mAtmListView,
428 TQ_SIGNAL( dragStarted() ),
429 TQ_SLOT( slotAttachmentDragStarted() ) );
436 slotUpdateSignatureAndEncrypionStateIndicators();
438 applyMainWindowSettings(KMKernel::config(),
"Composer");
440 connect( mEdtSubject, TQ_SIGNAL( subjectTextSpellChecked() ),
441 TQ_SLOT( slotSubjectTextSpellChecked() ) );
442 connect(mEdtSubject,TQ_SIGNAL(textChanged(
const TQString&)),
443 TQ_SLOT(slotUpdWinTitle(
const TQString&)));
444 connect(mIdentity,TQ_SIGNAL(identityChanged(uint)),
445 TQ_SLOT(slotIdentityChanged(uint)));
446 connect( kmkernel->identityManager(), TQ_SIGNAL(changed(uint)),
447 TQ_SLOT(slotIdentityChanged(uint)));
449 connect(mEdtFrom,TQ_SIGNAL(completionModeChanged(TDEGlobalSettings::Completion)),
450 TQ_SLOT(slotCompletionModeChanged(TDEGlobalSettings::Completion)));
451 connect(kmkernel->folderMgr(),TQ_SIGNAL(folderRemoved(
KMFolder*)),
452 TQ_SLOT(slotFolderRemoved(
KMFolder*)));
453 connect(kmkernel->imapFolderMgr(),TQ_SIGNAL(folderRemoved(
KMFolder*)),
454 TQ_SLOT(slotFolderRemoved(
KMFolder*)));
455 connect(kmkernel->dimapFolderMgr(),TQ_SIGNAL(folderRemoved(
KMFolder*)),
456 TQ_SLOT(slotFolderRemoved(
KMFolder*)));
457 connect( kmkernel, TQ_SIGNAL( configChanged() ),
458 this, TQ_SLOT( slotConfigChanged() ) );
460 connect (mEditor, TQ_SIGNAL (spellcheck_done(
int)),
461 this, TQ_SLOT (slotSpellcheckDone (
int)));
462 connect (mEditor, TQ_SIGNAL( attachPNGImageData(
const TQByteArray &) ),
463 this, TQ_SLOT ( slotAttachPNGImageData(
const TQByteArray &) ) );
464 connect (mEditor, TQ_SIGNAL( focusChanged(
bool) ),
465 this, TQ_SLOT (editorFocusChanged(
bool)) );
467 mMainWidget->resize(480,510);
468 setCentralWidget(mMainWidget);
471 if ( !mClassicalRecipients ) {
477 if ( GlobalSettings::self()->useExternalEditor() ) {
478 mEditor->setUseExternalEditor(
true);
479 mEditor->setExternalEditorPath( GlobalSettings::self()->externalEditor() );
483 slotUpdateSignatureActions();
487 fontChanged( mEditor->currentFont() );
493 KMComposeWin::~KMComposeWin()
498 mAutoDeleteMsg =
false;
499 mFolder->addMsg(mMsg);
501 mFolder->unGetMsg( mFolder->count() - 1 );
503 if (mAutoDeleteMsg) {
507 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.begin();
508 while ( it != mMapAtmLoadData.end() )
510 TDEIO::Job *job = it.key();
511 mMapAtmLoadData.remove( it );
513 it = mMapAtmLoadData.begin();
515 deleteAll( mComposedMessages );
517 for ( std::set<KTempDir*>::iterator it = mTempDirs.begin() ; it != mTempDirs.end() ; ++it ) {
522 void KMComposeWin::setAutoDeleteWindow(
bool f )
525 setWFlags( getWFlags() | WDestructiveClose );
527 setWFlags( getWFlags() & ~WDestructiveClose );
531 void KMComposeWin::send(
int how)
547 void KMComposeWin::addAttachmentsAndSend(
const KURL::List &urls,
const TQString &,
int how)
554 mAttachFilesSend = how;
555 mAttachFilesPending = urls;
556 connect(
this, TQ_SIGNAL(attachmentAdded(
const KURL&,
bool)), TQ_SLOT(slotAttachedFile(
const KURL&)));
557 for( KURL::List::ConstIterator itr = urls.begin(); itr != urls.end(); ++itr ) {
558 if (!addAttach( *itr ))
559 mAttachFilesPending.remove(mAttachFilesPending.find(*itr));
562 if (mAttachFilesPending.isEmpty() && mAttachFilesSend == how)
564 send(mAttachFilesSend);
565 mAttachFilesSend = -1;
569 void KMComposeWin::slotAttachedFile(
const KURL &url)
571 if (mAttachFilesPending.isEmpty())
573 mAttachFilesPending.remove(mAttachFilesPending.find(url));
574 if (mAttachFilesPending.isEmpty())
576 send(mAttachFilesSend);
577 mAttachFilesSend = -1;
582 void KMComposeWin::addAttachment(KURL url,TQString )
588 void KMComposeWin::addAttachment(
const TQString &name,
590 const TQByteArray &data,
591 const TQCString &type,
592 const TQCString &subType,
593 const TQCString ¶mAttr,
594 const TQString ¶mValue,
595 const TQCString &contDisp)
597 if (!data.isEmpty()) {
598 KMMessagePart *msgPart =
new KMMessagePart;
599 msgPart->setName(name);
600 if( type ==
"message" && subType ==
"rfc822" ) {
601 msgPart->setMessageBody( data );
603 TQValueList<int> dummy;
604 msgPart->setBodyAndGuessCte(data, dummy,
605 kmkernel->msgSender()->sendQuotedPrintable());
607 msgPart->setTypeStr(type);
608 msgPart->setSubtypeStr(subType);
609 msgPart->setParameter(paramAttr,paramValue);
610 msgPart->setContentDisposition(contDisp);
616 void KMComposeWin::slotAttachPNGImageData(
const TQByteArray &image)
620 TQString attName = KInputDialog::getText(
"KMail", i18n(
"Name of the attachment:"), TQString(), &ok,
this );
624 if ( !attName.lower().endsWith(
".png") ) attName +=
".png";
626 addAttachment( attName,
"base64", image,
"image",
"png", TQCString(), TQString(), TQCString() );
630 void KMComposeWin::setBody(TQString body)
632 mEditor->setText(body);
636 bool KMComposeWin::event(TQEvent *e)
638 if (e->type() == TQEvent::ApplicationPaletteChange)
642 return KMail::Composer::event(e);
647 void KMComposeWin::readColorConfig(
void)
649 if ( GlobalSettings::self()->useDefaultColors() ) {
650 mForeColor = TQColor(kapp->palette().active().text());
651 mBackColor = TQColor(kapp->palette().active().base());
653 mForeColor = GlobalSettings::self()->foregroundColor();
654 mBackColor = GlobalSettings::self()->backgroundColor();
658 mPalette = kapp->palette();
659 TQColorGroup cgrp = mPalette.active();
660 cgrp.setColor( TQColorGroup::Base, mBackColor);
661 cgrp.setColor( TQColorGroup::Text, mForeColor);
662 mPalette.setDisabled(cgrp);
663 mPalette.setActive(cgrp);
664 mPalette.setInactive(cgrp);
666 mEdtFrom->setPalette(mPalette);
667 mEdtReplyTo->setPalette(mPalette);
668 if ( mClassicalRecipients ) {
669 mEdtTo->setPalette(mPalette);
670 mEdtCc->setPalette(mPalette);
671 mEdtBcc->setPalette(mPalette);
673 mEdtSubject->setPalette(mPalette);
674 mTransport->setPalette(mPalette);
675 mEditor->setPalette(mPalette);
676 mFcc->setPalette(mPalette);
680 void KMComposeWin::readConfig(
bool reload )
683 mBtnIdentity->setChecked( GlobalSettings::self()->stickyIdentity() );
684 if (mBtnIdentity->isChecked()) {
685 mId = (GlobalSettings::self()->previousIdentity()!=0) ?
686 GlobalSettings::self()->previousIdentity() : mId;
688 mBtnFcc->setChecked( GlobalSettings::self()->stickyFcc() );
689 mBtnTransport->setChecked( GlobalSettings::self()->stickyTransport() );
690 mBtnDictionary->setChecked( GlobalSettings::self()->stickyDictionary() );
691 TQStringList transportHistory = GlobalSettings::self()->transportHistory();
692 TQString currentTransport = GlobalSettings::self()->currentTransport();
694 mEdtFrom->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
695 mEdtReplyTo->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
696 if ( mClassicalRecipients ) {
697 mEdtTo->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
698 mEdtCc->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
699 mEdtBcc->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
702 mRecipientsEditor->setCompletionMode( (TDEGlobalSettings::Completion)GlobalSettings::self()->completionMode() );
706 if ( GlobalSettings::self()->useDefaultFonts() ) {
707 mBodyFont = TDEGlobalSettings::generalFont();
708 mFixedFont = TDEGlobalSettings::fixedFont();
710 mBodyFont = GlobalSettings::self()->composerFont();
711 mFixedFont = GlobalSettings::self()->fixedFont();
715 mEdtFrom->setFont(mBodyFont);
716 mEdtReplyTo->setFont(mBodyFont);
717 if ( mClassicalRecipients ) {
718 mEdtTo->setFont(mBodyFont);
719 mEdtCc->setFont(mBodyFont);
720 mEdtBcc->setFont(mBodyFont);
722 mEdtSubject->setFont(mBodyFont);
725 TQSize siz = GlobalSettings::self()->composerSize();
726 if (siz.width() < 200) siz.setWidth(200);
727 if (siz.height() < 200) siz.setHeight(200);
730 if ( !GlobalSettings::self()->snippetSplitterPosition().isEmpty() ) {
731 mSnippetSplitter->setSizes( GlobalSettings::self()->snippetSplitterPosition() );
733 TQValueList<int> defaults;
734 defaults << (int)(width() * 0.8) << (
int)(width() * 0.2);
735 mSnippetSplitter->setSizes( defaults );
739 mIdentity->setCurrentIdentity( mId );
741 kdDebug(5006) <<
"KMComposeWin::readConfig. " << mIdentity->currentIdentityName() << endl;
742 const KPIM::Identity & ident =
743 kmkernel->identityManager()->identityForUoid( mIdentity->currentIdentity() );
746 mTransport->insertStringList( KMTransportInfo::availableTransports() );
747 while ( transportHistory.count() > (uint)GlobalSettings::self()->maxTransportEntries() )
748 transportHistory.remove( transportHistory.last() );
749 mTransport->insertStringList( transportHistory );
750 mTransport->setCurrentText( GlobalSettings::self()->defaultTransport() );
751 if ( mBtnTransport->isChecked() ) {
752 setTransport( currentTransport );
755 if ( mBtnDictionary->isChecked() ) {
756 mDictionaryCombo->setCurrentByDictionaryName( GlobalSettings::self()->previousDictionary() );
758 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
761 TQString fccName =
"";
762 if ( mBtnFcc->isChecked() ) {
763 fccName = GlobalSettings::self()->previousFcc();
764 }
else if ( !ident.fcc().isEmpty() ) {
765 fccName = ident.fcc();
772 void KMComposeWin::writeConfig(
void)
774 GlobalSettings::self()->setHeaders( mShowHeaders );
775 GlobalSettings::self()->setStickyFcc( mBtnFcc->isChecked() );
776 if ( !mIgnoreStickyFields ) {
777 GlobalSettings::self()->setCurrentTransport( mTransport->currentText() );
778 GlobalSettings::self()->setStickyTransport( mBtnTransport->isChecked() );
779 GlobalSettings::self()->setStickyDictionary( mBtnDictionary->isChecked() );
780 GlobalSettings::self()->setStickyIdentity( mBtnIdentity->isChecked() );
781 GlobalSettings::self()->setPreviousIdentity( mIdentity->currentIdentity() );
783 GlobalSettings::self()->setPreviousFcc( mFcc->getFolder()->idString() );
784 GlobalSettings::self()->setPreviousDictionary( mDictionaryCombo->currentDictionaryName() );
785 GlobalSettings::self()->setAutoSpellChecking(
786 mAutoSpellCheckingAction->isChecked() );
787 TQStringList transportHistory = GlobalSettings::self()->transportHistory();
788 transportHistory.remove(mTransport->currentText());
789 if (KMTransportInfo::availableTransports().findIndex(mTransport
790 ->currentText()) == -1) {
791 transportHistory.prepend(mTransport->currentText());
793 GlobalSettings::self()->setTransportHistory( transportHistory );
794 GlobalSettings::self()->setUseFixedFont( mFixedFontAction->isChecked() );
795 GlobalSettings::self()->setUseHtmlMarkup( mHtmlMarkup );
796 GlobalSettings::self()->setComposerSize( size() );
797 GlobalSettings::self()->setShowSnippetManager( mSnippetAction->isChecked() );
799 TDEConfigGroupSaver saver( KMKernel::config(),
"Geometry" );
800 saveMainWindowSettings( KMKernel::config(),
"Composer" );
801 GlobalSettings::setSnippetSplitterPosition( mSnippetSplitter->sizes() );
804 GlobalSettings::self()->writeConfig();
808 void KMComposeWin::autoSaveMessage()
810 kdDebug(5006) << k_funcinfo << endl;
811 if ( !mMsg || mComposer || mAutoSaveFilename.isEmpty() )
813 kdDebug(5006) << k_funcinfo <<
"autosaving message" << endl;
815 if ( mAutoSaveTimer )
816 mAutoSaveTimer->stop();
818 connect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
819 this, TQ_SLOT( slotContinueAutoSave() ) );
823 applyChanges(
true,
true );
828 void KMComposeWin::slotContinueAutoSave()
830 disconnect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
831 this, TQ_SLOT( slotContinueAutoSave() ) );
834 if ( mComposedMessages.isEmpty() ) {
835 kdDebug(5006) <<
"Composing the message failed." << endl;
838 KMMessage *msg = mComposedMessages.first();
842 kdDebug(5006) << k_funcinfo <<
"opening autoSaveFile " << mAutoSaveFilename
844 const TQString filename =
846 KSaveFile autoSaveFile( filename, 0600 );
847 int status = autoSaveFile.status();
848 kdDebug(5006) << k_funcinfo <<
"autoSaveFile.status() = " << status << endl;
850 kdDebug(5006) <<
"autosaving message in " << filename << endl;
851 int fd = autoSaveFile.handle();
853 if ( ::write( fd, msgStr.data(), msgStr.length() ) == -1 )
857 kdDebug(5006) << k_funcinfo <<
"closing autoSaveFile" << endl;
858 autoSaveFile.close();
859 mLastAutoSaveErrno = 0;
862 kdDebug(5006) << k_funcinfo <<
"autosaving failed" << endl;
863 autoSaveFile.abort();
864 if ( status != mLastAutoSaveErrno ) {
866 KMessageBox::queuedMessageBox( 0, KMessageBox::Sorry,
867 i18n(
"Autosaving the message as %1 "
870 .arg( filename, strerror( status ) ),
871 i18n(
"Autosaving Failed") );
872 mLastAutoSaveErrno = status;
876 if ( autoSaveInterval() > 0 )
881 void KMComposeWin::slotView(
void)
890 if (!sender()->isA(
"TDEToggleAction"))
892 TDEToggleAction *act = (TDEToggleAction *) sender();
894 if (act == mAllFieldsAction)
896 else if (act == mIdentityAction)
898 else if (act == mTransportAction)
900 else if (act == mFromAction)
902 else if (act == mReplyToAction)
904 else if (act == mToAction)
906 else if (act == mCcAction)
908 else if (act == mBccAction)
910 else if (act == mSubjectAction)
912 else if (act == mFccAction)
914 else if ( act == mDictionaryAction )
919 kdDebug(5006) <<
"Something is wrong (Oh, yeah?)" << endl;
926 if (!act->isChecked())
929 if (
id > 0) mShowHeaders = mShowHeaders & ~id;
930 else mShowHeaders = abs(mShowHeaders);
935 if (
id > 0) mShowHeaders |= id;
936 else mShowHeaders = -abs(mShowHeaders);
941 int KMComposeWin::calcColumnWidth(
int which,
long allShowing,
int width)
943 if ( (allShowing & which) == 0 )
947 if ( which == HDR_IDENTITY )
949 else if ( which == HDR_DICTIONARY )
950 w = mDictionaryLabel;
951 else if ( which == HDR_FCC )
953 else if ( which == HDR_TRANSPORT )
955 else if ( which == HDR_FROM )
957 else if ( which == HDR_REPLY_TO )
959 else if ( which == HDR_SUBJECT )
964 w->setBuddy( mEditor );
967 return TQMAX( width, w->sizeHint().width() );
970 void KMComposeWin::rethinkFields(
bool fromSlot)
973 int mask, row, numRows;
976 if (mShowHeaders < 0)
977 showHeaders = HDR_ALL;
979 showHeaders = mShowHeaders;
981 for (mask=1,mNumHeaders=0; mask<=showHeaders; mask<<=1)
982 if ((showHeaders&mask) != 0) mNumHeaders++;
984 numRows = mNumHeaders + 1;
988 mGrid =
new TQGridLayout( mHeadersArea, numRows, 3, KDialogBase::marginHint()/2, KDialogBase::spacingHint());
989 mGrid->setColStretch(0, 1);
990 mGrid->setColStretch(1, 100);
991 mGrid->setColStretch(2, 1);
992 mGrid->setRowStretch( mNumHeaders + 1, 100 );
995 kdDebug(5006) <<
"KMComposeWin::rethinkFields" << endl;
996 if (mRecipientsEditor)
997 mLabelWidth = mRecipientsEditor->setFirstColumnWidth( 0 );
998 mLabelWidth = calcColumnWidth( HDR_IDENTITY, showHeaders, mLabelWidth );
999 mLabelWidth = calcColumnWidth( HDR_DICTIONARY, showHeaders, mLabelWidth );
1000 mLabelWidth = calcColumnWidth( HDR_FCC, showHeaders, mLabelWidth );
1001 mLabelWidth = calcColumnWidth( HDR_TRANSPORT, showHeaders, mLabelWidth );
1002 mLabelWidth = calcColumnWidth( HDR_FROM, showHeaders, mLabelWidth );
1003 mLabelWidth = calcColumnWidth( HDR_REPLY_TO, showHeaders, mLabelWidth );
1004 mLabelWidth = calcColumnWidth( HDR_SUBJECT, showHeaders, mLabelWidth );
1006 if (!fromSlot) mAllFieldsAction->setChecked(showHeaders==HDR_ALL);
1008 if (!fromSlot) mIdentityAction->setChecked(abs(mShowHeaders)&HDR_IDENTITY);
1009 rethinkHeaderLine(showHeaders,HDR_IDENTITY, row,
1010 mLblIdentity, mIdentity, mBtnIdentity);
1012 if (!fromSlot) mDictionaryAction->setChecked(abs(mShowHeaders)&HDR_DICTIONARY);
1013 rethinkHeaderLine(showHeaders,HDR_DICTIONARY, row,
1014 mDictionaryLabel, mDictionaryCombo, mBtnDictionary );
1016 if (!fromSlot) mFccAction->setChecked(abs(mShowHeaders)&HDR_FCC);
1017 rethinkHeaderLine(showHeaders,HDR_FCC, row,
1018 mLblFcc, mFcc, mBtnFcc);
1020 if (!fromSlot) mTransportAction->setChecked(abs(mShowHeaders)&HDR_TRANSPORT);
1021 rethinkHeaderLine(showHeaders,HDR_TRANSPORT, row,
1022 mLblTransport, mTransport, mBtnTransport);
1024 if (!fromSlot) mFromAction->setChecked(abs(mShowHeaders)&HDR_FROM);
1025 rethinkHeaderLine(showHeaders,HDR_FROM, row,
1026 mLblFrom, mEdtFrom );
1028 TQWidget *prevFocus = mEdtFrom;
1030 if (!fromSlot) mReplyToAction->setChecked(abs(mShowHeaders)&HDR_REPLY_TO);
1031 rethinkHeaderLine(showHeaders,HDR_REPLY_TO,row,
1032 mLblReplyTo, mEdtReplyTo, 0);
1033 if ( showHeaders & HDR_REPLY_TO ) {
1034 prevFocus = connectFocusMoving( prevFocus, mEdtReplyTo );
1037 if ( mClassicalRecipients ) {
1038 if (!fromSlot) mToAction->setChecked(abs(mShowHeaders)&HDR_TO);
1039 rethinkHeaderLine(showHeaders, HDR_TO, row,
1040 mLblTo, mEdtTo, mBtnTo,
1041 i18n(
"Primary Recipients"),
1042 i18n(
"<qt>The email addresses you put "
1043 "in this field receive a copy of the email.</qt>"));
1044 if ( showHeaders & HDR_TO ) {
1045 prevFocus = connectFocusMoving( prevFocus, mEdtTo );
1048 if (!fromSlot) mCcAction->setChecked(abs(mShowHeaders)&HDR_CC);
1049 rethinkHeaderLine(showHeaders, HDR_CC, row,
1050 mLblCc, mEdtCc, mBtnCc,
1051 i18n(
"Additional Recipients"),
1052 i18n(
"<qt>The email addresses you put "
1053 "in this field receive a copy of the email. "
1054 "Technically it is the same thing as putting all the "
1055 "addresses in the <b>To:</b> field but differs in "
1056 "that it usually symbolises the receiver of the "
1057 "Carbon Copy (CC) is a listener, not the main "
1058 "recipient.</qt>"));
1059 if ( showHeaders & HDR_CC ) {
1060 prevFocus = connectFocusMoving( prevFocus, mEdtCc );
1063 if (!fromSlot) mBccAction->setChecked(abs(mShowHeaders)&HDR_BCC);
1064 rethinkHeaderLine(showHeaders,HDR_BCC, row,
1065 mLblBcc, mEdtBcc, mBtnBcc,
1066 i18n(
"Hidden Recipients"),
1067 i18n(
"<qt>Essentially the same thing "
1068 "as the <b>Copy To:</b> field but differs in that "
1069 "all other recipients do not see who receives a "
1070 "blind copy.</qt>"));
1071 if ( showHeaders & HDR_BCC ) {
1072 prevFocus = connectFocusMoving( prevFocus, mEdtBcc );
1075 mGrid->addMultiCellWidget( mRecipientsEditor, row, row, 0, 2 );
1078 if ( showHeaders & HDR_REPLY_TO ) {
1079 connect( mEdtReplyTo, TQ_SIGNAL( focusDown() ), mRecipientsEditor,
1080 TQ_SLOT( setFocusTop() ) );
1082 connect( mEdtFrom, TQ_SIGNAL( focusDown() ), mRecipientsEditor,
1083 TQ_SLOT( setFocusTop() ) );
1085 if ( showHeaders & HDR_REPLY_TO ) {
1086 connect( mRecipientsEditor, TQ_SIGNAL( focusUp() ), mEdtReplyTo, TQ_SLOT( setFocus() ) );
1088 connect( mRecipientsEditor, TQ_SIGNAL( focusUp() ), mEdtFrom, TQ_SLOT( setFocus() ) );
1091 connect( mRecipientsEditor, TQ_SIGNAL( focusDown() ), mEdtSubject,
1092 TQ_SLOT( setFocus() ) );
1093 connect( mEdtSubject, TQ_SIGNAL( focusUp() ), mRecipientsEditor,
1094 TQ_SLOT( setFocusBottom() ) );
1096 prevFocus = mRecipientsEditor;
1098 if (!fromSlot) mSubjectAction->setChecked(abs(mShowHeaders)&HDR_SUBJECT);
1099 rethinkHeaderLine(showHeaders,HDR_SUBJECT, row,
1100 mLblSubject, mEdtSubject);
1101 connectFocusMoving( mEdtSubject, mEditor );
1103 assert(row<=mNumHeaders);
1106 if( !mAtmList.isEmpty() )
1107 mAtmListView->show();
1109 mAtmListView->hide();
1110 resize(this->size());
1113 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
1115 mHeadersArea->show();
1117 slotUpdateAttachActions();
1118 mIdentityAction->setEnabled(!mAllFieldsAction->isChecked());
1119 mDictionaryAction->setEnabled( !mAllFieldsAction->isChecked() );
1120 mTransportAction->setEnabled(!mAllFieldsAction->isChecked());
1121 mFromAction->setEnabled(!mAllFieldsAction->isChecked());
1122 if ( mReplyToAction ) mReplyToAction->setEnabled(!mAllFieldsAction->isChecked());
1123 if ( mToAction ) mToAction->setEnabled(!mAllFieldsAction->isChecked());
1124 if ( mCcAction ) mCcAction->setEnabled(!mAllFieldsAction->isChecked());
1125 if ( mBccAction ) mBccAction->setEnabled(!mAllFieldsAction->isChecked());
1126 mFccAction->setEnabled(!mAllFieldsAction->isChecked());
1127 mSubjectAction->setEnabled(!mAllFieldsAction->isChecked());
1128 if (mRecipientsEditor)
1129 mRecipientsEditor->setFirstColumnWidth( mLabelWidth );
1132 TQWidget *KMComposeWin::connectFocusMoving( TQWidget *prev, TQWidget *next )
1134 connect( prev, TQ_SIGNAL( focusDown() ), next, TQ_SLOT( setFocus() ) );
1135 connect( next, TQ_SIGNAL( focusUp() ), prev, TQ_SLOT( setFocus() ) );
1141 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
1143 TQLineEdit* aEdt, TQPushButton* aBtn,
1144 const TQString &toolTip,
const TQString &whatsThis )
1148 if ( !toolTip.isEmpty() )
1149 TQToolTip::add( aLbl, toolTip );
1150 if ( !whatsThis.isEmpty() )
1151 TQWhatsThis::add( aLbl, whatsThis );
1152 aLbl->setFixedWidth( mLabelWidth );
1153 aLbl->setBuddy(aEdt);
1154 mGrid->addWidget(aLbl, aRow, 0);
1155 aEdt->setBackgroundColor( mBackColor );
1159 mGrid->addWidget(aEdt, aRow, 1);
1161 mGrid->addWidget(aBtn, aRow, 2);
1164 mGrid->addMultiCellWidget(aEdt, aRow, aRow, 1, 2 );
1172 if (aBtn) aBtn->hide();
1177 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int& aRow,
1179 TQComboBox* aCbx, TQCheckBox* aChk)
1184 aLbl->resize((
int)aLbl->sizeHint().width(),aLbl->sizeHint().height() + 6);
1185 aLbl->setMinimumSize(aLbl->size());
1187 aLbl->setBuddy(aCbx);
1188 mGrid->addWidget(aLbl, aRow, 0);
1190 aCbx->setMinimumSize(100, aLbl->height()+2);
1192 mGrid->addWidget(aCbx, aRow, 1);
1194 mGrid->addWidget(aChk, aRow, 2);
1195 aChk->setFixedSize(aChk->sizeHint().width(), aLbl->height());
1210 void KMComposeWin::getTransportMenu()
1212 TQStringList availTransports;
1214 mActNowMenu->clear();
1215 mActLaterMenu->clear();
1217 TQStringList::Iterator it;
1219 for(it = availTransports.begin(); it != availTransports.end() ; ++it,
id++)
1221 mActNowMenu->insertItem((*it).replace(
"&",
"&&"),
id);
1222 mActLaterMenu->insertItem((*it).replace(
"&",
"&&"),
id);
1228 void KMComposeWin::setupActions(
void)
1230 TDEActionMenu *actActionNowMenu, *actActionLaterMenu;
1232 if (kmkernel->msgSender()->sendImmediate())
1235 ( void )
new TDEAction( i18n(
"&Send Mail"),
"mail-send", CTRL+Key_Return,
1236 this, TQ_SLOT(slotSendNow()), actionCollection(),
"send_default");
1239 actActionNowMenu =
new TDEActionMenu (i18n(
"&Send Mail Via"),
"mail-send",
1240 actionCollection(),
"send_default_via" );
1242 (void)
new TDEAction (i18n(
"Send &Later"),
"queue", 0,
this,
1243 TQ_SLOT(slotSendLater()), actionCollection(),
"send_alternative");
1244 actActionLaterMenu =
new TDEActionMenu (i18n(
"Send &Later Via"),
"queue",
1245 actionCollection(),
"send_alternative_via" );
1251 (void)
new TDEAction (i18n(
"Send &Later"),
"queue",
1253 this, TQ_SLOT(slotSendLater()), actionCollection(),
"send_default");
1254 actActionLaterMenu =
new TDEActionMenu (i18n(
"Send &Later Via"),
"queue",
1255 actionCollection(),
"send_default_via" );
1257 ( void )
new TDEAction( i18n(
"&Send Mail"),
"mail-send", 0,
1258 this, TQ_SLOT(slotSendNow()), actionCollection(),
"send_alternative");
1261 actActionNowMenu =
new TDEActionMenu (i18n(
"&Send Mail Via"),
"mail-send",
1262 actionCollection(),
"send_alternative_via" );
1267 actActionNowMenu->setDelayed(
true);
1268 actActionLaterMenu->setDelayed(
true);
1270 connect( actActionNowMenu, TQ_SIGNAL( activated() ),
this,
1271 TQ_SLOT( slotSendNow() ) );
1272 connect( actActionLaterMenu, TQ_SIGNAL( activated() ),
this,
1273 TQ_SLOT( slotSendLater() ) );
1276 mActNowMenu = actActionNowMenu->popupMenu();
1277 mActLaterMenu = actActionLaterMenu->popupMenu();
1279 connect( mActNowMenu, TQ_SIGNAL( activated(
int ) ),
this,
1280 TQ_SLOT( slotSendNowVia(
int ) ) );
1281 connect( mActNowMenu, TQ_SIGNAL( aboutToShow() ),
this,
1282 TQ_SLOT( getTransportMenu() ) );
1284 connect( mActLaterMenu, TQ_SIGNAL( activated(
int ) ),
this,
1285 TQ_SLOT( slotSendLaterVia(
int ) ) );
1286 connect( mActLaterMenu, TQ_SIGNAL( aboutToShow() ),
this,
1287 TQ_SLOT( getTransportMenu() ) );
1292 (void)
new TDEAction (i18n(
"Save as &Draft"),
"document-save", 0,
1293 this, TQ_SLOT(slotSaveDraft()),
1294 actionCollection(),
"save_in_drafts");
1295 (void)
new TDEAction (i18n(
"Save as &Template"),
"document-save", 0,
1296 this, TQ_SLOT(slotSaveTemplate()),
1297 actionCollection(),
"save_in_templates");
1298 (void)
new TDEAction (i18n(
"&Insert File..."),
"document-open", 0,
1299 this, TQ_SLOT(slotInsertFile()),
1300 actionCollection(),
"insert_file");
1301 mRecentAction =
new TDERecentFilesAction (i18n(
"&Insert File Recent"),
1303 this, TQ_SLOT(slotInsertRecentFile(
const KURL&)),
1304 actionCollection(),
"insert_file_recent");
1306 mRecentAction->loadEntries( KMKernel::config() );
1308 (void)
new TDEAction (i18n(
"&Address Book"),
"contents",0,
1309 this, TQ_SLOT(slotAddrBook()),
1310 actionCollection(),
"addressbook");
1311 (void)
new TDEAction (i18n(
"&New Composer"),
"mail-message-new",
1312 TDEStdAccel::shortcut(TDEStdAccel::New),
1313 this, TQ_SLOT(slotNewComposer()),
1314 actionCollection(),
"new_composer");
1315 (void)
new TDEAction (i18n(
"New Main &Window"),
"window-new", 0,
1316 this, TQ_SLOT(slotNewMailReader()),
1317 actionCollection(),
"open_mailreader");
1319 if ( !mClassicalRecipients ) {
1320 new TDEAction( i18n(
"Select &Recipients..."), CTRL + Key_L, mRecipientsEditor,
1321 TQ_SLOT( selectRecipients() ), actionCollection(),
"select_recipients" );
1322 new TDEAction( i18n(
"Save &Distribution List..."), 0, mRecipientsEditor,
1323 TQ_SLOT( saveDistributionList() ), actionCollection(),
1324 "save_distribution_list" );
1328 KStdAction::print (
this, TQ_SLOT(slotPrint()), actionCollection());
1329 KStdAction::close (
this, TQ_SLOT(slotClose()), actionCollection());
1331 KStdAction::undo (
this, TQ_SLOT(slotUndo()), actionCollection());
1332 KStdAction::redo (
this, TQ_SLOT(slotRedo()), actionCollection());
1333 KStdAction::cut (
this, TQ_SLOT(slotCut()), actionCollection());
1334 KStdAction::copy (
this, TQ_SLOT(slotCopy()), actionCollection());
1335 KStdAction::pasteText (
this, TQ_SLOT(slotPasteClipboard()), actionCollection());
1336 KStdAction::selectAll (
this, TQ_SLOT(slotMarkAll()), actionCollection());
1338 KStdAction::find (
this, TQ_SLOT(slotFind()), actionCollection());
1339 KStdAction::findNext(
this, TQ_SLOT(slotSearchAgain()), actionCollection());
1341 KStdAction::replace (
this, TQ_SLOT(slotReplace()), actionCollection());
1342 KStdAction::spelling (
this, TQ_SLOT(slotSpellcheck()), actionCollection(),
"tools-check-spelling");
1344 mPasteQuotation =
new TDEAction (i18n(
"Pa&ste as Quotation"),0,
this,TQ_SLOT( slotPasteClipboardAsQuotation()),
1345 actionCollection(),
"paste_quoted");
1347 (void)
new TDEAction (i18n(
"Paste as Attac&hment"),0,
this,TQ_SLOT( slotPasteClipboardAsAttachment()),
1348 actionCollection(),
"paste_att");
1350 TDEAction * addq =
new TDEAction(i18n(
"Add &Quote Characters"), 0,
this,
1351 TQ_SLOT(slotAddQuotes()), actionCollection(),
"tools_quote");
1352 connect( mEditor, TQ_SIGNAL(selectionAvailable(
bool)),
1353 addq, TQ_SLOT(setEnabled(
bool)) );
1355 TDEAction * remq =
new TDEAction(i18n(
"Re&move Quote Characters"), 0,
this,
1356 TQ_SLOT(slotRemoveQuotes()), actionCollection(),
"tools_unquote");
1357 connect( mEditor, TQ_SIGNAL(selectionAvailable(
bool)),
1358 remq, TQ_SLOT(setEnabled(
bool)) );
1361 (void)
new TDEAction (i18n(
"Cl&ean Spaces"), 0,
this, TQ_SLOT(slotCleanSpace()),
1362 actionCollection(),
"clean_spaces");
1364 mFixedFontAction =
new TDEToggleAction( i18n(
"Use Fi&xed Font"), 0,
this,
1365 TQ_SLOT(slotUpdateFont()), actionCollection(),
"toggle_fixedfont" );
1366 mFixedFontAction->setChecked( GlobalSettings::self()->useFixedFont() );
1369 mUrgentAction =
new TDEToggleAction (i18n(
"&Urgent"), 0,
1372 mRequestMDNAction =
new TDEToggleAction ( i18n(
"&Request Disposition Notification"), 0,
1374 "options_request_mdn");
1375 mRequestMDNAction->setChecked(GlobalSettings::self()->requestMDN());
1377 mEncodingAction =
new TDESelectAction( i18n(
"Se&t Encoding" ),
"charset",
1378 0,
this, TQ_SLOT(slotSetCharset() ),
1379 actionCollection(),
"charsets" );
1380 mWordWrapAction =
new TDEToggleAction (i18n(
"&Wordwrap"), 0,
1381 actionCollection(),
"wordwrap");
1382 mWordWrapAction->setChecked(GlobalSettings::self()->wordWrap());
1383 connect(mWordWrapAction, TQ_SIGNAL(toggled(
bool)), TQ_SLOT(slotWordWrapToggled(
bool)));
1385 mSnippetAction =
new TDEToggleAction ( i18n(
"&Snippets"), 0,
1386 actionCollection(),
"snippets");
1387 connect(mSnippetAction, TQ_SIGNAL(toggled(
bool)), mSnippetWidget, TQ_SLOT(setShown(
bool)) );
1388 mSnippetAction->setChecked( GlobalSettings::self()->showSnippetManager() );
1390 mAutoSpellCheckingAction =
1391 new TDEToggleAction( i18n(
"&Automatic Spellchecking" ),
"tools-check-spelling", 0,
1392 actionCollection(),
"options_auto_spellchecking" );
1393 const bool spellChecking = GlobalSettings::self()->autoSpellChecking();
1394 mAutoSpellCheckingAction->setEnabled( !GlobalSettings::self()->useExternalEditor() );
1395 mAutoSpellCheckingAction->setChecked( !GlobalSettings::self()->useExternalEditor() && spellChecking );
1396 slotAutoSpellCheckingToggled( !GlobalSettings::self()->useExternalEditor() && spellChecking );
1397 connect( mAutoSpellCheckingAction, TQ_SIGNAL( toggled(
bool ) ),
1398 this, TQ_SLOT( slotAutoSpellCheckingToggled(
bool ) ) );
1400 TQStringList encodings = KMMsgBase::supportedEncodings(
true);
1401 encodings.prepend( i18n(
"Auto-Detect"));
1402 mEncodingAction->setItems( encodings );
1403 mEncodingAction->setCurrentItem( -1 );
1406 markupAction =
new TDEToggleAction (i18n(
"Formatting (HTML)"), 0,
this,
1407 TQ_SLOT(slotToggleMarkup()),
1408 actionCollection(),
"html");
1410 mAllFieldsAction =
new TDEToggleAction (i18n(
"&All Fields"), 0,
this,
1411 TQ_SLOT(slotView()),
1412 actionCollection(),
"show_all_fields");
1413 mIdentityAction =
new TDEToggleAction (i18n(
"&Identity"), 0,
this,
1414 TQ_SLOT(slotView()),
1415 actionCollection(),
"show_identity");
1416 mDictionaryAction =
new TDEToggleAction (i18n(
"&Dictionary"), 0,
this,
1417 TQ_SLOT(slotView()),
1418 actionCollection(),
"show_dictionary");
1419 mFccAction =
new TDEToggleAction (i18n(
"&Sent-Mail Folder"), 0,
this,
1420 TQ_SLOT(slotView()),
1421 actionCollection(),
"show_fcc");
1422 mTransportAction =
new TDEToggleAction (i18n(
"&Mail Transport"), 0,
this,
1423 TQ_SLOT(slotView()),
1424 actionCollection(),
"show_transport");
1425 mFromAction =
new TDEToggleAction (i18n(
"&From"), 0,
this,
1426 TQ_SLOT(slotView()),
1427 actionCollection(),
"show_from");
1428 mReplyToAction =
new TDEToggleAction (i18n(
"&Reply To"), 0,
this,
1429 TQ_SLOT(slotView()),
1430 actionCollection(),
"show_reply_to");
1431 if ( mClassicalRecipients ) {
1432 mToAction =
new TDEToggleAction (i18n(
"&To"), 0,
this,
1433 TQ_SLOT(slotView()),
1434 actionCollection(),
"show_to");
1435 mCcAction =
new TDEToggleAction (i18n(
"&CC"), 0,
this,
1436 TQ_SLOT(slotView()),
1437 actionCollection(),
"show_cc");
1438 mBccAction =
new TDEToggleAction (i18n(
"&BCC"), 0,
this,
1439 TQ_SLOT(slotView()),
1440 actionCollection(),
"show_bcc");
1442 mSubjectAction =
new TDEToggleAction (i18n(
"S&ubject"), 0,
this,
1443 TQ_SLOT(slotView()),
1444 actionCollection(),
"show_subject");
1447 mAppendSignatureAction =
new TDEAction (i18n(
"Append S&ignature"), 0,
this,
1448 TQ_SLOT(slotAppendSignature()),
1449 actionCollection(),
"append_signature");
1450 mPrependSignatureAction =
new TDEAction (i18n(
"Prepend S&ignature"), 0,
this,
1451 TQ_SLOT(slotPrependSignature()),
1452 actionCollection(),
"prepend_signature");
1454 mInsertSignatureAction =
new TDEAction (i18n(
"Insert Signature At C&ursor Position"),
"edit", 0,
this,
1455 TQ_SLOT(slotInsertSignatureAtCursor()),
1456 actionCollection(),
"insert_signature_at_cursor_position");
1458 mAttachPK =
new TDEAction (i18n(
"Attach &Public Key..."), 0,
this,
1459 TQ_SLOT(slotInsertPublicKey()),
1460 actionCollection(),
"attach_public_key");
1461 mAttachMPK =
new TDEAction (i18n(
"Attach &My Public Key"), 0,
this,
1462 TQ_SLOT(slotInsertMyPublicKey()),
1463 actionCollection(),
"attach_my_public_key");
1464 (void)
new TDEAction (i18n(
"&Attach File..."),
"attach",
1465 0,
this, TQ_SLOT(slotAttachFile()),
1466 actionCollection(),
"attach");
1467 mAttachRemoveAction =
new TDEAction (i18n(
"&Remove Attachment"), 0,
this,
1468 TQ_SLOT(slotAttachRemove()),
1469 actionCollection(),
"remove");
1470 mAttachSaveAction =
new TDEAction (i18n(
"&Save Attachment As..."),
"document-save",0,
1471 this, TQ_SLOT(slotAttachSave()),
1472 actionCollection(),
"attach_save");
1473 mAttachPropertiesAction =
new TDEAction (i18n(
"Attachment Pr&operties"), 0,
this,
1474 TQ_SLOT(slotAttachProperties()),
1475 actionCollection(),
"attach_properties");
1477 setStandardToolBarMenuEnabled(
true);
1479 KStdAction::keyBindings(
this, TQ_SLOT(slotEditKeys()), actionCollection());
1480 KStdAction::configureToolbars(
this, TQ_SLOT(slotEditToolbars()), actionCollection());
1481 KStdAction::preferences(kmkernel, TQ_SLOT(slotShowConfigurationDialog()), actionCollection());
1483 (void)
new TDEAction (i18n(
"&Spellchecker..."), 0,
this, TQ_SLOT(slotSpellcheckConfig()),
1484 actionCollection(),
"setup_spellchecker");
1486 if ( Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) ) {
1487 TDEToggleAction * a =
new TDEToggleAction( i18n(
"Encrypt Message with Chiasmus..." ),
1488 "chidecrypted", 0, actionCollection(),
1489 "encrypt_message_chiasmus" );
1490 a->setCheckedState( KGuiItem( i18n(
"Encrypt Message with Chiasmus..." ),
"chiencrypted" ) );
1491 mEncryptChiasmusAction = a;
1492 connect( mEncryptChiasmusAction, TQ_SIGNAL(toggled(
bool)),
1493 this, TQ_SLOT(slotEncryptChiasmusToggled(
bool)) );
1495 mEncryptChiasmusAction = 0;
1498 mEncryptAction =
new TDEToggleAction (i18n(
"&Encrypt Message"),
1500 actionCollection(),
"encrypt_message");
1501 mSignAction =
new TDEToggleAction (i18n(
"&Sign Message"),
1503 actionCollection(),
"sign_message");
1505 const KPIM::Identity & ident =
1506 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
1509 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1510 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1512 mLastEncryptActionState =
false;
1513 mLastSignActionState = GlobalSettings::self()->pgpAutoSign();
1516 mAttachPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() );
1520 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
1521 !ident.pgpEncryptionKey().isEmpty() );
1523 if ( !Kleo::CryptoBackendFactory::instance()->openpgp() && !Kleo::CryptoBackendFactory::instance()->smime() ) {
1525 mEncryptAction->setEnabled(
false );
1526 setEncryption(
false );
1527 mSignAction->setEnabled(
false );
1528 setSigning(
false );
1530 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
1531 && !ident.pgpSigningKey().isEmpty();
1532 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
1533 && !ident.smimeSigningKey().isEmpty();
1535 setEncryption(
false );
1536 setSigning( ( canOpenPGPSign || canSMIMESign ) && GlobalSettings::self()->pgpAutoSign() );
1539 connect(mEncryptAction, TQ_SIGNAL(toggled(
bool)),
1540 TQ_SLOT(slotEncryptToggled(
bool )));
1541 connect(mSignAction, TQ_SIGNAL(toggled(
bool)),
1542 TQ_SLOT(slotSignToggled(
bool )));
1545 for (
int i = 0 ; i < numCryptoMessageFormats ; ++i )
1546 l.push_back( Kleo::cryptoMessageFormatToLabel( cryptoMessageFormats[i] ) );
1548 mCryptoModuleAction =
new TDESelectAction( i18n(
"&Cryptographic Message Format" ), 0,
1549 this, TQ_SLOT(slotSelectCryptoModule()),
1550 actionCollection(),
"options_select_crypto" );
1551 mCryptoModuleAction->setItems( l );
1552 mCryptoModuleAction->setCurrentItem( format2cb( ident.preferredCryptoMessageFormat() ) );
1553 mCryptoModuleAction->setToolTip( i18n(
"Select a cryptographic format for this message" ) );
1554 slotSelectCryptoModule(
true );
1556 TQStringList styleItems;
1557 styleItems << i18n(
"Standard" );
1558 styleItems << i18n(
"Bulleted List (Disc)" );
1559 styleItems << i18n(
"Bulleted List (Circle)" );
1560 styleItems << i18n(
"Bulleted List (Square)" );
1561 styleItems << i18n(
"Ordered List (Decimal)" );
1562 styleItems << i18n(
"Ordered List (Alpha lower)" );
1563 styleItems << i18n(
"Ordered List (Alpha upper)" );
1565 listAction =
new TDESelectAction( i18n(
"Select Style" ), 0, actionCollection(),
1567 listAction->setItems( styleItems );
1568 listAction->setToolTip( i18n(
"Select a list style" ) );
1569 connect( listAction, TQ_SIGNAL( activated(
const TQString& ) ),
1570 TQ_SLOT( slotListAction(
const TQString& ) ) );
1571 fontAction =
new TDEFontAction(
"Select Font", 0, actionCollection(),
1573 fontAction->setToolTip( i18n(
"Select a font" ) );
1574 connect( fontAction, TQ_SIGNAL( activated(
const TQString& ) ),
1575 TQ_SLOT( slotFontAction(
const TQString& ) ) );
1576 fontSizeAction =
new TDEFontSizeAction(
"Select Size", 0, actionCollection(),
1578 fontSizeAction->setToolTip( i18n(
"Select a font size" ) );
1579 connect( fontSizeAction, TQ_SIGNAL( fontSizeChanged(
int ) ),
1580 TQ_SLOT( slotSizeAction(
int ) ) );
1582 alignLeftAction =
new TDEToggleAction (i18n(
"Align Left"),
"format-text-direction-ltr", 0,
1583 this, TQ_SLOT(slotAlignLeft()), actionCollection(),
1585 alignLeftAction->setChecked(
true );
1586 alignRightAction =
new TDEToggleAction (i18n(
"Align Right"),
"format-text-direction-rtl", 0,
1587 this, TQ_SLOT(slotAlignRight()), actionCollection(),
1589 alignCenterAction =
new TDEToggleAction (i18n(
"Align Center"),
"text_center", 0,
1590 this, TQ_SLOT(slotAlignCenter()), actionCollection(),
1592 textBoldAction =
new TDEToggleAction( i18n(
"&Bold"),
"format-text-bold", CTRL+Key_B,
1593 this, TQ_SLOT(slotTextBold()),
1594 actionCollection(),
"format-text-bold");
1595 textItalicAction =
new TDEToggleAction( i18n(
"&Italic"),
"format-text-italic", CTRL+Key_I,
1596 this, TQ_SLOT(slotTextItalic()),
1597 actionCollection(),
"format-text-italic");
1598 textUnderAction =
new TDEToggleAction( i18n(
"&Underline"),
"format-text-underline", CTRL+Key_U,
1599 this, TQ_SLOT(slotTextUnder()),
1600 actionCollection(),
"format-text-underline");
1601 actionFormatReset =
new TDEAction( i18n(
"Reset Font Settings" ),
"eraser", 0,
1602 this, TQ_SLOT( slotFormatReset() ),
1603 actionCollection(),
"format_reset");
1604 actionFormatColor =
new TDEAction( i18n(
"Text Color..." ),
"colorize", 0,
1605 this, TQ_SLOT( slotTextColor() ),
1606 actionCollection(),
"format_color");
1609 createGUI(
"kmcomposerui.rc");
1611 connect( toolBar(
"htmlToolBar"), TQ_SIGNAL( visibilityChanged(
bool) ),
1612 this, TQ_SLOT( htmlToolBarVisibilityChanged(
bool) ) );
1616 TDEAction* configureAction = actionCollection()->action(
"options_configure" );
1617 if ( configureAction )
1618 configureAction->setText( i18n(
"Configure KMail..." ) );
1622 void KMComposeWin::setupStatusBar(
void)
1624 statusBar()->insertItem(
"", 0, 1);
1625 statusBar()->setItemAlignment(0, AlignLeft | AlignVCenter);
1627 statusBar()->insertItem(i18n(
" Spellcheck: %1 ").arg(
" " ), 3, 0,
true );
1628 statusBar()->insertItem(i18n(
" Column: %1 ").arg(
" "), 2, 0,
true);
1629 statusBar()->insertItem(i18n(
" Line: %1 ").arg(
" "), 1, 0,
true);
1634 void KMComposeWin::updateCursorPosition()
1638 line = mEditor->currentLine();
1639 col = mEditor->currentColumn();
1640 temp = i18n(
" Line: %1 ").arg(line+1);
1641 statusBar()->changeItem(temp,1);
1642 temp = i18n(
" Column: %1 ").arg(col+1);
1643 statusBar()->changeItem(temp,2);
1648 void KMComposeWin::setupEditor(
void)
1651 mEditor->setModified(
false);
1652 TQFontMetrics fm(mBodyFont);
1653 mEditor->setTabStopWidth(fm.width(TQChar(
' ')) * 8);
1656 slotWordWrapToggled( GlobalSettings::self()->wordWrap() );
1682 updateCursorPosition();
1683 connect(mEditor,TQ_SIGNAL(CursorPositionChanged()),TQ_SLOT(updateCursorPosition()));
1684 connect( mEditor, TQ_SIGNAL( currentFontChanged(
const TQFont & ) ),
1685 this, TQ_SLOT( fontChanged(
const TQFont & ) ) );
1686 connect( mEditor, TQ_SIGNAL( currentAlignmentChanged(
int ) ),
1687 this, TQ_SLOT( alignmentChanged(
int ) ) );
1693 static TQString cleanedUpHeaderString(
const TQString & s )
1697 res.replace(
'\r',
"" );
1698 res.replace(
'\n',
" " );
1699 return res.stripWhiteSpace();
1703 TQString KMComposeWin::subject()
const
1705 return cleanedUpHeaderString( mEdtSubject->text() );
1709 TQString KMComposeWin::to()
const
1712 return cleanedUpHeaderString( mEdtTo->text() );
1713 }
else if ( mRecipientsEditor ) {
1714 return mRecipientsEditor->recipientString( Recipient::To );
1721 TQString KMComposeWin::cc()
const
1723 if ( mEdtCc && !mEdtCc->isHidden() ) {
1724 return cleanedUpHeaderString( mEdtCc->text() );
1725 }
else if ( mRecipientsEditor ) {
1726 return mRecipientsEditor->recipientString( Recipient::Cc );
1733 TQString KMComposeWin::bcc()
const
1735 if ( mEdtBcc && !mEdtBcc->isHidden() ) {
1736 return cleanedUpHeaderString( mEdtBcc->text() );
1737 }
else if ( mRecipientsEditor ) {
1738 return mRecipientsEditor->recipientString( Recipient::Bcc );
1745 TQString KMComposeWin::from()
const
1747 return cleanedUpHeaderString( mEdtFrom->text() );
1751 TQString KMComposeWin::replyTo()
const
1753 if ( mEdtReplyTo ) {
1754 return cleanedUpHeaderString( mEdtReplyTo->text() );
1761 void KMComposeWin::verifyWordWrapLengthIsAdequate(
const TQString &body)
1763 int maxLineLength = 0;
1766 if (mEditor->TQTextEdit::wordWrap() == TQTextEdit::FixedColumnWidth) {
1767 for (curPos = 0; curPos < (int)body.length(); ++curPos)
1768 if (body[curPos] ==
'\n') {
1769 if ((curPos - oldPos) > maxLineLength)
1770 maxLineLength = curPos - oldPos;
1773 if ((curPos - oldPos) > maxLineLength)
1774 maxLineLength = curPos - oldPos;
1775 if (mEditor->wrapColumnOrWidth() < maxLineLength)
1776 mEditor->setWrapColumnOrWidth(maxLineLength);
1781 void KMComposeWin::decryptOrStripOffCleartextSignature( TQCString& body )
1783 TQPtrList<Kpgp::Block> pgpBlocks;
1784 TQStrList nonPgpBlocks;
1785 if( Kpgp::Module::prepareMessageForDecryption( body,
1786 pgpBlocks, nonPgpBlocks ) )
1790 if( pgpBlocks.count() == 1 )
1792 Kpgp::Block* block = pgpBlocks.first();
1793 if( ( block->type() == Kpgp::PgpMessageBlock ) ||
1794 ( block->type() == Kpgp::ClearsignedBlock ) )
1796 if( block->type() == Kpgp::PgpMessageBlock )
1803 body = nonPgpBlocks.first()
1805 + nonPgpBlocks.last();
1812 void KMComposeWin::setTransport(
const TQString & transport )
1814 kdDebug(5006) <<
"KMComposeWin::setTransport( \"" << transport <<
"\" )" << endl;
1816 if ( transport.isEmpty() )
1819 bool transportFound =
false;
1820 for (
int i = 0; i < mTransport->count(); ++i ) {
1821 if ( mTransport->text(i) == transport ) {
1822 transportFound =
true;
1823 mTransport->setCurrentItem(i);
1824 kdDebug(5006) <<
"transport found, it's no. " << i <<
" in the list" << endl;
1828 if ( !transportFound ) {
1829 kdDebug(5006) <<
"unknown transport \"" << transport <<
"\"" << endl;
1830 if ( transport.startsWith(
"smtp://") || transport.startsWith(
"smtps://") ||
1831 transport.startsWith(
"file://") ) {
1833 mTransport->setEditText( transport );
1837 mTransport->setCurrentText( GlobalSettings::self()->defaultTransport() );
1843 void KMComposeWin::setMsg(
KMMessage* newMsg,
bool mayAutoSign,
1844 bool allowDecryption,
bool isModified)
1849 kdDebug(5006) <<
"KMComposeWin::setMsg() : newMsg == 0!" << endl;
1853 KPIM::IdentityManager * im = kmkernel->identityManager();
1855 mEdtFrom->setText(mMsg->from());
1856 mEdtReplyTo->setText(mMsg->replyTo());
1857 if ( mClassicalRecipients ) {
1858 mEdtTo->setText(mMsg->to());
1859 mEdtCc->setText(mMsg->cc());
1860 mEdtBcc->setText(mMsg->bcc());
1862 mRecipientsEditor->setRecipientString( mMsg->to(), Recipient::To );
1863 mRecipientsEditor->setRecipientString( mMsg->cc(), Recipient::Cc );
1864 mRecipientsEditor->setRecipientString( mMsg->bcc(), Recipient::Bcc );
1865 mRecipientsEditor->setFocusBottom();
1867 mEdtSubject->setText(mMsg->subject());
1869 const bool stickyIdentity = mBtnIdentity->isChecked() && !mIgnoreStickyFields;
1870 const bool messageHasIdentity = !newMsg->
headerField(
"X-KMail-Identity").isEmpty();
1871 if (!stickyIdentity && messageHasIdentity)
1872 mId = newMsg->
headerField(
"X-KMail-Identity").stripWhiteSpace().toUInt();
1876 if ( !stickyIdentity ) {
1877 disconnect(mIdentity,TQ_SIGNAL(identityChanged(uint)),
1878 this, TQ_SLOT(slotIdentityChanged(uint)));
1881 mIdentity->setCurrentIdentity( mId );
1882 const uint idToApply = mId;
1883 if ( !stickyIdentity ) {
1884 connect(mIdentity,TQ_SIGNAL(identityChanged(uint)),
1885 this, TQ_SLOT(slotIdentityChanged(uint)));
1890 if ( messageHasIdentity )
1891 mId = newMsg->
headerField(
"X-KMail-Identity").stripWhiteSpace().toUInt();
1893 mId = im->defaultIdentity().uoid();
1898 slotIdentityChanged( idToApply );
1900 const KPIM::Identity & ident = im->identityForUoid( mIdentity->currentIdentity() );
1904 TQString mdnAddr = newMsg->
headerField(
"Disposition-Notification-To");
1905 mRequestMDNAction->setChecked( ( !mdnAddr.isEmpty() &&
1906 im->thatIsMe( mdnAddr ) ) ||
1907 GlobalSettings::self()->requestMDN() );
1910 mUrgentAction->setChecked( newMsg->
isUrgent() );
1912 if (!ident.isXFaceEnabled() || ident.xface().isEmpty())
1913 mMsg->removeHeaderField(
"X-Face");
1916 TQString xface = ident.xface();
1917 if (!xface.isEmpty())
1919 int numNL = ( xface.length() - 1 ) / 70;
1920 for (
int i = numNL; i > 0; --i )
1921 xface.insert( i*70,
"\n\t" );
1922 mMsg->setHeaderField(
"X-Face", xface);
1927 switch ( mMsg->encryptionState() ) {
1928 case KMMsgFullyEncrypted:
1929 case KMMsgPartiallyEncrypted:
1930 mLastEncryptActionState =
true;
1932 case KMMsgNotEncrypted:
1933 mLastEncryptActionState =
false;
1940 switch ( mMsg->signatureState() ) {
1941 case KMMsgFullySigned:
1942 case KMMsgPartiallySigned:
1943 mLastSignActionState =
true;
1945 case KMMsgNotSigned:
1946 mLastSignActionState =
false;
1953 if ( mMsg->headers().FindField(
"X-KMail-SignatureActionEnabled" ) )
1954 mLastSignActionState = (mMsg->headerField(
"X-KMail-SignatureActionEnabled" ) ==
"true");
1955 if ( mMsg->headers().FindField(
"X-KMail-EncryptActionEnabled" ) )
1956 mLastEncryptActionState = (mMsg->headerField(
"X-KMail-EncryptActionEnabled" ) ==
"true");
1957 if ( mMsg->headers().FindField(
"X-KMail-CryptoMessageFormat" ) )
1958 mCryptoModuleAction->setCurrentItem( format2cb(
static_cast<Kleo::CryptoMessageFormat
>(
1959 mMsg->headerField(
"X-KMail-CryptoMessageFormat" ).toInt() ) ) );
1961 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1962 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1964 if ( Kleo::CryptoBackendFactory::instance()->openpgp() || Kleo::CryptoBackendFactory::instance()->smime() ) {
1965 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp()
1966 && !ident.pgpSigningKey().isEmpty();
1967 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime()
1968 && !ident.smimeSigningKey().isEmpty();
1970 setEncryption( mLastEncryptActionState );
1971 setSigning( ( canOpenPGPSign || canSMIMESign ) && mLastSignActionState );
1973 slotUpdateSignatureAndEncrypionStateIndicators();
1977 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
1978 !ident.pgpEncryptionKey().isEmpty() );
1980 TQString transport = newMsg->
headerField(
"X-KMail-Transport");
1981 const bool stickyTransport = mBtnTransport->isChecked() && !mIgnoreStickyFields;
1982 if (!stickyTransport && !transport.isEmpty()) {
1983 setTransport( transport );
1988 if (transport.isEmpty() && !mMsg->originatingAccountName().isEmpty()) {
1989 TQString transportCandidate = mMsg->originatingAccountName();
1990 bool transportFound =
false;
1991 for (
int i = 0; i < mTransport->count(); ++i ) {
1992 if ( mTransport->text(i) == transportCandidate ) {
1993 transportFound =
true;
1994 setTransport(transportCandidate);
2000 if (!mBtnFcc->isChecked())
2002 if (!mMsg->fcc().isEmpty())
2003 setFcc(mMsg->fcc());
2005 setFcc(ident.fcc());
2008 const bool stickyDictionary = mBtnDictionary->isChecked() && !mIgnoreStickyFields;
2009 if ( !stickyDictionary ) {
2010 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
2013 partNode * root = partNode::fromMessage( mMsg );
2015 KMail::ObjectTreeParser otp;
2016 otp.parseObjectTree( root );
2018 KMail::AttachmentCollector ac;
2019 ac.collectAttachmentsFrom( root );
2021 for ( std::vector<partNode*>::const_iterator it = ac.attachments().begin() ; it != ac.attachments().end() ; ++it )
2022 addAttach(
new KMMessagePart( (*it)->msgPart() ) );
2024 mEditor->setText( otp.textualContent() );
2025 mCharset = otp.textualContentCharset();
2026 if ( partNode * n = root->findType( DwMime::kTypeText, DwMime::kSubtypeHtml ) )
2027 if ( partNode * p = n->parentNode() )
2028 if ( p->hasType( DwMime::kTypeMultipart ) &&
2029 p->hasSubType( DwMime::kSubtypeAlternative ) )
2030 if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" ) {
2031 toggleMarkup(
true );
2034 mCharset = n->msgPart().charset();
2035 TQCString bodyDecoded = n->msgPart().bodyDecoded();
2038 const TQTextCodec *codec = KMMsgBase::codecForName( mCharset );
2040 mEditor->setText( codec->toUnicode( bodyDecoded ) );
2042 mEditor->setText( TQString::fromLocal8Bit( bodyDecoded ) );
2046 if ( mCharset.isEmpty() )
2047 mCharset = mMsg->charset();
2048 if ( mCharset.isEmpty() )
2049 mCharset = mDefCharset;
2050 setCharset( mCharset );
2053 if ( mMsg->numBodyParts() == 0 && otp.textualContent().isEmpty() ) {
2054 mCharset=mMsg->charset();
2055 if ( mCharset.isEmpty() || mCharset ==
"default" )
2056 mCharset = mDefCharset;
2058 TQCString bodyDecoded = mMsg->bodyDecoded();
2060 if( allowDecryption )
2061 decryptOrStripOffCleartextSignature( bodyDecoded );
2063 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2065 mEditor->setText(codec->toUnicode(bodyDecoded));
2067 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2069 #ifdef BROKEN_FOR_OPAQUE_SIGNED_OR_ENCRYPTED_MAILS
2070 const int num = mMsg->numBodyParts();
2071 kdDebug(5006) <<
"KMComposeWin::setMsg() mMsg->numBodyParts="
2072 << mMsg->numBodyParts() << endl;
2075 KMMessagePart bodyPart;
2076 int firstAttachment = 0;
2078 mMsg->bodyPart(1, &bodyPart);
2079 if ( bodyPart.typeStr().lower() ==
"text" &&
2080 bodyPart.subtypeStr().lower() ==
"html" ) {
2082 partNode *root = partNode::fromMessage( mMsg );
2083 partNode *node = root->findType( DwMime::kTypeText,
2084 DwMime::kSubtypeHtml );
2085 if ( node && node->parentNode() &&
2086 node->parentNode()->hasType( DwMime::kTypeMultipart ) &&
2087 node->parentNode()->hasSubType( DwMime::kSubtypeAlternative ) ) {
2089 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/html found" << endl;
2090 firstAttachment = 2;
2091 if ( mMsg->headerField(
"X-KMail-Markup" ) ==
"true" )
2092 toggleMarkup(
true );
2094 delete root; root = 0;
2096 if ( firstAttachment == 0 ) {
2097 mMsg->bodyPart(0, &bodyPart);
2098 if ( bodyPart.typeStr().lower() ==
"text" ) {
2100 kdDebug(5006) <<
"KMComposeWin::setMsg() : text/* found" << endl;
2101 firstAttachment = 1;
2105 if ( firstAttachment != 0 )
2107 mCharset = bodyPart.charset();
2108 if ( mCharset.isEmpty() || mCharset ==
"default" )
2109 mCharset = mDefCharset;
2111 TQCString bodyDecoded = bodyPart.bodyDecoded();
2113 if( allowDecryption )
2114 decryptOrStripOffCleartextSignature( bodyDecoded );
2122 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2124 mEditor->setText(codec->toUnicode(bodyDecoded));
2126 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2128 }
else mEditor->setText(
"");
2129 for(
int i = firstAttachment; i < num; ++i )
2131 KMMessagePart *msgPart =
new KMMessagePart;
2132 mMsg->bodyPart(i, msgPart);
2133 TQCString mimeType = msgPart->typeStr().lower() +
'/'
2134 + msgPart->subtypeStr().lower();
2137 if( mimeType !=
"application/pgp-signature" ) {
2142 mCharset=mMsg->charset();
2143 if ( mCharset.isEmpty() || mCharset ==
"default" )
2144 mCharset = mDefCharset;
2146 TQCString bodyDecoded = mMsg->bodyDecoded();
2148 if( allowDecryption )
2149 decryptOrStripOffCleartextSignature( bodyDecoded );
2151 const TQTextCodec *codec = KMMsgBase::codecForName(mCharset);
2153 mEditor->setText(codec->toUnicode(bodyDecoded));
2155 mEditor->setText(TQString::fromLocal8Bit(bodyDecoded));
2158 setCharset(mCharset);
2161 if( (GlobalSettings::self()->autoTextSignature()==
"auto") && mayAutoSign ) {
2169 if ( GlobalSettings::self()->prependSignature() ) {
2170 TQTimer::singleShot( 0,
this, TQ_SLOT(slotPrependSignature()) );
2172 TQTimer::singleShot( 0,
this, TQ_SLOT(slotAppendSignature()) );
2176 if ( mMsg->getCursorPos() > 0 ) {
2179 mPreserveUserCursorPosition =
true;
2181 setModified( isModified );
2184 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
2187 mPreventFccOverwrite = ( !newMsg->
fcc().isEmpty() && ident.fcc() != newMsg->
fcc() );
2192 void KMComposeWin::setFcc(
const TQString &idString )
2195 if ( ! idString.isEmpty() && kmkernel->findFolderById( idString ) ) {
2196 mFcc->setFolder( idString );
2198 mFcc->setFolder( kmkernel->sentFolder() );
2204 bool KMComposeWin::isModified()
const
2206 return ( mEditor->isModified() ||
2207 mEdtFrom->edited() ||
2208 ( mEdtReplyTo && mEdtReplyTo->edited() ) ||
2209 ( mEdtTo && mEdtTo->edited() ) ||
2210 ( mEdtCc && mEdtCc->edited() ) ||
2211 ( mEdtBcc && mEdtBcc->edited() ) ||
2212 ( mRecipientsEditor && mRecipientsEditor->isModified() ) ||
2213 mEdtSubject->edited() ||
2215 ( mTransport->lineEdit() && mTransport->lineEdit()->edited() ) );
2220 void KMComposeWin::setModified(
bool modified )
2222 mEditor->setModified( modified );
2224 mEdtFrom->setEdited(
false );
2225 if ( mEdtReplyTo ) mEdtReplyTo->setEdited(
false );
2226 if ( mEdtTo ) mEdtTo->setEdited(
false );
2227 if ( mEdtCc ) mEdtCc->setEdited(
false );
2228 if ( mEdtBcc ) mEdtBcc->setEdited(
false );
2229 if ( mRecipientsEditor ) mRecipientsEditor->clearModified();
2230 mEdtSubject->setEdited(
false );
2231 mAtmModified = false ;
2232 if ( mTransport->lineEdit() )
2233 mTransport->lineEdit()->setEdited(
false );
2239 bool KMComposeWin::queryClose ()
2241 if ( !mEditor->checkExternalEditorFinished() )
2243 if ( kmkernel->shuttingDown() || kapp->sessionSaving() )
2245 if ( mComposer && mComposer->isPerformingSignOperation() )
2248 if ( isModified() ) {
2249 bool istemplate = ( mFolder!=0 && mFolder->isTemplates() );
2250 const TQString savebut = ( istemplate ?
2251 i18n(
"Re&save as Template") :
2252 i18n(
"&Save as Draft") );
2253 const TQString savetext = ( istemplate ?
2254 i18n(
"Resave this message in the Templates folder. "
2255 "It can then be used at a later time.") :
2256 i18n(
"Save this message in the Drafts folder. "
2257 "It can then be edited and sent at a later time.") );
2259 const int rc = KMessageBox::warningYesNoCancel(
this,
2260 i18n(
"Do you want to save the message for later or discard it?"),
2261 i18n(
"Close Composer"),
2262 KGuiItem(savebut,
"document-save", TQString(), savetext),
2263 KStdGuiItem::discard() );
2264 if ( rc == KMessageBox::Cancel )
2266 else if ( rc == KMessageBox::Yes ) {
2281 bool KMComposeWin::userForgotAttachment()
2283 bool checkForForgottenAttachments =
2284 mCheckForForgottenAttachments && GlobalSettings::self()->showForgottenAttachmentWarning();
2286 if ( !checkForForgottenAttachments || ( mAtmList.count() > 0 ) )
2290 TQStringList attachWordsList = GlobalSettings::self()->attachmentKeywords();
2292 if ( attachWordsList.isEmpty() ) {
2294 attachWordsList << TQString::fromLatin1(
"attachment")
2295 << TQString::fromLatin1(
"attached");
2296 if ( TQString::fromLatin1(
"attachment") != i18n(
"attachment") )
2297 attachWordsList << i18n(
"attachment");
2298 if ( TQString::fromLatin1(
"attached") != i18n(
"attached") )
2299 attachWordsList << i18n(
"attached");
2302 TQRegExp rx ( TQString::fromLatin1(
"\\b") +
2303 attachWordsList.join(
"\\b|\\b") +
2304 TQString::fromLatin1(
"\\b") );
2305 rx.setCaseSensitive(
false );
2307 bool gotMatch =
false;
2311 TQString subj = subject();
2312 gotMatch = ( KMMessage::stripOffPrefixes( subj ) == subj )
2313 && ( rx.search( subj ) >= 0 );
2318 TQRegExp quotationRx (
"^([ \\t]*([|>:}#]|[A-Za-z]+>))+");
2319 for (
int i = 0; i < mEditor->numLines(); ++i ) {
2320 TQString line = mEditor->textLine( i );
2321 gotMatch = ( quotationRx.search( line ) < 0 )
2322 && ( rx.search( line ) >= 0 );
2331 int rc = KMessageBox::warningYesNoCancel(
this,
2332 i18n(
"The message you have composed seems to refer to an "
2333 "attached file but you have not attached anything.\n"
2334 "Do you want to attach a file to your message?"),
2335 i18n(
"File Attachment Reminder"),
2336 i18n(
"&Attach File..."),
2337 i18n(
"&Send as Is") );
2338 if ( rc == KMessageBox::Cancel )
2340 if ( rc == KMessageBox::Yes ) {
2349 void KMComposeWin::applyChanges(
bool dontSignNorEncrypt,
bool dontDisable )
2351 kdDebug(5006) <<
"entering KMComposeWin::applyChanges" << endl;
2353 if(!mMsg || mComposer) {
2354 kdDebug(5006) <<
"KMComposeWin::applyChanges() : mMsg == 0!\n" << endl;
2355 emit applyChangesDone(
false );
2360 mComposer =
new MessageComposer(
this );
2361 connect( mComposer, TQ_SIGNAL( done(
bool ) ),
2362 this, TQ_SLOT( slotComposerDone(
bool ) ) );
2367 if ( !dontDisable ) setEnabled(
false );
2369 mComposer->setDisableBreaking( mDisableBreaking );
2370 mComposer->applyChanges( dontSignNorEncrypt );
2373 void KMComposeWin::slotComposerDone(
bool rc )
2375 deleteAll( mComposedMessages );
2376 mComposedMessages = mComposer->composedMessageList();
2377 emit applyChangesDone( rc );
2385 const KPIM::Identity & KMComposeWin::identity()
const {
2386 return kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
2389 uint KMComposeWin::identityUid()
const {
2390 return mIdentity->currentIdentity();
2393 Kleo::CryptoMessageFormat KMComposeWin::cryptoMessageFormat()
const {
2394 if ( !mCryptoModuleAction )
2395 return Kleo::AutoFormat;
2396 return cb2format( mCryptoModuleAction->currentItem() );
2399 bool KMComposeWin::encryptToSelf()
const {
2401 TDEConfigGroup group( KMKernel::config(),
"Composer" );
2402 return group.readBoolEntry(
"crypto-encrypt-to-self",
true );
2405 bool KMComposeWin::queryExit ()
2411 bool KMComposeWin::addAttach(
const KURL aUrl)
2413 if ( !aUrl.isValid() ) {
2414 KMessageBox::sorry(
this, i18n(
"<qt><p>KMail could not recognize the location of the attachment (%1);</p>"
2415 "<p>you have to specify the full path if you wish to attach a file.</p></qt>" )
2416 .arg( aUrl.prettyURL() ) );
2420 const int maxAttachmentSize = GlobalSettings::maximumAttachmentSize();
2421 const uint maximumAttachmentSizeInByte = maxAttachmentSize*1024*1024;
2422 if ( aUrl.isLocalFile() && TQFileInfo( aUrl.pathOrURL() ).size() > maximumAttachmentSizeInByte ) {
2423 KMessageBox::sorry(
this, i18n(
"<qt><p>Your administrator has disallowed attaching files bigger than %1 MB.</p>" ).arg( maxAttachmentSize ) );
2427 TDEIO::TransferJob *job = TDEIO::get(aUrl);
2428 TDEIO::Scheduler::scheduleJob( job );
2431 ld.data = TQByteArray();
2433 if( !aUrl.fileEncoding().isEmpty() )
2434 ld.encoding = aUrl.fileEncoding().latin1();
2436 mMapAtmLoadData.insert(job, ld);
2437 mAttachJobs[job] = aUrl;
2438 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
2439 this, TQ_SLOT(slotAttachFileResult(TDEIO::Job *)));
2440 connect(job, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
2441 this, TQ_SLOT(slotAttachFileData(TDEIO::Job *,
const TQByteArray &)));
2447 void KMComposeWin::addAttach(
const KMMessagePart* msgPart)
2449 mAtmList.append(msgPart);
2452 if (mAtmList.count()==1)
2454 mAtmListView->resize(mAtmListView->width(), 50);
2455 mAtmListView->show();
2460 KMAtmListViewItem *lvi =
new KMAtmListViewItem( mAtmListView );
2461 msgPartToItem(msgPart, lvi);
2462 mAtmItemList.append(lvi);
2465 if ( mTempDir != 0 ) {
2470 connect( lvi, TQ_SIGNAL( compress(
int ) ),
2471 this, TQ_SLOT( compressAttach(
int ) ) );
2472 connect( lvi, TQ_SIGNAL( uncompress(
int ) ),
2473 this, TQ_SLOT( uncompressAttach(
int ) ) );
2475 slotUpdateAttachActions();
2480 void KMComposeWin::slotUpdateAttachActions()
2482 int selectedCount = 0;
2483 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it ) {
2484 if ( (*it)->isSelected() ) {
2489 mAttachRemoveAction->setEnabled( selectedCount >= 1 );
2490 mAttachSaveAction->setEnabled( selectedCount == 1 );
2491 mAttachPropertiesAction->setEnabled( selectedCount == 1 );
2497 TQString KMComposeWin::prettyMimeType(
const TQString& type )
2499 TQString t = type.lower();
2500 KServiceType::Ptr st = KServiceType::serviceType( t );
2501 return st ? st->comment() : t;
2504 void KMComposeWin::msgPartToItem(
const KMMessagePart* msgPart,
2505 KMAtmListViewItem *lvi,
bool loadDefaults)
2507 assert(msgPart != 0);
2509 if (!msgPart->fileName().isEmpty())
2510 lvi->setText(0, msgPart->fileName());
2512 lvi->setText(0, msgPart->name());
2513 lvi->setText(1, TDEIO::convertSize( msgPart->decodedSize()));
2514 lvi->setText(2, msgPart->contentTransferEncodingStr());
2515 lvi->setText(3, prettyMimeType(msgPart->typeStr() +
"/" + msgPart->subtypeStr()));
2516 lvi->setAttachmentSize(msgPart->decodedSize());
2518 if ( loadDefaults ) {
2519 if( canSignEncryptAttachments() ) {
2520 lvi->enableCryptoCBs(
true );
2521 lvi->setEncrypt( mEncryptAction->isChecked() );
2522 lvi->setSign( mSignAction->isChecked() );
2524 lvi->enableCryptoCBs(
false );
2531 void KMComposeWin::removeAttach(
const TQString &aUrl)
2534 KMMessagePart* msgPart;
2535 for(idx=0,msgPart=mAtmList.first(); msgPart;
2536 msgPart=mAtmList.next(),idx++) {
2537 if (msgPart->name() == aUrl) {
2546 void KMComposeWin::removeAttach(
int idx)
2548 mAtmModified =
true;
2550 KMAtmListViewItem *item =
static_cast<KMAtmListViewItem*
>( mAtmItemList.at( idx ) );
2551 if ( item->itemBelow() )
2552 mAtmSelectNew = item->itemBelow();
2553 else if ( item->itemAbove() )
2554 mAtmSelectNew = item->itemAbove();
2556 mAtmList.remove(idx);
2557 delete mAtmItemList.take(idx);
2559 if( mAtmList.isEmpty() )
2561 mAtmListView->hide();
2562 mAtmListView->setMinimumSize(0, 0);
2569 bool KMComposeWin::encryptFlagOfAttachment(
int idx)
2571 return (
int)(mAtmItemList.count()) > idx
2572 ?
static_cast<KMAtmListViewItem*
>( mAtmItemList.at( idx ) )->isEncrypt()
2578 bool KMComposeWin::signFlagOfAttachment(
int idx)
2580 return (
int)(mAtmItemList.count()) > idx
2581 ? ((KMAtmListViewItem*)(mAtmItemList.at( idx )))->isSign()
2587 void KMComposeWin::addrBookSelInto()
2589 if ( mClassicalRecipients ) {
2590 if ( GlobalSettings::self()->addresseeSelectorType() ==
2591 GlobalSettings::EnumAddresseeSelectorType::New ) {
2592 addrBookSelIntoNew();
2594 addrBookSelIntoOld();
2597 kdWarning() <<
"To be implemented: call recipients picker." << endl;
2601 void KMComposeWin::addrBookSelIntoOld()
2603 AddressesDialog dlg(
this );
2608 if ( !txt.isEmpty() ) {
2609 lst = KPIM::splitEmailAddrList( txt );
2610 dlg.setSelectedTo( lst );
2613 txt = mEdtCc->text();
2614 if ( !txt.isEmpty() ) {
2615 lst = KPIM::splitEmailAddrList( txt );
2616 dlg.setSelectedCC( lst );
2619 txt = mEdtBcc->text();
2620 if ( !txt.isEmpty() ) {
2621 lst = KPIM::splitEmailAddrList( txt );
2622 dlg.setSelectedBCC( lst );
2625 dlg.setRecentAddresses( RecentAddresses::self( KMKernel::config() )->tdeabcAddresses() );
2627 if (dlg.exec()==TQDialog::Rejected)
return;
2629 mEdtTo->setText( dlg.to().join(
", ") );
2630 mEdtTo->setEdited(
true );
2632 mEdtCc->setText( dlg.cc().join(
", ") );
2633 mEdtCc->setEdited(
true );
2635 mEdtBcc->setText( dlg.bcc().join(
", ") );
2636 mEdtBcc->setEdited(
true );
2639 if ( !mEdtBcc->text().isEmpty() ) {
2640 mShowHeaders |= HDR_BCC;
2641 rethinkFields(
false );
2645 void KMComposeWin::addrBookSelIntoNew()
2647 AddresseeEmailSelection selection;
2649 AddresseeSelectorDialog dlg( &selection );
2655 if ( !txt.isEmpty() ) {
2656 lst = KPIM::splitEmailAddrList( txt );
2657 selection.setSelectedTo( lst );
2660 txt = mEdtCc->text();
2661 if ( !txt.isEmpty() ) {
2662 lst = KPIM::splitEmailAddrList( txt );
2663 selection.setSelectedCC( lst );
2666 txt = mEdtBcc->text();
2667 if ( !txt.isEmpty() ) {
2668 lst = KPIM::splitEmailAddrList( txt );
2669 selection.setSelectedBCC( lst );
2672 if (dlg.exec()==TQDialog::Rejected)
return;
2674 TQStringList list = selection.to() + selection.toDistributionLists();
2675 mEdtTo->setText( list.join(
", ") );
2676 mEdtTo->setEdited(
true );
2678 list = selection.cc() + selection.ccDistributionLists();
2679 mEdtCc->setText( list.join(
", ") );
2680 mEdtCc->setEdited(
true );
2682 list = selection.bcc() + selection.bccDistributionLists();
2683 mEdtBcc->setText( list.join(
", ") );
2684 mEdtBcc->setEdited(
true );
2687 if ( !mEdtBcc->text().isEmpty() ) {
2688 mShowHeaders |= HDR_BCC;
2689 rethinkFields(
false );
2695 void KMComposeWin::setCharset(
const TQCString& aCharset,
bool forceDefault)
2697 if ((forceDefault && GlobalSettings::self()->forceReplyCharset()) || aCharset.isEmpty())
2698 mCharset = mDefCharset;
2700 mCharset = aCharset.lower();
2702 if ( mCharset.isEmpty() || mCharset ==
"default" )
2703 mCharset = mDefCharset;
2707 mEncodingAction->setCurrentItem( 0 );
2711 TQStringList encodings = mEncodingAction->items();
2713 bool charsetFound =
false;
2714 for ( TQStringList::Iterator it = encodings.begin(); it != encodings.end();
2717 if (i > 0 && ((mCharset ==
"us-ascii" && i == 1) ||
2718 (i != 1 && TDEGlobal::charsets()->codecForName(
2719 TDEGlobal::charsets()->encodingForName(*it))
2720 == TDEGlobal::charsets()->codecForName(mCharset))))
2722 mEncodingAction->setCurrentItem( i );
2724 charsetFound =
true;
2728 if (!aCharset.isEmpty() && !charsetFound) setCharset(
"",
true);
2733 void KMComposeWin::slotAddrBook()
2735 KAddrBookExternal::openAddressBook(
this);
2740 void KMComposeWin::slotAddrBookFrom()
2747 void KMComposeWin::slotAddrBookReplyTo()
2754 void KMComposeWin::slotAddrBookTo()
2760 void KMComposeWin::slotAttachFile()
2768 KURL recentURL = KFileDialog::getStartURL( TQString(), recent );
2769 if ( !recentURL.url().isEmpty() &&
2770 !TDEIO::NetAccess::exists( recentURL,
true,
this ) ) {
2771 recentURL = KURL( TQDir::homeDirPath() );
2774 KFileDialog fdlg( recentURL.url(), TQString(),
this, 0,
true );
2775 fdlg.setOperationMode( KFileDialog::Other );
2776 fdlg.setCaption( i18n(
"Attach File" ) );
2777 fdlg.okButton()->setGuiItem( KGuiItem( i18n(
"&Attach" ),
"document-open" ) );
2778 fdlg.setMode( KFile::Files );
2780 KURL::List files = fdlg.selectedURLs();
2782 for (KURL::List::Iterator it = files.begin(); it != files.end(); ++it)
2788 void KMComposeWin::slotAttachFileData(TDEIO::Job *job,
const TQByteArray &data)
2790 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
2791 assert(it != mMapAtmLoadData.end());
2792 TQBuffer buff((*it).data);
2793 buff.open(IO_WriteOnly | IO_Append);
2794 buff.writeBlock(data.data(), data.size());
2800 void KMComposeWin::slotAttachFileResult(TDEIO::Job *job)
2802 TQMap<TDEIO::Job*, atmLoadData>::Iterator it = mMapAtmLoadData.find(job);
2803 assert(it != mMapAtmLoadData.end());
2805 TQMap<TDEIO::Job*, KURL>::iterator jit = mAttachJobs.find(job);
2806 bool attachURLfound = (jit != mAttachJobs.end());
2809 attachURL = jit.data();
2810 mAttachJobs.remove(jit);
2814 mMapAtmLoadData.remove(it);
2815 job->showErrorDialog();
2817 emit attachmentAdded(attachURL,
false);
2822 (*it).data.resize((*it).data.size() + 1);
2823 (*it).data[(*it).data.size() - 1] =
'\0';
2824 if (
const TQTextCodec * codec = TDEGlobal::charsets()->codecForName((*it).encoding) )
2825 mEditor->insert( codec->toUnicode( (*it).data ) );
2827 mEditor->insert( TQString::fromLocal8Bit( (*it).data ) );
2828 mMapAtmLoadData.remove(it);
2830 emit attachmentAdded(attachURL,
true);
2833 TQCString partCharset;
2834 if ( !( *it ).url.fileEncoding().isEmpty() ) {
2835 partCharset = TQCString( ( *it ).url.fileEncoding().latin1() );
2838 TDELocale *loc = TDEGlobal::locale();
2839 ed.setAutoDetectLanguage( EncodingDetector::scriptForLanguageCode ( loc->language() ) );
2842 if ( partCharset.isEmpty() )
2843 partCharset = mCharset;
2846 KMMessagePart* msgPart;
2849 TQString name( (*it).url.fileName() );
2851 TQString mimeType =
static_cast<TDEIO::MimetypeJob*
>(job)->mimetype();
2853 if ( name.isEmpty() ) {
2856 if( mimeType ==
"text/html" )
2857 name =
"index.html";
2860 TQStringList patterns( KMimeType::mimeType( mimeType )->patterns() );
2862 if( !patterns.isEmpty() ) {
2864 int i = ext.findRev(
'.' );
2870 name = TQString(
"unknown") += ext;
2874 name.truncate( 256 );
2876 TQCString encoding = KMMsgBase::autoDetectCharset(partCharset,
2878 if ( encoding.isEmpty() )
2882 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
2883 encName = KMMsgBase::encodeRFC2047String( name, encoding );
2885 encName = KMMsgBase::encodeRFC2231String( name, encoding );
2886 bool RFC2231encoded =
false;
2887 if ( !GlobalSettings::self()->outlookCompatibleAttachments() )
2888 RFC2231encoded = name != TQString( encName );
2891 msgPart =
new KMMessagePart;
2892 msgPart->setName(name);
2893 TQValueList<int> allowedCTEs;
2894 if ( mimeType ==
"message/rfc822" ) {
2895 msgPart->setMessageBody( (*it).data );
2896 allowedCTEs << DwMime::kCte7bit;
2897 allowedCTEs << DwMime::kCte8bit;
2899 msgPart->setBodyAndGuessCte((*it).data, allowedCTEs,
2900 !kmkernel->msgSender()->sendQuotedPrintable());
2901 kdDebug(5006) <<
"autodetected cte: " << msgPart->cteStr() << endl;
2903 int slash = mimeType.find(
'/' );
2905 slash = mimeType.length();
2906 msgPart->setTypeStr( mimeType.left( slash ).latin1() );
2907 msgPart->setSubtypeStr( mimeType.mid( slash + 1 ).latin1() );
2908 msgPart->setContentDisposition(TQCString(
"attachment;\n\tfilename")
2909 + ( RFC2231encoded ?
"*=" + encName :
"=\"" + encName +
'"' ) );
2911 mMapAtmLoadData.remove(it);
2913 if ( msgPart->typeStr().lower() ==
"text" ) {
2914 msgPart->setCharset(partCharset);
2918 TDEConfigGroup composer(KMKernel::config(),
"Composer");
2919 if ( GlobalSettings::self()->showMessagePartDialogOnAttach() ) {
2923 for ( TQValueListConstIterator<int> it = allowedCTEs.begin() ;
2924 it != allowedCTEs.end() ; ++it )
2926 case DwMime::kCteBase64: encodings |= KMMsgPartDialog::Base64;
break;
2927 case DwMime::kCteQp: encodings |= KMMsgPartDialog::QuotedPrintable;
break;
2928 case DwMime::kCte7bit: encodings |= KMMsgPartDialog::SevenBit;
break;
2929 case DwMime::kCte8bit: encodings |= KMMsgPartDialog::EightBit;
break;
2932 dlg.setShownEncodings( encodings );
2933 dlg.setMsgPart(msgPart);
2938 emit attachmentAdded(attachURL,
false);
2942 mAtmModified =
true;
2948 emit attachmentAdded(attachURL,
true);
2953 void KMComposeWin::slotInsertFile()
2955 KFileDialog fdlg(TQString(), TQString(),
this, 0,
true);
2956 fdlg.setOperationMode( KFileDialog::Opening );
2957 fdlg.okButton()->setText(i18n(
"&Insert"));
2958 fdlg.setCaption(i18n(
"Insert File"));
2959 fdlg.toolBar()->insertCombo(KMMsgBase::supportedEncodings(
false), 4711,
2961 KComboBox *combo = fdlg.toolBar()->getCombo(4711);
2962 for (
int i = 0; i < combo->count(); i++)
2963 if (TDEGlobal::charsets()->codecForName(TDEGlobal::charsets()->
2964 encodingForName(combo->text(i)))
2965 == TQTextCodec::codecForLocale()) combo->setCurrentItem(i);
2966 if (!fdlg.exec())
return;
2968 KURL u = fdlg.selectedURL();
2969 mRecentAction->addURL(u);
2972 TDEConfig *config = KMKernel::config();
2973 TDEConfigGroupSaver saver( config,
"Composer" );
2974 TQString encoding = TDEGlobal::charsets()->encodingForName(combo->currentText()).latin1();
2975 TQStringList urls = config->readListEntry(
"recent-urls" );
2976 TQStringList encodings = config->readListEntry(
"recent-encodings" );
2979 uint mMaxRecentFiles = 30;
2980 while (urls.count() > mMaxRecentFiles)
2981 urls.erase( urls.fromLast() );
2982 while (encodings.count() > mMaxRecentFiles)
2983 encodings.erase( encodings.fromLast() );
2985 if (urls.count() != encodings.count()) {
2989 urls.prepend( u.prettyURL() );
2990 encodings.prepend( encoding );
2991 config->writeEntry(
"recent-urls", urls );
2992 config->writeEntry(
"recent-encodings", encodings );
2993 mRecentAction->saveEntries( config );
2995 slotInsertRecentFile(u);
3000 void KMComposeWin::slotInsertRecentFile(
const KURL& u)
3002 if (u.fileName().isEmpty())
return;
3004 TDEIO::Job *job = TDEIO::get(u);
3007 ld.data = TQByteArray();
3011 TDEConfig *config = KMKernel::config();
3012 TDEConfigGroupSaver saver( config,
"Composer" );
3013 TQStringList urls = config->readListEntry(
"recent-urls" );
3014 TQStringList encodings = config->readListEntry(
"recent-encodings" );
3015 int index = urls.findIndex( u.prettyURL() );
3017 TQString encoding = encodings[ index ];
3018 ld.encoding = encoding.latin1();
3021 mMapAtmLoadData.insert(job, ld);
3022 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
3023 this, TQ_SLOT(slotAttachFileResult(TDEIO::Job *)));
3024 connect(job, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
3025 this, TQ_SLOT(slotAttachFileData(TDEIO::Job *,
const TQByteArray &)));
3030 void KMComposeWin::slotSetCharset()
3032 if (mEncodingAction->currentItem() == 0)
3034 mAutoCharset =
true;
3037 mAutoCharset =
false;
3039 mCharset = TDEGlobal::charsets()->encodingForName( mEncodingAction->
3040 currentText() ).latin1();
3045 void KMComposeWin::slotSelectCryptoModule(
bool init )
3048 setModified(
true );
3050 if( canSignEncryptAttachments() ) {
3052 if( 0 == mAtmListView->columnWidth( mAtmColEncrypt ) ) {
3055 if( !mAtmList.isEmpty() ) {
3056 for( KMAtmListViewItem* lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.first() );
3058 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3059 lvi->setSign( mSignAction->isChecked() );
3060 lvi->setEncrypt( mEncryptAction->isChecked() );
3065 for(
int col=0; col < mAtmColEncrypt; col++ )
3066 totalWidth += mAtmListView->columnWidth( col );
3067 int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
3072 for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
3073 int newWidth = mAtmListView->columnWidth( col ) * reducedTotalWidth
3075 mAtmListView->setColumnWidth( col, newWidth );
3076 usedWidth += newWidth;
3081 mAtmListView->setColumnWidth( mAtmColEncrypt-1,
3082 reducedTotalWidth - usedWidth );
3083 mAtmListView->setColumnWidth( mAtmColEncrypt, mAtmEncryptColWidth );
3084 mAtmListView->setColumnWidth( mAtmColSign, mAtmSignColWidth );
3085 for( KMAtmListViewItem* lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.first() );
3087 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3088 lvi->enableCryptoCBs(
true );
3093 if( 0 != mAtmListView->columnWidth( mAtmColEncrypt ) ) {
3094 mAtmEncryptColWidth = mAtmListView->columnWidth( mAtmColEncrypt );
3095 mAtmSignColWidth = mAtmListView->columnWidth( mAtmColSign );
3098 for(
int col=0; col < mAtmListView->columns(); col++ )
3099 totalWidth += mAtmListView->columnWidth( col );
3100 int reducedTotalWidth = totalWidth - mAtmEncryptColWidth
3105 for(
int col=0; col < mAtmColEncrypt-1; col++ ) {
3106 int newWidth = mAtmListView->columnWidth( col ) * totalWidth
3107 / reducedTotalWidth;
3108 mAtmListView->setColumnWidth( col, newWidth );
3109 usedWidth += newWidth;
3114 mAtmListView->setColumnWidth( mAtmColEncrypt-1, totalWidth - usedWidth );
3115 mAtmListView->setColumnWidth( mAtmColEncrypt, 0 );
3116 mAtmListView->setColumnWidth( mAtmColSign, 0 );
3117 for( KMAtmListViewItem* lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.first() );
3119 lvi =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) ) {
3120 lvi->enableCryptoCBs(
false );
3126 static void showExportError( TQWidget * w,
const GpgME::Error & err ) {
3128 const TQString msg = i18n(
"<qt><p>An error occurred while trying to export "
3129 "the key from the backend:</p>"
3130 "<p><b>%1</b></p></qt>")
3131 .arg( TQString::fromLocal8Bit( err.asString() ) );
3132 KMessageBox::error( w, msg, i18n(
"Key Export Failed") );
3137 void KMComposeWin::slotInsertMyPublicKey()
3141 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() ).pgpEncryptionKey();
3142 if ( !mFingerprint.isEmpty() )
3143 startPublicKeyExport();
3146 void KMComposeWin::startPublicKeyExport() {
3147 if ( mFingerprint.isEmpty() || !Kleo::CryptoBackendFactory::instance()->openpgp() )
3149 Kleo::ExportJob * job = Kleo::CryptoBackendFactory::instance()->openpgp()->publicKeyExportJob(
true );
3152 connect( job, TQ_SIGNAL(result(
const GpgME::Error&,
const TQByteArray&)),
3153 this, TQ_SLOT(slotPublicKeyExportResult(
const GpgME::Error&,
const TQByteArray&)) );
3155 const GpgME::Error err = job->start( mFingerprint );
3157 showExportError(
this, err );
3159 (
void)
new Kleo::ProgressDialog( job, i18n(
"Exporting key..."),
this );
3162 void KMComposeWin::slotPublicKeyExportResult(
const GpgME::Error & err,
const TQByteArray & keydata ) {
3164 showExportError(
this, err );
3169 KMMessagePart * msgPart =
new KMMessagePart();
3170 msgPart->setName( i18n(
"OpenPGP key 0x%1").arg( mFingerprint ) );
3171 msgPart->setTypeStr(
"application");
3172 msgPart->setSubtypeStr(
"pgp-keys");
3173 TQValueList<int> dummy;
3174 msgPart->setBodyAndGuessCte(keydata, dummy,
false);
3175 msgPart->setContentDisposition(
"attachment;\n\tfilename=0x" + TQCString( mFingerprint.latin1() ) +
".asc" );
3183 void KMComposeWin::slotInsertPublicKey()
3185 Kleo::KeySelectionDialog dlg( i18n(
"Attach Public OpenPGP Key"),
3186 i18n(
"Select the public key which should "
3188 std::vector<GpgME::Key>(),
3189 Kleo::KeySelectionDialog::PublicKeys|Kleo::KeySelectionDialog::OpenPGPKeys,
3192 this,
"attach public key selection dialog" );
3193 if ( dlg.exec() != TQDialog::Accepted )
3196 mFingerprint = dlg.fingerprint();
3197 startPublicKeyExport();
3202 void KMComposeWin::slotAttachPopupMenu(TQListViewItem *,
const TQPoint &,
int)
3206 mAttachMenu =
new TQPopupMenu(
this);
3208 mOpenId = mAttachMenu->insertItem(i18n(
"to open",
"Open"),
this,
3209 TQ_SLOT(slotAttachOpen()));
3210 mOpenWithId = mAttachMenu->insertItem(i18n(
"Open With..."),
this,
3211 TQ_SLOT(slotAttachOpenWith()));
3212 mViewId = mAttachMenu->insertItem(i18n(
"to view",
"View"),
this,
3213 TQ_SLOT(slotAttachView()));
3214 mEditId = mAttachMenu->insertItem( i18n(
"Edit"),
this, TQ_SLOT(slotAttachEdit()) );
3215 mEditWithId = mAttachMenu->insertItem( i18n(
"Edit With..."),
this,
3216 TQ_SLOT(slotAttachEditWith()) );
3217 mRemoveId = mAttachMenu->insertItem(i18n(
"Remove"),
this, TQ_SLOT(slotAttachRemove()));
3218 mSaveAsId = mAttachMenu->insertItem( SmallIconSet(
"document-save-as"), i18n(
"Save As..."),
this,
3219 TQ_SLOT( slotAttachSave() ) );
3220 mPropertiesId = mAttachMenu->insertItem( i18n(
"Properties"),
this,
3221 TQ_SLOT( slotAttachProperties() ) );
3222 mAttachMenu->insertSeparator();
3223 mAttachMenu->insertItem(i18n(
"Add Attachment..."),
this, TQ_SLOT(slotAttachFile()));
3226 int selectedCount = 0;
3227 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it ) {
3228 if ( (*it)->isSelected() ) {
3233 mAttachMenu->setItemEnabled( mOpenId, selectedCount > 0 );
3234 mAttachMenu->setItemEnabled( mOpenWithId, selectedCount > 0 );
3235 mAttachMenu->setItemEnabled( mViewId, selectedCount > 0 );
3236 mAttachMenu->setItemEnabled( mEditId, selectedCount == 1 );
3237 mAttachMenu->setItemEnabled( mEditWithId, selectedCount == 1 );
3238 mAttachMenu->setItemEnabled( mRemoveId, selectedCount > 0 );
3239 mAttachMenu->setItemEnabled( mSaveAsId, selectedCount == 1 );
3240 mAttachMenu->setItemEnabled( mPropertiesId, selectedCount == 1 );
3242 mAttachMenu->popup(TQCursor::pos());
3246 int KMComposeWin::currentAttachmentNum()
3249 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i )
3250 if ( *it == mAtmListView->currentItem() )
3256 void KMComposeWin::slotAttachProperties()
3258 int idx = currentAttachmentNum();
3260 if (idx < 0)
return;
3262 KMMessagePart* msgPart = mAtmList.at(idx);
3265 dlg.setMsgPart(msgPart);
3266 KMAtmListViewItem* listItem = (KMAtmListViewItem*)(mAtmItemList.at(idx));
3267 if( canSignEncryptAttachments() && listItem ) {
3268 dlg.setCanSign(
true );
3269 dlg.setCanEncrypt(
true );
3270 dlg.setSigned( listItem->isSign() );
3271 dlg.setEncrypted( listItem->isEncrypt() );
3273 dlg.setCanSign(
false );
3274 dlg.setCanEncrypt(
false );
3278 mAtmModified =
true;
3281 msgPartToItem(msgPart, listItem);
3282 if( canSignEncryptAttachments() ) {
3283 listItem->setSign( dlg.isSigned() );
3284 listItem->setEncrypt( dlg.isEncrypted() );
3291 void KMComposeWin::compressAttach(
int idx )
3293 if (idx < 0)
return;
3296 for ( i = 0; i < mAtmItemList.count(); ++i )
3297 if ( mAtmItemList.at( i )->itemPos() == idx )
3300 if ( i > mAtmItemList.count() )
3303 KMMessagePart* msgPart;
3304 msgPart = mAtmList.at( i );
3306 TQBuffer dev( array );
3308 TQByteArray decoded = msgPart->bodyDecodedBinary();
3309 if ( ! zip.open( IO_WriteOnly ) ) {
3310 KMessageBox::sorry(0, i18n(
"KMail could not compress the file.") );
3311 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3315 zip.setCompression( KZip::DeflateCompression );
3316 if ( ! zip.writeFile( msgPart->name(),
"",
"", decoded.size(),
3317 decoded.data() ) ) {
3318 KMessageBox::sorry(0, i18n(
"KMail could not compress the file.") );
3319 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3323 if ( array.size() >= decoded.size() ) {
3324 if ( KMessageBox::questionYesNo(
this, i18n(
"The compressed file is larger "
3325 "than the original. Do you want to keep the original one?" ), TQString(), i18n(
"Keep"), i18n(
"Compress") )
3326 == KMessageBox::Yes ) {
3327 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setCompress(
false );
3331 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setUncompressedCodec(
3332 msgPart->cteStr() );
3334 msgPart->setCteStr(
"base64" );
3335 msgPart->setBodyEncodedBinary( array );
3336 TQString name = msgPart->name() +
".zip";
3338 msgPart->setName( name );
3340 TQCString cDisp =
"attachment;";
3341 TQCString encoding = KMMsgBase::autoDetectCharset( msgPart->charset(),
3343 kdDebug(5006) <<
"encoding: " << encoding << endl;
3344 if ( encoding.isEmpty() ) encoding =
"utf-8";
3345 kdDebug(5006) <<
"encoding after: " << encoding << endl;
3347 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
3348 encName = KMMsgBase::encodeRFC2047String( name, encoding );
3350 encName = KMMsgBase::encodeRFC2231String( name, encoding );
3352 cDisp +=
"\n\tfilename";
3353 if ( name != TQString( encName ) )
3354 cDisp +=
"*=" + encName;
3356 cDisp +=
"=\"" + encName +
'"';
3357 msgPart->setContentDisposition( cDisp );
3359 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->setUncompressedMimeType(
3360 msgPart->typeStr(), msgPart->subtypeStr() );
3361 msgPart->setTypeStr(
"application" );
3362 msgPart->setSubtypeStr(
"x-zip" );
3364 KMAtmListViewItem* listItem =
static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) );
3365 msgPartToItem( msgPart, listItem,
false );
3370 void KMComposeWin::uncompressAttach(
int idx )
3372 if (idx < 0)
return;
3375 for ( i = 0; i < mAtmItemList.count(); ++i )
3376 if ( mAtmItemList.at( i )->itemPos() == idx )
3379 if ( i > mAtmItemList.count() )
3382 KMMessagePart* msgPart;
3383 msgPart = mAtmList.at( i );
3385 TQBuffer dev( msgPart->bodyDecodedBinary() );
3387 TQByteArray decoded;
3389 decoded = msgPart->bodyDecodedBinary();
3390 if ( ! zip.open( IO_ReadOnly ) ) {
3391 KMessageBox::sorry(0, i18n(
"KMail could not uncompress the file.") );
3392 static_cast<KMAtmListViewItem *
>( mAtmItemList.at( i ) )->setCompress(
true );
3395 const KArchiveDirectory *dir = zip.directory();
3397 KZipFileEntry *entry;
3398 if ( dir->entries().count() != 1 ) {
3399 KMessageBox::sorry(0, i18n(
"KMail could not uncompress the file.") );
3400 static_cast<KMAtmListViewItem *
>( mAtmItemList.at( i ) )->setCompress(
true );
3403 entry = (KZipFileEntry*)dir->entry( dir->entries()[0] );
3406 static_cast<KMAtmListViewItem*
>( mAtmItemList.at(i) )->uncompressedCodec() );
3408 msgPart->setBodyEncodedBinary( entry->data() );
3409 TQString name = entry->name();
3410 msgPart->setName( name );
3414 TQCString cDisp =
"attachment;";
3415 TQCString encoding = KMMsgBase::autoDetectCharset( msgPart->charset(),
3417 if ( encoding.isEmpty() ) encoding =
"utf-8";
3420 if ( GlobalSettings::self()->outlookCompatibleAttachments() )
3421 encName = KMMsgBase::encodeRFC2047String( name, encoding );
3423 encName = KMMsgBase::encodeRFC2231String( name, encoding );
3425 cDisp +=
"\n\tfilename";
3426 if ( name != TQString( encName ) )
3427 cDisp +=
"*=" + encName;
3429 cDisp +=
"=\"" + encName +
'"';
3430 msgPart->setContentDisposition( cDisp );
3432 TQCString type, subtype;
3433 static_cast<KMAtmListViewItem*
>( mAtmItemList.at( i ) )->uncompressedMimeType( type,
3436 msgPart->setTypeStr( type );
3437 msgPart->setSubtypeStr( subtype );
3439 KMAtmListViewItem* listItem =
static_cast<KMAtmListViewItem*
>(mAtmItemList.at( i ));
3440 msgPartToItem( msgPart, listItem,
false );
3445 void KMComposeWin::slotAttachView()
3448 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3449 if ( (*it)->isSelected() ) {
3455 void KMComposeWin::slotAttachOpen()
3458 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3459 if ( (*it)->isSelected() ) {
3460 openAttach( i,
false );
3466 void KMComposeWin::slotAttachOpenWith()
3469 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3470 if ( (*it)->isSelected() ) {
3471 openAttach( i,
true );
3476 void KMComposeWin::slotAttachEdit()
3479 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3480 if ( (*it)->isSelected() ) {
3481 editAttach( i,
false );
3486 void KMComposeWin::slotAttachEditWith()
3489 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++i ) {
3490 if ( (*it)->isSelected() ) {
3491 editAttach( i,
true );
3497 bool KMComposeWin::inlineSigningEncryptionSelected() {
3498 if ( !mSignAction->isChecked() && !mEncryptAction->isChecked() )
3500 return cryptoMessageFormat() == Kleo::InlineOpenPGPFormat;
3504 void KMComposeWin::viewAttach(
int index )
3507 KMMessagePart* msgPart;
3508 msgPart = mAtmList.at(index);
3509 pname = msgPart->name().stripWhiteSpace();
3510 if (pname.isEmpty()) pname=msgPart->contentDescription();
3511 if (pname.isEmpty()) pname=
"unnamed";
3513 KTempFile* atmTempFile =
new KTempFile();
3514 mAtmTempList.append( atmTempFile );
3515 atmTempFile->setAutoDelete(
true );
3516 KPIM::kByteArrayToFile(msgPart->bodyDecodedBinary(), atmTempFile->name(),
false,
false,
3518 KMReaderMainWin *win =
new KMReaderMainWin(msgPart,
false,
3519 atmTempFile->name(), pname, mCharset );
3524 void KMComposeWin::openAttach(
int index,
bool with )
3526 KMMessagePart* msgPart = mAtmList.at(index);
3527 const TQString contentTypeStr =
3528 ( msgPart->typeStr() +
'/' + msgPart->subtypeStr() ).lower();
3530 KMimeType::Ptr mimetype;
3531 mimetype = KMimeType::mimeType( contentTypeStr );
3533 KTempFile* atmTempFile =
new KTempFile();
3534 mAtmTempList.append( atmTempFile );
3535 const bool autoDelete =
true;
3536 atmTempFile->setAutoDelete( autoDelete );
3539 url.setPath( atmTempFile->name() );
3541 KPIM::kByteArrayToFile( msgPart->bodyDecodedBinary(), atmTempFile->name(),
false,
false,
3543 if ( ::chmod( TQFile::encodeName( atmTempFile->name() ), S_IRUSR ) != 0) {
3544 TQFile::remove(url.path());
3548 KService::Ptr offer =
3549 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
3551 if ( with || !offer || mimetype->name() ==
"application/octet-stream" ) {
3552 if ( ( !KRun::displayOpenWithDialog( url, autoDelete ) ) && autoDelete ) {
3553 TQFile::remove(url.path());
3557 if ( ( !KRun::run( *offer, url, autoDelete ) ) && autoDelete ) {
3558 TQFile::remove( url.path() );
3563 void KMComposeWin::editAttach(
int index,
bool openWith)
3565 KMMessagePart* msgPart = mAtmList.at(index);
3566 const TQString contentTypeStr =
3567 ( msgPart->typeStr() +
'/' + msgPart->subtypeStr() ).lower();
3569 KTempFile* atmTempFile =
new KTempFile();
3570 mAtmTempList.append( atmTempFile );
3571 atmTempFile->setAutoDelete(
true );
3572 atmTempFile->file()->writeBlock( msgPart->bodyDecodedBinary() );
3573 atmTempFile->file()->flush();
3580 if ( watcher->start() ) {
3581 mEditorMap.insert( watcher, msgPart );
3582 mEditorTempFiles.insert( watcher, atmTempFile );
3587 void KMComposeWin::slotAttachSave()
3589 KMMessagePart* msgPart;
3590 TQString fileName, pname;
3591 int idx = currentAttachmentNum();
3593 if (idx < 0)
return;
3595 msgPart = mAtmList.at(idx);
3596 pname = msgPart->name();
3597 if (pname.isEmpty()) pname=
"unnamed";
3599 KURL url = KFileDialog::getSaveURL(pname, TQString(), 0, i18n(
"Save Attachment As"));
3604 kmkernel->byteArrayToRemoteFile(msgPart->bodyDecodedBinary(), url);
3609 void KMComposeWin::slotAttachRemove()
3612 bool attachmentRemoved =
false;
3614 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ) {
3615 if ( (*it)->isSelected() ) {
3617 attachmentRemoved =
true;
3625 if ( attachmentRemoved ) {
3626 setModified(
true );
3627 slotUpdateAttachActions();
3628 if ( mAtmSelectNew ) {
3629 mAtmListView->setSelected( mAtmSelectNew,
true );
3630 mAtmListView->setCurrentItem( mAtmSelectNew );
3636 void KMComposeWin::slotFind()
3641 void KMComposeWin::slotSearchAgain()
3643 mEditor->repeatSearch();
3647 void KMComposeWin::slotReplace()
3653 void KMComposeWin::slotUpdateFont()
3655 kdDebug() <<
"KMComposeWin::slotUpdateFont " << endl;
3656 if ( ! mFixedFontAction ) {
3659 mEditor->setFont( mFixedFontAction->isChecked() ? mFixedFont : mBodyFont );
3662 TQString KMComposeWin::quotePrefixName()
const
3667 int languageNr = GlobalSettings::self()->replyCurrentLanguage();
3668 ReplyPhrases replyPhrases( TQString::number(languageNr) );
3669 replyPhrases.readConfig();
3670 TQString quotePrefix = msg()->formatString(
3671 replyPhrases.indentPrefix() );
3673 quotePrefix = msg()->formatString(quotePrefix);
3677 void KMComposeWin::slotPasteClipboardAsQuotation()
3679 if( mEditor->hasFocus() && msg() )
3681 TQString s = TQApplication::clipboard()->text();
3683 mEditor->insert(addQuotesToText(s));
3687 void KMComposeWin::slotPasteClipboardAsAttachment()
3689 KURL url( TQApplication::clipboard()->text( TQClipboard::Clipboard ) );
3690 if ( url.isValid() ) {
3691 addAttach(TQApplication::clipboard()->text( TQClipboard::Clipboard ) );
3695 TQMimeSource *mimeSource = TQApplication::clipboard()->data();
3696 if ( TQImageDrag::canDecode(mimeSource) ) {
3697 slotAttachPNGImageData(mimeSource->encodedData(
"image/png"));
3701 TQString attName = KInputDialog::getText(
"KMail", i18n(
"Name of the attachment:"), TQString(), &ok,
this );
3704 KMMessagePart *msgPart =
new KMMessagePart;
3705 msgPart->setName(attName);
3706 TQValueList<int> dummy;
3707 msgPart->setBodyAndGuessCte(TQCString(TQApplication::clipboard()->text().latin1()), dummy,
3708 kmkernel->msgSender()->sendQuotedPrintable());
3713 void KMComposeWin::slotAddQuotes()
3715 if( mEditor->hasFocus() && msg() )
3721 if ( mEditor->hasMarkedText() ) {
3722 TQString s = mEditor->markedText();
3724 mEditor->insert(addQuotesToText(s));
3726 int l = mEditor->currentLine();
3727 int c = mEditor->currentColumn();
3728 TQString s = mEditor->textLine(l);
3729 s.prepend(quotePrefixName());
3730 mEditor->insertLine(s,l);
3731 mEditor->removeLine(l+1);
3732 mEditor->setCursorPosition(l,c+2);
3737 TQString KMComposeWin::addQuotesToText(
const TQString &inputText)
3739 TQString answer = TQString( inputText );
3740 TQString indentStr = quotePrefixName();
3741 answer.replace(
'\n',
'\n' + indentStr);
3742 answer.prepend( indentStr );
3747 TQString KMComposeWin::removeQuotesFromText(
const TQString &inputText)
3749 TQString s = inputText;
3752 TQString quotePrefix =
'^' + quotePrefixName();
3753 TQRegExp rx(quotePrefix);
3757 quotePrefix =
'\n' + quotePrefixName();
3759 s.replace(rx,
"\n");
3764 void KMComposeWin::slotRemoveQuotes()
3766 if( mEditor->hasFocus() && msg() )
3772 if ( mEditor->hasMarkedText() ) {
3773 TQString s = mEditor->markedText();
3774 mEditor->insert(removeQuotesFromText(s));
3776 int l = mEditor->currentLine();
3777 int c = mEditor->currentColumn();
3778 TQString s = mEditor->textLine(l);
3779 mEditor->insertLine(removeQuotesFromText(s),l);
3780 mEditor->removeLine(l+1);
3781 mEditor->setCursorPosition(l,c-2);
3787 void KMComposeWin::slotUndo()
3789 TQWidget* fw = focusWidget();
3792 if ( ::tqt_cast<KEdit*>(fw) )
3793 static_cast<TQTextEdit*
>(fw)->undo();
3794 else if (::tqt_cast<TQLineEdit*>(fw))
3795 static_cast<TQLineEdit*
>(fw)->undo();
3798 void KMComposeWin::slotRedo()
3800 TQWidget* fw = focusWidget();
3803 if (::tqt_cast<KEdit*>(fw))
3804 static_cast<KEdit*
>(fw)->redo();
3805 else if (::tqt_cast<TQLineEdit*>(fw))
3806 static_cast<TQLineEdit*
>(fw)->redo();
3810 void KMComposeWin::slotCut()
3812 TQWidget* fw = focusWidget();
3815 if (::tqt_cast<KEdit*>(fw))
3816 static_cast<KEdit*
>(fw)->cut();
3817 else if (::tqt_cast<TQLineEdit*>(fw))
3818 static_cast<TQLineEdit*
>(fw)->cut();
3823 void KMComposeWin::slotCopy()
3825 TQWidget* fw = focusWidget();
3832 TQKeyEvent k(TQEvent::KeyPress, Key_C, 0, ControlButton);
3833 kapp->notify(fw, &k);
3838 void KMComposeWin::slotPasteClipboard()
3840 paste( TQClipboard::Clipboard );
3843 void KMComposeWin::paste( TQClipboard::Mode mode )
3845 TQWidget* fw = focusWidget();
3848 TQMimeSource *mimeSource = TQApplication::clipboard()->data( mode );
3849 if ( mimeSource->provides(
"image/png") ) {
3850 slotAttachPNGImageData(mimeSource->encodedData(
"image/png"));
3851 }
else if ( KURLDrag::canDecode( mimeSource ) ) {
3853 if( KURLDrag::decode( mimeSource, urlList ) ) {
3854 const TQString asText = i18n(
"Add as Text");
3855 const TQString asAttachment = i18n(
"Add as Attachment");
3856 const TQString text = i18n(
"Please select whether you want to insert the content as text into the editor, "
3857 "or append the referenced file as an attachment.");
3858 const TQString caption = i18n(
"Paste as text or attachment?");
3860 int id = KMessageBox::questionYesNoCancel(
this, text, caption,
3861 KGuiItem( asText ), KGuiItem( asAttachment) );
3863 case KMessageBox::Yes:
3864 for ( KURL::List::Iterator it = urlList.begin();
3865 it != urlList.end(); ++it ) {
3866 mEditor->insert( (*it).url() );
3869 case KMessageBox::No:
3870 for ( KURL::List::Iterator it = urlList.begin();
3871 it != urlList.end(); ++it ) {
3877 }
else if ( TQTextDrag::canDecode( mimeSource ) ) {
3879 if ( TQTextDrag::decode( mimeSource, s ) )
3880 mEditor->insert( s );
3886 void KMComposeWin::slotMarkAll()
3888 TQWidget* fw = focusWidget();
3891 if (::tqt_cast<TQLineEdit*>(fw))
3892 static_cast<TQLineEdit*
>(fw)->selectAll();
3893 else if (::tqt_cast<KEdit*>(fw))
3894 static_cast<KEdit*
>(fw)->selectAll();
3899 void KMComposeWin::slotClose()
3906 void KMComposeWin::slotNewComposer()
3912 win =
new KMComposeWin(msg);
3918 void KMComposeWin::slotNewMailReader()
3920 KMMainWin *kmmwin =
new KMMainWin(0);
3927 void KMComposeWin::slotUpdWinTitle(
const TQString& text)
3933 setCaption(
"("+i18n(
"unnamed")+
")");
3934 else setCaption( s.replace( TQChar(
'\n'),
' ' ) );
3939 void KMComposeWin::slotEncryptToggled(
bool on)
3941 setEncryption( on,
true );
3942 slotUpdateSignatureAndEncrypionStateIndicators();
3947 void KMComposeWin::setEncryption(
bool encrypt,
bool setByUser )
3949 bool wasModified = isModified();
3951 setModified(
true );
3952 if ( !mEncryptAction->isEnabled() )
3956 else if ( encrypt && encryptToSelf() && !mLastIdentityHasEncryptionKey ) {
3958 KMessageBox::sorry(
this,
3959 i18n(
"<qt><p>You have requested that messages be "
3960 "encrypted to yourself, but the currently selected "
3961 "identity does not define an (OpenPGP or S/MIME) "
3962 "encryption key to use for this.</p>"
3963 "<p>Please select the key(s) to use "
3964 "in the identity configuration.</p>"
3966 i18n(
"Undefined Encryption Key") );
3967 setModified( wasModified );
3973 mEncryptAction->setChecked( encrypt );
3977 mEncryptAction->setIcon(
"encrypted");
3979 mEncryptAction->setIcon(
"decrypted");
3982 if ( canSignEncryptAttachments() ) {
3983 for ( KMAtmListViewItem* entry =
3984 static_cast<KMAtmListViewItem*
>( mAtmItemList.first() );
3986 entry =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) )
3987 entry->setEncrypt( encrypt );
3993 void KMComposeWin::slotSignToggled(
bool on)
3995 setSigning( on,
true );
3996 slotUpdateSignatureAndEncrypionStateIndicators();
4001 void KMComposeWin::setSigning(
bool sign,
bool setByUser )
4003 bool wasModified = isModified();
4005 setModified(
true );
4006 if ( !mSignAction->isEnabled() )
4010 if ( sign && !mLastIdentityHasSigningKey ) {
4012 KMessageBox::sorry(
this,
4013 i18n(
"<qt><p>In order to be able to sign "
4014 "this message you first have to "
4015 "define the (OpenPGP or S/MIME) signing key "
4017 "<p>Please select the key to use "
4018 "in the identity configuration.</p>"
4020 i18n(
"Undefined Signing Key") );
4021 setModified( wasModified );
4027 mSignAction->setChecked( sign );
4030 if ( canSignEncryptAttachments() ) {
4031 for ( KMAtmListViewItem* entry =
4032 static_cast<KMAtmListViewItem*
>( mAtmItemList.first() );
4034 entry =
static_cast<KMAtmListViewItem*
>( mAtmItemList.next() ) )
4035 entry->setSign( sign );
4041 void KMComposeWin::slotWordWrapToggled(
bool on)
4045 mEditor->setWordWrap( TQTextEdit::FixedColumnWidth );
4046 mEditor->setWrapColumnOrWidth( GlobalSettings::self()->lineWrapWidth() );
4050 mEditor->setWordWrap( TQTextEdit::WidgetWidth );
4055 void KMComposeWin::disableWordWrap()
4057 mEditor->setWordWrap( TQTextEdit::NoWrap );
4060 void KMComposeWin::disableRecipientNumberCheck()
4062 mCheckForRecipients =
false;
4065 void KMComposeWin::disableForgottenAttachmentsCheck()
4067 mCheckForForgottenAttachments =
false;
4070 void KMComposeWin::ignoreStickyFields()
4072 mIgnoreStickyFields =
true;
4073 mBtnTransport->setChecked(
false );
4074 mBtnDictionary->setChecked(
false );
4075 mBtnIdentity->setChecked(
false );
4076 mBtnTransport->setEnabled(
false );
4077 mBtnDictionary->setEnabled(
false );
4078 mBtnIdentity->setEnabled(
false );
4082 void KMComposeWin::slotPrint()
4084 mMessageWasModified = isModified();
4085 connect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
4086 this, TQ_SLOT( slotContinuePrint(
bool ) ) );
4087 applyChanges(
true );
4090 void KMComposeWin::slotContinuePrint(
bool rc )
4092 disconnect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
4093 this, TQ_SLOT( slotContinuePrint(
bool ) ) );
4096 if ( mComposedMessages.isEmpty() ) {
4097 kdDebug(5006) <<
"Composing the message failed." << endl;
4100 KMCommand *command =
new KMPrintCommand(
this, mComposedMessages.first() );
4102 setModified( mMessageWasModified );
4107 bool KMComposeWin::validateAddresses( TQWidget * parent,
const TQString & addresses )
4109 TQString brokenAddress;
4111 if ( !( errorCode == KPIM::AddressOk || errorCode == KPIM::AddressEmpty ) ) {
4112 TQString errorMsg(
"<qt><p><b>" + brokenAddress +
4113 "</b></p><p>" + KPIM::emailParseResultToString( errorCode ) +
4115 KMessageBox::sorry( parent, errorMsg, i18n(
"Invalid Email Address") );
4122 void KMComposeWin::doSend( KMail::MessageSender::SendMethod method,
4123 KMComposeWin::SaveIn saveIn )
4125 if ( method != KMail::MessageSender::SendLater && kmkernel->isOffline() ) {
4126 KMessageBox::information(
this,
4127 i18n(
"KMail is currently in offline mode,"
4128 "your messages will be kept in the outbox until you go online."),
4129 i18n(
"Online/Offline"),
"kmailIsOffline" );
4130 mSendMethod = KMail::MessageSender::SendLater;
4132 mSendMethod = method;
4136 if ( saveIn == KMComposeWin::None ) {
4137 if ( KPIM::getFirstEmailAddress( from() ).isEmpty() ) {
4138 if ( !( mShowHeaders & HDR_FROM ) ) {
4139 mShowHeaders |= HDR_FROM;
4140 rethinkFields(
false );
4142 mEdtFrom->setFocus();
4143 KMessageBox::sorry(
this,
4144 i18n(
"You must enter your email address in the "
4145 "From: field. You should also set your email "
4146 "address for all identities, so that you do "
4147 "not have to enter it for each message.") );
4150 if ( to().isEmpty() )
4152 if ( cc().isEmpty() && bcc().isEmpty()) {
4153 if ( mEdtTo ) mEdtTo->setFocus();
4154 KMessageBox::information(
this,
4155 i18n(
"You must specify at least one receiver,"
4156 "either in the To: field or as CC or as BCC.") );
4160 if ( mEdtTo ) mEdtTo->setFocus();
4162 KMessageBox::questionYesNo(
this,
4163 i18n(
"To field is missing."
4164 "Send message anyway?"),
4165 i18n(
"No To: specified") );
4166 if ( rc == KMessageBox::No ){
4173 if ( !validateAddresses(
this, to().stripWhiteSpace() ) ) {
4177 if ( !validateAddresses(
this, cc().stripWhiteSpace() ) ) {
4181 if ( !validateAddresses(
this, bcc().stripWhiteSpace() ) ) {
4185 if (subject().isEmpty())
4187 mEdtSubject->setFocus();
4189 KMessageBox::questionYesNo(
this,
4190 i18n(
"You did not specify a subject. "
4191 "Send message anyway?"),
4192 i18n(
"No Subject Specified"),
4193 i18n(
"S&end as Is"),
4194 i18n(
"&Specify the Subject"),
4195 "no_subject_specified" );
4196 if( rc == KMessageBox::No )
4202 if ( userForgotAttachment() )
4207 mMsg->setDateToday();
4214 TQString hf = mMsg->headerField(
"X-KMail-Transport");
4215 if ((mTransport->currentText() != mTransport->text(0)) ||
4216 (!hf.isEmpty() && (hf != mTransport->text(0))))
4217 mMsg->setHeaderField(
"X-KMail-Transport", mTransport->currentText());
4219 mDisableBreaking = ( saveIn != KMComposeWin::None );
4221 const bool neverEncrypt = ( mDisableBreaking && GlobalSettings::self()->neverEncryptDrafts() )
4222 || mSigningAndEncryptionExplicitlyDisabled;
4223 connect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
4224 TQ_SLOT( slotContinueDoSend(
bool ) ) );
4226 if ( mEditor->textFormat() == TQt::RichText )
4227 mMsg->setHeaderField(
"X-KMail-Markup",
"true" );
4229 mMsg->removeHeaderField(
"X-KMail-Markup" );
4230 if ( mEditor->textFormat() == TQt::RichText && inlineSigningEncryptionSelected() ) {
4231 TQString keepBtnText = mEncryptAction->isChecked() ?
4232 mSignAction->isChecked() ? i18n(
"&Keep markup, do not sign/encrypt" )
4233 : i18n(
"&Keep markup, do not encrypt" )
4234 : i18n(
"&Keep markup, do not sign" );
4235 TQString yesBtnText = mEncryptAction->isChecked() ?
4236 mSignAction->isChecked() ? i18n(
"Sign/Encrypt (delete markup)")
4237 : i18n(
"Encrypt (delete markup)" )
4238 : i18n(
"Sign (delete markup)" );
4239 int ret = KMessageBox::warningYesNoCancel(
this,
4240 i18n(
"<qt><p>Inline signing/encrypting of HTML messages is not possible;</p>"
4241 "<p>do you want to delete your markup?</p></qt>"),
4242 i18n(
"Sign/Encrypt Message?"),
4243 KGuiItem( yesBtnText ),
4244 KGuiItem( keepBtnText ) );
4245 if ( KMessageBox::Cancel == ret )
4247 if ( KMessageBox::No == ret ) {
4248 mEncryptAction->setChecked(
false);
4249 mSignAction->setChecked(
false);
4252 toggleMarkup(
false);
4256 if (neverEncrypt && saveIn != KMComposeWin::None ) {
4259 mMsg->setHeaderField(
"X-KMail-SignatureActionEnabled", mSignAction->isChecked()?
"true":
"false" );
4260 mMsg->setHeaderField(
"X-KMail-EncryptActionEnabled", mEncryptAction->isChecked()?
"true":
"false" );
4261 mMsg->setHeaderField(
"X-KMail-CryptoMessageFormat", TQString::number( cryptoMessageFormat() ) );
4263 mMsg->removeHeaderField(
"X-KMail-SignatureActionEnabled" );
4264 mMsg->removeHeaderField(
"X-KMail-EncryptActionEnabled" );
4265 mMsg->removeHeaderField(
"X-KMail-CryptoMessageFormat" );
4269 kdDebug(5006) <<
"KMComposeWin::doSend() - calling applyChanges()"
4271 applyChanges( neverEncrypt );
4274 bool KMComposeWin::saveDraftOrTemplate(
const TQString &folderName,
4277 KMFolder *theFolder = 0, *imapTheFolder = 0;
4279 if ( !folderName.isEmpty() ) {
4280 theFolder = kmkernel->folderMgr()->findIdString( folderName );
4281 if ( theFolder == 0 )
4284 theFolder = kmkernel->dimapFolderMgr()->findIdString( folderName );
4285 if ( theFolder == 0 )
4286 imapTheFolder = kmkernel->imapFolderMgr()->findIdString( folderName );
4287 if ( !theFolder && !imapTheFolder ) {
4288 const KPIM::Identity &
id = kmkernel->identityManager()
4289 ->identityForUoidOrDefault( msg->
headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
4290 KMessageBox::information( 0,
4291 i18n(
"The custom drafts or templates folder for "
4292 "identify \"%1\" does not exist (anymore); "
4293 "therefore, the default drafts or templates "
4294 "folder will be used.")
4295 .arg(
id.identityName() ) );
4298 if ( imapTheFolder && imapTheFolder->noContent() )
4301 bool didOpen =
false;
4302 if ( theFolder == 0 ) {
4303 theFolder = ( mSaveIn==KMComposeWin::Drafts ?
4304 kmkernel->draftsFolder() : kmkernel->templatesFolder() );
4307 theFolder->
open(
"composer" );
4310 kdDebug(5006) << k_funcinfo <<
"theFolder=" << theFolder->name() << endl;
4311 if ( imapTheFolder )
4312 kdDebug(5006) << k_funcinfo <<
"imapTheFolder=" << imapTheFolder->name() << endl;
4314 bool sentOk = !( theFolder->
addMsg( msg ) );
4318 msg = theFolder->
getMsg( theFolder->
count() - 1 );
4321 if ( imapTheFolder ) {
4323 imapTheFolder->moveMsg( msg );
4324 (
static_cast<KMFolderImap*
>( imapTheFolder->storage() ))->getFolder();
4328 theFolder->
close(
"composer" );
4332 void KMComposeWin::slotContinueDoSend(
bool sentOk )
4334 kdDebug(5006) <<
"KMComposeWin::slotContinueDoSend( " << sentOk <<
" )"
4336 disconnect(
this, TQ_SIGNAL( applyChangesDone(
bool ) ),
4337 this, TQ_SLOT( slotContinueDoSend(
bool ) ) );
4340 mDisableBreaking =
false;
4344 for ( TQValueVector<KMMessage*>::iterator it = mComposedMessages.begin() ; it != mComposedMessages.end() ; ++it ) {
4347 (*it)->cleanupHeader();
4350 (*it)->setComplete(
true );
4352 if ( mSaveIn==KMComposeWin::Drafts ) {
4353 sentOk = saveDraftOrTemplate( (*it)->drafts(), (*it) );
4354 }
else if ( mSaveIn==KMComposeWin::Templates ) {
4355 sentOk = saveDraftOrTemplate( (*it)->templates(), (*it) );
4359 if( !mComposer->originalBCC().isEmpty() )
4361 TQString recips = (*it)->headerField(
"X-KMail-Recipients" );
4362 if( !recips.isEmpty() ) {
4365 (*it)->cleanupHeader();
4366 sentOk = kmkernel->msgSender()->send((*it), mSendMethod);
4375 RecentAddresses::self( KMKernel::config() )->add( bcc() );
4376 RecentAddresses::self( KMKernel::config() )->add( cc() );
4377 RecentAddresses::self( KMKernel::config() )->add( to() );
4379 setModified(
false );
4380 mAutoDeleteMsg =
false;
4387 bool KMComposeWin::checkTransport()
const
4390 KMessageBox::information( mMainWidget,
4391 i18n(
"Please create an account for sending and try again.") );
4399 void KMComposeWin::slotSendLater()
4401 if ( !checkTransport() )
4403 if ( !checkRecipientNumber() )
4405 if ( mEditor->checkExternalEditorFinished() )
4406 doSend( KMail::MessageSender::SendLater );
4411 void KMComposeWin::slotSaveDraft() {
4412 if ( mEditor->checkExternalEditorFinished() )
4413 doSend( KMail::MessageSender::SendLater, KMComposeWin::Drafts );
4417 void KMComposeWin::slotSaveTemplate() {
4418 if ( mEditor->checkExternalEditorFinished() )
4419 doSend( KMail::MessageSender::SendLater, KMComposeWin::Templates );
4423 void KMComposeWin::slotSendNowVia(
int item )
4426 TQString customTransport = availTransports[ item ];
4428 mTransport->setCurrentText( customTransport );
4433 void KMComposeWin::slotSendLaterVia(
int item )
4436 TQString customTransport = availTransports[ item ];
4438 mTransport->setCurrentText( customTransport );
4444 void KMComposeWin::slotSendNow() {
4445 if ( !mEditor->checkExternalEditorFinished() )
4447 if ( !checkTransport() )
4449 if ( !checkRecipientNumber() )
4451 if ( GlobalSettings::self()->confirmBeforeSend() )
4453 int rc = KMessageBox::warningYesNoCancel( mMainWidget,
4454 i18n(
"About to send email..."),
4455 i18n(
"Send Confirmation"),
4457 i18n(
"Send &Later") );
4459 if ( rc == KMessageBox::Yes )
4460 doSend( KMail::MessageSender::SendImmediate );
4461 else if ( rc == KMessageBox::No )
4462 doSend( KMail::MessageSender::SendLater );
4465 doSend( KMail::MessageSender::SendImmediate );
4470 bool KMComposeWin::checkRecipientNumber()
const
4472 uint thresHold = GlobalSettings::self()->recipientThreshold();
4473 if ( mCheckForRecipients &&
4474 GlobalSettings::self()->tooManyRecipients() &&
4475 mRecipientsEditor->recipients().count() > thresHold ) {
4476 if ( KMessageBox::questionYesNo( mMainWidget,
4477 i18n(
"You are trying to send the mail to more than %1 recipients. Send message anyway?").arg(thresHold),
4478 i18n(
"Too many receipients"),
4479 i18n(
"&Send as Is"),
4480 i18n(
"&Edit Recipients")) == KMessageBox::No ) {
4489 void KMComposeWin::slotAppendSignature()
4495 void KMComposeWin::slotPrependSignature()
4497 insertSignature( Prepend );
4501 void KMComposeWin::slotInsertSignatureAtCursor()
4503 insertSignature( AtCursor );
4507 void KMComposeWin::insertSignature( SignaturePlacement placement )
4509 bool mod = mEditor->isModified();
4511 const KPIM::Identity &ident =
4512 kmkernel->identityManager()->
4513 identityForUoidOrDefault( mIdentity->currentIdentity() );
4515 mOldSigText = GlobalSettings::self()->prependSignature()? ident.signature().rawText() : ident.signatureText();
4517 if( !mOldSigText.isEmpty() )
4520 int paragraph, index;
4521 mEditor->getCursorPosition( ¶graph, &index );
4522 index = mEditor->indexOfCurrentLineStart( paragraph, index );
4524 switch( placement ) {
4526 mEditor->setText( mEditor->text() + mOldSigText );
4529 mOldSigText =
"\n\n" + mOldSigText +
"\n";
4530 mEditor->insertAt( mOldSigText, paragraph, index );
4537 if ( mEditor->paragraphLength( paragraph ) > 0 )
4538 mOldSigText = mOldSigText +
"\n";
4539 if ( mOldSigText.startsWith(
"\n" ) )
4540 mOldSigText = mOldSigText.remove( 0, 1 );
4545 mOldSigText =
"\n" + mOldSigText;
4547 mEditor->insertAt( mOldSigText, paragraph, index );
4551 mEditor->setModified(mod);
4553 if ( mPreserveUserCursorPosition ) {
4554 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
4559 mPreserveUserCursorPosition =
false;
4564 mEditor->setCursorPosition( paragraph, 0 );
4567 mEditor->setCursorPosition( paragraph + 1, 0 );
4569 if ( placement == Prepend || placement == Append )
4570 mEditor->setContentsPos( 0, 0 );
4577 void KMComposeWin::slotHelp()
4583 void KMComposeWin::slotCleanSpace()
4594 if ( mEditor->hasMarkedText() ) {
4595 s = mEditor->markedText();
4599 s = mEditor->text();
4604 bool restore =
false;
4605 const KPIM::Identity & ident =
4606 kmkernel->identityManager()->identityForUoid( mId );
4607 if ( !ident.isNull() ) {
4608 sig = ident.signatureText();
4609 if( !sig.isEmpty() ) {
4610 if( s.endsWith( sig ) ) {
4611 s.truncate( s.length() - sig.length() );
4618 TQRegExp squeeze(
"[\t ]+" );
4619 s.replace( squeeze, TQChar(
' ' ) );
4622 TQRegExp trailing(
"\\s+$" );
4623 s.replace( trailing, TQChar(
'\n' ) );
4626 TQRegExp singleSpace(
"[\n]{2,}" );
4627 s.replace( singleSpace, TQChar(
'\n' ) );
4640 if ( !mEditor->hasMarkedText() )
4642 mEditor->insert( s );
4646 void KMComposeWin::slotToggleMarkup()
4648 if ( markupAction->isChecked() ) {
4650 toolBar(
"htmlToolBar")->show();
4652 fontChanged( mEditor->currentFont() );
4653 mSaveFont = mEditor->currentFont();
4656 toggleMarkup(
false);
4660 void KMComposeWin::toggleMarkup(
bool markup)
4663 if ( !mUseHTMLEditor ) {
4664 kdDebug(5006) <<
"setting RichText editor" << endl;
4665 mUseHTMLEditor =
true;
4669 int paraFrom, indexFrom, paraTo, indexTo;
4670 mEditor->getSelection ( ¶From, &indexFrom, ¶To, &indexTo);
4671 mEditor->selectAll();
4673 bool _bold = textBoldAction->isChecked();
4674 bool _italic = textItalicAction->isChecked();
4675 mEditor->setColor(TQColor(0,0,0));
4676 textBoldAction->setChecked(_bold);
4677 textItalicAction->setChecked(_italic);
4678 mEditor->setSelection ( paraFrom, indexFrom, paraTo, indexTo);
4680 mEditor->setTextFormat(TQt::RichText);
4681 mEditor->setModified(
true);
4682 markupAction->setChecked(
true);
4683 toolBar(
"htmlToolBar" )->show();
4684 mEditor->deleteAutoSpellChecking();
4685 mAutoSpellCheckingAction->setChecked(
false);
4686 slotAutoSpellCheckingToggled(
false);
4689 kdDebug(5006) <<
"setting PlainText editor" << endl;
4690 mHtmlMarkup =
false;
4691 toolBar(
"htmlToolBar")->hide();
4692 if ( mUseHTMLEditor ) {
4693 mUseHTMLEditor =
false;
4694 mEditor->setTextFormat(TQt::PlainText);
4695 TQString text = mEditor->text();
4696 mEditor->setText(text);
4697 mEditor->setModified(
true);
4698 slotAutoSpellCheckingToggled(
true);
4703 void KMComposeWin::htmlToolBarVisibilityChanged(
bool visible )
4707 markupAction->setChecked(
false );
4708 toggleMarkup(
false );
4712 void KMComposeWin::slotSubjectTextSpellChecked()
4714 mSubjectTextWasSpellChecked =
true;
4718 void KMComposeWin::slotAutoSpellCheckingToggled(
bool on )
4720 if ( mEditor->autoSpellChecking(on) == -1 ) {
4721 mAutoSpellCheckingAction->setChecked(
false);
4726 temp = i18n(
"Spellcheck: on" );
4728 temp = i18n(
"Spellcheck: off" );
4729 statusBar()->changeItem( temp, 3 );
4732 void KMComposeWin::slotSpellcheck()
4734 if (mSpellCheckInProgress)
return;
4735 mSubjectTextWasSpellChecked =
false;
4736 mSpellCheckInProgress=
true;
4742 mEditor->spellcheck();
4745 void KMComposeWin::slotUpdateSignatureActions()
4749 const KPIM::Identity & ident =
4750 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity->currentIdentity() );
4751 TQString sig = ident.signatureText();
4753 if ( sig.isEmpty() ) {
4754 mAppendSignatureAction->setEnabled(
false );
4755 mPrependSignatureAction->setEnabled(
false );
4756 mInsertSignatureAction->setEnabled(
false );
4759 mAppendSignatureAction->setEnabled(
true );
4760 mPrependSignatureAction->setEnabled(
true );
4761 mInsertSignatureAction->setEnabled(
true );
4765 void KMComposeWin::polish()
4768 markupAction->setChecked(mHtmlMarkup);
4770 toolBar(
"htmlToolBar")->show();
4772 toolBar(
"htmlToolBar")->hide();
4773 KMail::Composer::polish();
4777 void KMComposeWin::slotSpellcheckDone(
int result)
4779 kdDebug(5006) <<
"spell check complete: result = " << result << endl;
4780 mSpellCheckInProgress=
false;
4785 statusBar()->changeItem(i18n(
" Spell check canceled."),0);
4788 statusBar()->changeItem(i18n(
" Spell check stopped."),0);
4791 statusBar()->changeItem(i18n(
" Spell check complete."),0);
4794 TQTimer::singleShot( 2000,
this, TQ_SLOT(slotSpellcheckDoneClearStatus()) );
4797 void KMComposeWin::slotSpellcheckDoneClearStatus()
4799 statusBar()->changeItem(
"", 0);
4804 void KMComposeWin::slotIdentityChanged( uint uoid )
4806 const KPIM::Identity & ident =
4807 kmkernel->identityManager()->identityForUoid( uoid );
4808 if( ident.isNull() )
return;
4811 slotUpdateSignatureActions();
4813 if( !ident.fullEmailAddr().isNull() )
4814 mEdtFrom->setText(ident.fullEmailAddr());
4816 if ( KPIM::getFirstEmailAddress( from() ).isEmpty() )
4817 mShowHeaders |= HDR_FROM;
4818 if ( mEdtReplyTo ) mEdtReplyTo->setText(ident.replyToAddr());
4820 if ( mRecipientsEditor ) {
4822 const KPIM::Identity & oldIdentity =
4823 kmkernel->identityManager()->identityForUoidOrDefault( mId );
4824 if ( oldIdentity.bcc() != ident.bcc() ) {
4825 mRecipientsEditor->removeRecipient( oldIdentity.bcc(), Recipient::Bcc );
4826 mRecipientsEditor->addRecipient( ident.bcc(), Recipient::Bcc );
4827 mRecipientsEditor->setFocusBottom();
4833 if( mEdtBcc && !mEdtBcc->edited() && !ident.bcc().isEmpty() ) {
4836 if( !mEdtBcc->text().isEmpty() && mEdtBcc->text() != ident.bcc() && !mEdtBcc->edited() ) {
4837 mEdtBcc->setText( ident.bcc() );
4842 if ( mEdtBcc->text() != ident.bcc() && !mEdtBcc->text().isEmpty() ) {
4843 TQString temp_string( mEdtBcc->text() + TQString::fromLatin1(
",") + ident.bcc() );
4844 mEdtBcc->setText( temp_string );
4848 mEdtBcc->setText( ident.bcc() );
4855 if( mEdtBcc && mEdtBcc->edited() && !ident.bcc().isEmpty() ) {
4856 if( !mEdtBcc->text().isEmpty() ) {
4857 TQString temp_string ( mEdtBcc->text() + TQString::fromLatin1(
",") + ident.bcc() );
4858 mEdtBcc->setText( temp_string );
4860 mEdtBcc->setText( ident.bcc() );
4866 if( mEdtBcc && !mEdtBcc->edited() && ident.bcc().isEmpty() ) {
4867 mEdtBcc->setText( ident.bcc() );
4870 if ( !ident.bcc().isEmpty() ) {
4871 mShowHeaders |= HDR_BCC;
4874 if ( ident.organization().isEmpty() )
4875 mMsg->removeHeaderField(
"Organization");
4877 mMsg->setHeaderField(
"Organization", ident.organization());
4879 if (!ident.isXFaceEnabled() || ident.xface().isEmpty())
4880 mMsg->removeHeaderField(
"X-Face");
4883 TQString xface = ident.xface();
4884 if (!xface.isEmpty())
4886 int numNL = ( xface.length() - 1 ) / 70;
4887 for (
int i = numNL; i > 0; --i )
4888 xface.insert( i*70,
"\n\t" );
4889 mMsg->setHeaderField(
"X-Face", xface);
4893 if ( !mBtnTransport->isChecked() && !mIgnoreStickyFields ) {
4894 TQString transp = ident.transport();
4895 if ( transp.isEmpty() )
4897 mMsg->removeHeaderField(
"X-KMail-Transport");
4898 transp = GlobalSettings::self()->defaultTransport();
4901 mMsg->setHeaderField(
"X-KMail-Transport", transp);
4902 setTransport( transp );
4905 if ( !mBtnDictionary->isChecked() && !mIgnoreStickyFields ) {
4906 mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
4909 if ( !mBtnFcc->isChecked() && !mPreventFccOverwrite ) {
4910 setFcc( ident.fcc() );
4913 TQString edtText = mEditor->text();
4915 if ( mOldSigText.isEmpty() ) {
4916 const KPIM::Identity &
id =
4919 identityForUoidOrDefault( mMsg->headerField(
"X-KMail-Identity" ).
4920 stripWhiteSpace().toUInt() );
4921 mOldSigText = GlobalSettings::self()->prependSignature() ?
id.signature().rawText() :
id.signatureText();
4925 if ( !GlobalSettings::prependSignature() ) {
4928 while ( !edtText.isEmpty() && edtText[edtText.length()-1].isSpace() )
4929 edtText.truncate( edtText.length() - 1 );
4931 while ( !mOldSigText.isEmpty() && mOldSigText[mOldSigText.length()-1].isSpace() )
4932 mOldSigText.truncate( mOldSigText.length() - 1 );
4934 if ( edtText.endsWith( mOldSigText ) )
4935 edtText.truncate( edtText.length() - mOldSigText.length() );
4938 mOldSigText = ident.signatureText();
4939 if( ( !mOldSigText.isEmpty() ) &&
4940 ( GlobalSettings::self()->autoTextSignature() ==
"auto" ) ) {
4941 edtText.append( mOldSigText );
4943 mEditor->setText( edtText );
4945 const int pos = edtText.find( mOldSigText );
4946 if ( pos >= 0 && !mOldSigText.isEmpty() ) {
4947 const int oldLength = mOldSigText.length();
4948 mOldSigText =
"\n\n"+ ident.signature().rawText() +
"\n";
4949 edtText = edtText.replace( pos, oldLength, mOldSigText );
4950 mEditor->setText( edtText );
4952 insertSignature( Append );
4958 bool bNewIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
4959 bool bNewIdentityHasEncryptionKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
4960 mAttachMPK->setEnabled( Kleo::CryptoBackendFactory::instance()->openpgp() &&
4961 !ident.pgpEncryptionKey().isEmpty() );
4963 if ( !bNewIdentityHasEncryptionKey && mLastIdentityHasEncryptionKey ) {
4964 mLastEncryptActionState = mEncryptAction->isChecked();
4965 setEncryption(
false );
4967 if ( !bNewIdentityHasSigningKey && mLastIdentityHasSigningKey ) {
4968 mLastSignActionState = mSignAction->isChecked();
4969 setSigning(
false );
4972 if ( bNewIdentityHasEncryptionKey && !mLastIdentityHasEncryptionKey )
4973 setEncryption( mLastEncryptActionState );
4974 if ( bNewIdentityHasSigningKey && !mLastIdentityHasSigningKey )
4975 setSigning( mLastSignActionState );
4977 mLastIdentityHasSigningKey = bNewIdentityHasSigningKey;
4978 mLastIdentityHasEncryptionKey = bNewIdentityHasEncryptionKey;
4980 setModified(
true );
4984 rethinkFields(
false );
4988 void KMComposeWin::slotSpellcheckConfig()
4990 KDialogBase dlg(KDialogBase::Plain, i18n(
"Spellchecker"),
4991 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok,
4992 this, 0,
true,
true );
4994 TQTabDialog qtd (
this,
"tabdialog",
true);
4995 KSpellConfig mKSpellConfig (&qtd);
4996 mKSpellConfig.layout()->setMargin( KDialog::marginHint() );
4998 qtd.addTab (&mKSpellConfig, i18n(
"Spellchecker"));
4999 qtd.setCancelButton ();
5001 twin.setIcons (qtd.winId(), kapp->icon(), kapp->miniIcon());
5002 qtd.setCancelButton(KStdGuiItem::cancel().text());
5003 qtd.setOkButton(KStdGuiItem::ok().text());
5006 mKSpellConfig.writeGlobalSettings();
5010 void KMComposeWin::slotStatusMessage(
const TQString &message)
5012 statusBar()->changeItem( message, 0 );
5015 void KMComposeWin::slotEditToolbars()
5017 saveMainWindowSettings(KMKernel::config(),
"Composer");
5018 KEditToolbar dlg(guiFactory(),
this);
5020 connect( &dlg, TQ_SIGNAL(newToolbarConfig()),
5021 TQ_SLOT(slotUpdateToolbars()) );
5026 void KMComposeWin::slotUpdateToolbars()
5028 createGUI(
"kmcomposerui.rc");
5029 applyMainWindowSettings(KMKernel::config(),
"Composer");
5032 void KMComposeWin::slotEditKeys()
5034 KKeyDialog::configure( actionCollection(),
5039 void KMComposeWin::setReplyFocus(
bool hasMessage )
5041 mEditor->setFocus();
5043 if( mMsg->getCursorPos() ) {
5044 mEditor->setCursorPositionFromStart( (
unsigned int) mMsg->getCursorPos() );
5046 mEditor->setCursorPosition( 1, 0 );
5051 void KMComposeWin::setFocusToSubject()
5053 mEdtSubject->setFocus();
5056 int KMComposeWin::autoSaveInterval()
const
5058 return GlobalSettings::self()->autosaveInterval() * 1000 * 60;
5061 void KMComposeWin::initAutoSave()
5063 kdDebug(5006) << k_funcinfo << endl;
5066 if ( mAutoSaveFilename.isEmpty() ) {
5067 mAutoSaveFilename = KMFolderMaildir::constructValidFileName();
5073 void KMComposeWin::updateAutoSave()
5075 if ( autoSaveInterval() == 0 ) {
5076 delete mAutoSaveTimer; mAutoSaveTimer = 0;
5079 if ( !mAutoSaveTimer ) {
5080 mAutoSaveTimer =
new TQTimer(
this,
"mAutoSaveTimer" );
5081 connect( mAutoSaveTimer, TQ_SIGNAL( timeout() ),
5082 this, TQ_SLOT( autoSaveMessage() ) );
5084 mAutoSaveTimer->start( autoSaveInterval() );
5088 void KMComposeWin::setAutoSaveFilename(
const TQString & filename )
5090 mAutoSaveFilename = filename;
5093 void KMComposeWin::cleanupAutoSave()
5095 delete mAutoSaveTimer; mAutoSaveTimer = 0;
5096 if ( !mAutoSaveFilename.isEmpty() ) {
5097 kdDebug(5006) << k_funcinfo <<
"deleting autosave file "
5098 << mAutoSaveFilename << endl;
5100 mAutoSaveFilename );
5101 mAutoSaveFilename = TQString();
5105 void KMComposeWin::slotCompletionModeChanged( TDEGlobalSettings::Completion mode)
5107 GlobalSettings::self()->setCompletionMode( (
int) mode );
5110 mEdtFrom->setCompletionMode( mode );
5111 mEdtReplyTo->setCompletionMode( mode );
5112 if ( mClassicalRecipients ) {
5113 mEdtTo->setCompletionMode( mode );
5114 mEdtCc->setCompletionMode( mode );
5115 mEdtBcc->setCompletionMode( mode );
5117 mRecipientsEditor->setCompletionMode( mode );
5120 void KMComposeWin::slotConfigChanged()
5125 slotWordWrapToggled( mWordWrapAction->isChecked() );
5132 void KMComposeWin::slotFolderRemoved(
KMFolder* folder)
5135 if ( (mFolder) && (folder->
idString() == mFolder->idString()) )
5137 mFolder = kmkernel->draftsFolder();
5138 kdDebug(5006) <<
"restoring drafts to " << mFolder->idString() << endl;
5140 if (mMsg) mMsg->setParent(0);
5144 void KMComposeWin::editorFocusChanged(
bool gained)
5146 mPasteQuotation->setEnabled(gained);
5149 void KMComposeWin::slotSetAlwaysSend(
bool bAlways )
5151 mAlwaysSend = bAlways;
5154 void KMComposeWin::slotListAction(
const TQString& style )
5157 if ( style == i18n(
"Standard" ) )
5158 mEditor->setParagType( TQStyleSheetItem::DisplayBlock, TQStyleSheetItem::ListDisc );
5159 else if ( style == i18n(
"Bulleted List (Disc)" ) )
5160 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDisc );
5161 else if ( style == i18n(
"Bulleted List (Circle)" ) )
5162 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListCircle );
5163 else if ( style == i18n(
"Bulleted List (Square)" ) )
5164 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListSquare );
5165 else if ( style == i18n(
"Ordered List (Decimal)" ))
5166 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDecimal );
5167 else if ( style == i18n(
"Ordered List (Alpha lower)" ) )
5168 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListLowerAlpha );
5169 else if ( style == i18n(
"Ordered List (Alpha upper)" ) )
5170 mEditor->setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListUpperAlpha );
5171 mEditor->viewport()->setFocus();
5174 void KMComposeWin::slotFontAction(
const TQString& font)
5177 mEditor->TQTextEdit::setFamily( font );
5178 mEditor->viewport()->setFocus();
5181 void KMComposeWin::slotSizeAction(
int size )
5184 mEditor->setPointSize( size );
5185 mEditor->viewport()->setFocus();
5188 void KMComposeWin::slotAlignLeft()
5191 mEditor->TQTextEdit::setAlignment( AlignLeft );
5194 void KMComposeWin::slotAlignCenter()
5197 mEditor->TQTextEdit::setAlignment( AlignHCenter );
5200 void KMComposeWin::slotAlignRight()
5203 mEditor->TQTextEdit::setAlignment( AlignRight );
5206 void KMComposeWin::slotTextBold()
5209 mEditor->TQTextEdit::setBold( textBoldAction->isChecked() );
5212 void KMComposeWin::slotTextItalic()
5215 mEditor->TQTextEdit::setItalic( textItalicAction->isChecked() );
5218 void KMComposeWin::slotTextUnder()
5221 mEditor->TQTextEdit::setUnderline( textUnderAction->isChecked() );
5224 void KMComposeWin::slotFormatReset()
5226 mEditor->setColor(mForeColor);
5227 mEditor->setCurrentFont( mSaveFont );
5229 void KMComposeWin::slotTextColor()
5231 TQColor color = mEditor->color();
5233 if ( KColorDialog::getColor( color,
this ) ) {
5235 mEditor->setColor( color );
5239 void KMComposeWin::fontChanged(
const TQFont &f )
5241 TQFont fontTemp = f;
5242 fontTemp.setBold(
true );
5243 fontTemp.setItalic(
true );
5244 TQFontInfo fontInfo( fontTemp );
5246 if ( fontInfo.bold() ) {
5247 textBoldAction->setChecked( f.bold() );
5248 textBoldAction->setEnabled(
true ) ;
5250 textBoldAction->setEnabled(
false );
5253 if ( fontInfo.italic() ) {
5254 textItalicAction->setChecked( f.italic() );
5255 textItalicAction->setEnabled(
true ) ;
5257 textItalicAction->setEnabled(
false );
5260 textUnderAction->setChecked( f.underline() );
5262 fontAction->setFont( f.family() );
5263 fontSizeAction->setFontSize( f.pointSize() );
5266 void KMComposeWin::alignmentChanged(
int a )
5269 alignLeftAction->setChecked( ( a == AlignAuto ) || ( a & AlignLeft ) );
5270 alignCenterAction->setChecked( ( a & AlignHCenter ) );
5271 alignRightAction->setChecked( ( a & AlignRight ) );
5275 class TDEToggleActionResetter {
5276 TDEToggleAction * mAction;
5279 TDEToggleActionResetter( TDEToggleAction * action,
bool on )
5280 : mAction( action ), mOn( on ) {}
5281 ~TDEToggleActionResetter() {
5283 mAction->setChecked( mOn );
5285 void disable() { mAction = 0; }
5289 void KMComposeWin::slotEncryptChiasmusToggled(
bool on ) {
5290 mEncryptWithChiasmus =
false;
5295 TDEToggleActionResetter resetter( mEncryptChiasmusAction,
false );
5297 const Kleo::CryptoBackend::Protocol * chiasmus =
5298 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" );
5301 const TQString msg = Kleo::CryptoBackendFactory::instance()->knowsAboutProtocol(
"Chiasmus" )
5302 ? i18n(
"Please configure a Crypto Backend to use for "
5303 "Chiasmus encryption first.\n"
5304 "You can do this in the Crypto Backends tab of "
5305 "the configure dialog's Security page." )
5306 : i18n(
"It looks as though libkleopatra was compiled without "
5307 "Chiasmus support. You might want to recompile "
5308 "libkleopatra with --enable-chiasmus.");
5309 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Backend Configured" ) );
5313 STD_NAMESPACE_PREFIX unique_ptr<Kleo::SpecialJob> job( chiasmus->specialJob(
"x-obtain-keys", TQStringVariantMap() ) );
5315 const TQString msg = i18n(
"Chiasmus backend does not offer the "
5316 "\"x-obtain-keys\" function. Please report this bug." );
5317 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
5321 if ( job->exec() ) {
5322 job->showErrorDialog(
this, i18n(
"Chiasmus Backend Error" ) );
5326 const TQVariant result = job->property(
"result" );
5327 if ( result.type() != TQVariant::StringList ) {
5328 const TQString msg = i18n(
"Unexpected return value from Chiasmus backend: "
5329 "The \"x-obtain-keys\" function did not return a "
5330 "string list. Please report this bug." );
5331 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
5335 const TQStringList keys = result.toStringList();
5336 if ( keys.empty() ) {
5337 const TQString msg = i18n(
"No keys have been found. Please check that a "
5338 "valid key path has been set in the Chiasmus "
5340 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Keys Found" ) );
5344 ChiasmusKeySelector selectorDlg(
this, i18n(
"Chiasmus Encryption Key Selection" ),
5345 keys, GlobalSettings::chiasmusKey(),
5346 GlobalSettings::chiasmusOptions() );
5347 if ( selectorDlg.exec() != TQDialog::Accepted )
5350 GlobalSettings::setChiasmusOptions( selectorDlg.options() );
5351 GlobalSettings::setChiasmusKey( selectorDlg.key() );
5352 assert( !GlobalSettings::chiasmusKey().isEmpty() );
5353 mEncryptWithChiasmus =
true;
5359 kdDebug(5006) << k_funcinfo << endl;
5360 KMMessagePart *part = mEditorMap[ watcher ];
5361 KTempFile *tf = mEditorTempFiles[ watcher ];
5362 mEditorMap.remove( watcher );
5363 mEditorTempFiles.remove( watcher );
5364 if ( !watcher->fileChanged() )
5367 tf->file()->reset();
5368 TQByteArray data = tf->file()->readAll();
5369 part->setBodyEncodedBinary( data );
5373 void KMComposeWin::slotUpdateSignatureAndEncrypionStateIndicators()
5375 const bool showIndicatorsAlways =
false;
5376 mSignatureStateIndicator->setText( mSignAction->isChecked()? i18n(
"Message will be signed") : i18n(
"Message will not be signed") );
5377 mEncryptionStateIndicator->setText( mEncryptAction->isChecked()? i18n(
"Message will be encrypted") : i18n(
"Message will not be encrypted") );
5378 if ( !showIndicatorsAlways ) {
5379 mSignatureStateIndicator->setShown( mSignAction->isChecked() );
5380 mEncryptionStateIndicator->setShown( mEncryptAction->isChecked() );
5384 void KMComposeWin::slotAttachmentDragStarted()
5386 kdDebug(5006) << k_funcinfo << endl;
5388 TQStringList filenames;
5389 for ( TQPtrListIterator<TQListViewItem> it(mAtmItemList); *it; ++it, ++idx ) {
5390 if ( (*it)->isSelected() ) {
5391 KMMessagePart* msgPart = mAtmList.at(idx);
5392 KTempDir * tempDir =
new KTempDir();
5393 tempDir->setAutoDelete(
true );
5394 mTempDirs.insert( tempDir );
5395 const TQString fileName = tempDir->name() +
"/" + msgPart->name();
5396 KPIM::kByteArrayToFile(msgPart->bodyDecodedBinary(),
5398 false,
false,
false);
5400 url.setPath( fileName );
5401 filenames << url.path();
5404 if ( filenames.isEmpty() )
return;
5406 TQUriDrag *drag =
new TQUriDrag( mAtmListView );
5407 drag->setFileNames( filenames );
5411 void KMComposeWin::recipientEditorSizeHintChanged()
5413 TQTimer::singleShot( 1,
this, TQ_SLOT(setMaximumHeaderSize()) );
5416 void KMComposeWin::setMaximumHeaderSize()
5418 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
Provides encoding detection capabilities.
const char * encoding() const
Convenience method.
bool analyze(const char *data, int len)
Analyze text data.
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
TQString idString() const
Returns a string that can be used to identify this folder.
KMMsgInfo * unGetMsg(int idx)
Replace KMMessage with KMMsgInfo and delete KMMessage
int addMsg(KMMessage *msg, int *index_return=0)
Add the given message to the folder.
void close(const char *owner, bool force=false)
Close folder.
KMMessage * getMsg(int idx)
Read message at given index.
int count(bool cache=false) const
Number of messages in this folder.
int open(const char *owner)
Open folder for access.
static TQString localDataPath()
Returns the full path of the user's local data directory for KMail.
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...
static TQString smartQuote(const TQString &msg, int maxLineLength)
Given argument msg add quoting characters and relayout for max width maxLength.
static const TQStringList & preferredCharsets()
Get a list of preferred message charsets.
static TQString expandAliases(const TQString &recipients)
Expands aliases (distribution lists and nick names) and appends a domain part to all email addresses ...
const DwString & asDwString() const
Return the entire message contents in the DwString.
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
static TQCString defaultCharset()
Get the default message charset.
TQString fcc() const
Get or set the 'Fcc' header field.
void initHeader(uint identity=0)
Initialize header fields.
The attachment dialog with convenience backward compatible methods.
A combo box for selecting the dictionary used for spell checking.
Starts an editor for the given URL and emits an signal when editing has been finished.
static TQStringList transportNames()
Returns the list for transport names.
DCOP interface for mail composer window.