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