29 #include "messagecomposer/attachment/attachmentmodel.h"
32 #include <messagecomposer/job/emailaddressresolvejob.h>
33 #include "kleo_util.h"
40 #include "mailcomposeradaptor.h"
41 #include "messageviewer/viewer/stl_util.h"
42 #include "messageviewer/utils/util.h"
43 #include "messagecore/utils/stringutil.h"
44 #include "messagecore/attachment/attachmentcollector.h"
47 #include "templatesconfiguration_kfg.h"
48 #include "foldercollectionmonitor.h"
49 #include "kernel/mailkernel.h"
51 #include "messagecomposer/autocorrection/subjectlineeditwithautocorrection.h"
52 #include "pimcommon/translator/translatorwidget.h"
57 #include "agents/sendlateragent/sendlaterutil.h"
58 #include "agents/sendlateragent/sendlaterdialog.h"
59 #include "agents/sendlateragent/sendlaterinfo.h"
62 #include <libkpgp/kpgpblock.h>
63 #include <libkleo/ui/progressdialog.h>
64 #include <libkleo/ui/keyselectiondialog.h>
65 #include "kleo/cryptobackendfactory.h"
66 #include "kleo/exportjob.h"
67 #include "kleo/specialjob.h"
68 #include <messageviewer/viewer/objecttreeemptysource.h>
71 #include <messageviewer/utils/kcursorsaver.h>
74 #include <messageviewer/viewer/objecttreeparser.h>
75 #include <messageviewer/viewer/nodehelper.h>
77 #include <messageviewer/settings/globalsettings.h>
78 #include <messagecomposer/composer/composer.h>
79 #include <messagecomposer/part/globalpart.h>
80 #include <messagecomposer/part/infopart.h>
81 #include <messagecomposer/part/textpart.h>
82 #include <settings/messagecomposersettings.h>
83 #include <messagecomposer/helper/messagehelper.h>
84 #include <messagecomposer/composer/signaturecontroller.h>
85 #include <messagecomposer/job/inserttextfilejob.h>
86 #include <messagecomposer/composer/composerlineedit.h>
87 #include <messagecore/attachment/attachmentpart.h>
88 #include "messagecore/settings/globalsettings.h"
89 #include <templateparser/templateparser.h>
90 #include <templatesconfiguration.h>
91 #include "messagecore/helpers/nodehelper.h"
92 #include <akonadi/kmime/messagestatus.h>
93 #include "messagecore/helpers/messagehelpers.h"
94 #include "mailcommon/folder/folderrequester.h"
95 #include "mailcommon/folder/foldercollection.h"
102 #include <akonadi/changerecorder.h>
103 #include <akonadi/itemcreatejob.h>
104 #include <akonadi/entitymimetypefiltermodel.h>
105 #include <akonadi/itemfetchjob.h>
106 #include <kpimutils/email.h>
107 #include <kpimidentities/identitymanager.h>
108 #include <kpimidentities/identitycombo.h>
109 #include <kpimidentities/identity.h>
110 #include <mailtransport/transportcombobox.h>
111 #include <mailtransport/transportmanager.h>
112 #include <mailtransport/transport.h>
113 #include <kmime/kmime_codecs.h>
114 #include <kmime/kmime_message.h>
115 #include <kpimtextedit/selectspecialchar.h>
119 #include <kactioncollection.h>
120 #include <kactionmenu.h>
121 #include <kapplication.h>
122 #include <kcharsets.h>
124 #include <kdescendantsproxymodel.h>
125 #include <kedittoolbar.h>
126 #include <kinputdialog.h>
128 #include <kmimetype.h>
129 #include <kmessagebox.h>
130 #include <krecentfilesaction.h>
131 #include <kshortcutsdialog.h>
132 #include <kstandarddirs.h>
133 #include <kstandardshortcut.h>
134 #include <kstatusbar.h>
135 #include <ktempdir.h>
136 #include <ktoggleaction.h>
137 #include <ktoolbar.h>
138 #include <ktoolinvocation.h>
139 #include <sonnet/dictionarycombobox.h>
141 #include <KIO/JobUiDelegate>
142 #include <KPrintPreview>
143 #include <KFileDialog>
146 #include <QClipboard>
153 #include <QTextDocumentWriter>
160 #include <boost/shared_ptr.hpp>
163 #include "kmcomposewin.moc"
165 using Sonnet::DictionaryComboBox;
166 using MailTransport::TransportManager;
167 using MailTransport::Transport;
169 using MessageComposer::KMeditor;
171 KMail::Composer *KMail::makeComposer(
const KMime::Message::Ptr &msg,
bool lastSignState,
bool lastEncryptState, Composer::TemplateContext context,
172 uint identity,
const QString & textSelection,
173 const QString & customTemplate ) {
174 return KMComposeWin::create( msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate );
178 uint identity,
const QString & textSelection,
179 const QString & customTemplate ) {
180 return new KMComposeWin( msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate );
183 int KMComposeWin::s_composerNumber = 0;
186 KMComposeWin::KMComposeWin(
const KMime::Message::Ptr &aMsg,
bool lastSignState,
bool lastEncryptState, Composer::TemplateContext context, uint
id,
187 const QString & textSelection,
const QString & customTemplate )
188 : KMail::Composer(
"kmail-composer#" ),
190 mTextSelection( textSelection ),
191 mCustomTemplate( customTemplate ),
192 mSigningAndEncryptionExplicitlyDisabled( false ),
193 mFolder( Akonadi::Collection( -1 ) ),
194 mForceDisableHtml( false ),
197 mSignAction( 0 ), mEncryptAction( 0 ), mRequestMDNAction( 0 ),
198 mUrgentAction( 0 ), mAllFieldsAction( 0 ), mFromAction( 0 ),
199 mReplyToAction( 0 ), mSubjectAction( 0 ),
200 mIdentityAction( 0 ), mTransportAction( 0 ), mFccAction( 0 ),
201 mWordWrapAction( 0 ), mFixedFontAction( 0 ), mAutoSpellCheckingAction( 0 ),
202 mDictionaryAction( 0 ), mSnippetAction( 0 ), mTranslateAction(0),
204 mCryptoModuleAction( 0 ),
215 mSelectSpecialChar( 0 ),
216 mSignatureStateIndicator( 0 ), mEncryptionStateIndicator( 0 ),
217 mPreventFccOverwrite( false ),
218 mCheckForForgottenAttachments( true ),
219 mIgnoreStickyFields( false ),
220 mWasModified( false )
223 mComposerBase =
new MessageComposer::ComposerViewBase(
this,
this );
224 mComposerBase->setIdentityManager(
kmkernel->identityManager() );
226 connect( mComposerBase, SIGNAL(disableHtml(MessageComposer::ComposerViewBase::Confirmation)),
227 this, SLOT(disableHtml(MessageComposer::ComposerViewBase::Confirmation)) );
229 connect( mComposerBase, SIGNAL(enableHtml()),
230 this, SLOT(enableHtml()) );
231 connect( mComposerBase, SIGNAL(failed(QString,MessageComposer::ComposerViewBase::FailedType)),
this, SLOT(slotSendFailed(QString,MessageComposer::ComposerViewBase::FailedType)) );
232 connect( mComposerBase, SIGNAL(sentSuccessfully()),
this, SLOT(slotSendSuccessful()) );
233 connect( mComposerBase, SIGNAL(modified(
bool)),
this, SLOT(
setModified(
bool)) );
235 (void)
new MailcomposerAdaptor(
this );
236 mdbusObjectPath = QLatin1String(
"/Composer_") + QString::number( ++s_composerNumber );
237 QDBusConnection::sessionBus().registerObject( mdbusObjectPath,
this );
239 MessageComposer::SignatureController* sigController =
new MessageComposer::SignatureController(
this );
240 connect( sigController, SIGNAL(enableHtml()), SLOT(enableHtml()) );
241 mComposerBase->setSignatureController( sigController );
243 if (
kmkernel->xmlGuiInstance().isValid() ) {
244 setComponentData(
kmkernel->xmlGuiInstance() );
246 mMainWidget =
new QWidget(
this );
248 mHeadersToEditorSplitter =
new QSplitter( Qt::Vertical, mMainWidget );
249 mHeadersToEditorSplitter->setObjectName( QLatin1String(
"mHeadersToEditorSplitter") );
250 mHeadersToEditorSplitter->setChildrenCollapsible(
false );
251 mHeadersArea =
new QWidget( mHeadersToEditorSplitter );
252 mHeadersArea->setSizePolicy( mHeadersToEditorSplitter->sizePolicy().horizontalPolicy(),
253 QSizePolicy::Expanding );
254 mHeadersToEditorSplitter->addWidget( mHeadersArea );
257 mHeadersToEditorSplitter->setSizes( defaultSizes );
261 QVBoxLayout *v =
new QVBoxLayout( mMainWidget );
264 nepomukWarning->
setMissingFeatures( QStringList() << i18n(
"Recipient auto-completion") << i18n(
"Distribution lists") << i18n(
"Per-contact crypto preferences") );
265 v->addWidget( nepomukWarning );
268 v->addWidget( mHeadersToEditorSplitter );
269 KPIMIdentities::IdentityCombo*
identity =
new KPIMIdentities::IdentityCombo(
kmkernel->identityManager(),
271 identity->setToolTip( i18n(
"Select an identity for this message" ) );
272 mComposerBase->setIdentityCombo( identity );
274 sigController->setIdentityCombo( identity );
275 sigController->suspend();
277 mDictionaryCombo =
new DictionaryComboBox( mHeadersArea );
278 mDictionaryCombo->setToolTip( i18n(
"Select the dictionary to use when spell-checking this message" ) );
280 mFccFolder =
new MailCommon::FolderRequester( mHeadersArea );
281 mFccFolder->setNotAllowToCreateNewFolder(
true );
282 mFccFolder->setMustBeReadWrite(
true );
285 mFccFolder->setToolTip( i18n(
"Select the sent-mail folder where a copy of this message will be saved" ) );
286 connect( mFccFolder, SIGNAL(folderChanged(Akonadi::Collection)),
287 this, SLOT(slotFccFolderChanged(Akonadi::Collection)) );
289 MailTransport::TransportComboBox* transport =
new MailTransport::TransportComboBox( mHeadersArea );
290 transport->setToolTip( i18n(
"Select the outgoing account to use for sending this message" ) );
291 mComposerBase->setTransportCombo( transport );
293 mEdtFrom =
new MessageComposer::ComposerLineEdit(
false, mHeadersArea );
294 mEdtFrom->setObjectName( QLatin1String(
"fromLine") );
295 mEdtFrom->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
296 mEdtFrom->setToolTip( i18n(
"Set the \"From:\" email address for this message" ) );
297 mEdtReplyTo =
new MessageComposer::ComposerLineEdit(
true, mHeadersArea );
298 mEdtReplyTo->setObjectName( QLatin1String(
"replyToLine") );
299 mEdtReplyTo->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
300 mEdtReplyTo->setToolTip( i18n(
"Set the \"Reply-To:\" email address for this message" ) );
301 connect( mEdtReplyTo, SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
302 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)) );
304 MessageComposer::RecipientsEditor* recipientsEditor =
new MessageComposer::RecipientsEditor( mHeadersArea );
305 recipientsEditor->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
306 connect( recipientsEditor,
307 SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
308 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)) );
309 connect( recipientsEditor, SIGNAL(sizeHintChanged()), SLOT(recipientEditorSizeHintChanged()) );
310 mComposerBase->setRecipientsEditor( recipientsEditor );
312 mEdtSubject =
new MessageComposer::SubjectLineEditWithAutoCorrection( mHeadersArea, QLatin1String(
"kmail2rc" ) );
313 mEdtSubject->setActivateLanguageMenu(
false);
314 mEdtSubject->setToolTip( i18n(
"Set a subject for this message" ) );
315 mEdtSubject->setAutocorrection(
KMKernel::self()->composerAutoCorrection());
316 mLblIdentity =
new QLabel( i18n(
"&Identity:"), mHeadersArea );
317 mDictionaryLabel =
new QLabel( i18n(
"&Dictionary:"), mHeadersArea );
318 mLblFcc =
new QLabel( i18n(
"&Sent-Mail folder:"), mHeadersArea );
319 mLblTransport =
new QLabel( i18n(
"&Mail transport:"), mHeadersArea );
320 mLblFrom =
new QLabel( i18nc(
"sender address field",
"&From:"), mHeadersArea );
321 mLblReplyTo =
new QLabel( i18n(
"&Reply to:"), mHeadersArea );
322 mLblSubject =
new QLabel( i18nc(
"@label:textbox Subject of email.",
"S&ubject:"), mHeadersArea );
323 QString sticky = i18nc(
"@option:check Sticky identity.",
"Sticky");
324 mBtnIdentity =
new QCheckBox( sticky, mHeadersArea );
325 mBtnIdentity->setToolTip( i18n(
"Use the selected value as your identity for future messages" ) );
326 mBtnFcc =
new QCheckBox( sticky, mHeadersArea );
327 mBtnFcc->setToolTip( i18n(
"Use the selected value as your sent-mail folder for future messages" ) );
328 mBtnTransport =
new QCheckBox( sticky, mHeadersArea );
329 mBtnTransport->setToolTip( i18n(
"Use the selected value as your outgoing account for future messages" ) );
330 mBtnDictionary =
new QCheckBox( sticky, mHeadersArea );
331 mBtnDictionary->setToolTip( i18n(
"Use the selected value as your dictionary for future messages" ) );
336 mFixedFontAction = 0;
338 mSplitter =
new QSplitter( Qt::Vertical, mMainWidget );
339 mSplitter->setObjectName( QLatin1String(
"mSplitter") );
340 mSplitter->setChildrenCollapsible(
false );
341 mSnippetSplitter =
new QSplitter( Qt::Horizontal, mSplitter );
342 mSnippetSplitter->setObjectName( QLatin1String(
"mSnippetSplitter") );
343 mSnippetSplitter->setChildrenCollapsible(
false );
344 mSplitter->addWidget( mSnippetSplitter );
346 QWidget *editorAndCryptoStateIndicators =
new QWidget( mSplitter );
347 QVBoxLayout *vbox =
new QVBoxLayout( editorAndCryptoStateIndicators );
349 QHBoxLayout *hbox =
new QHBoxLayout();
352 mSignatureStateIndicator =
new QLabel( editorAndCryptoStateIndicators );
353 mSignatureStateIndicator->setAlignment( Qt::AlignHCenter );
354 hbox->addWidget( mSignatureStateIndicator );
356 QPalette p( mSignatureStateIndicator->palette() );
357 KColorScheme scheme( QPalette::Active, KColorScheme::View );
358 QColor defaultSignedColor =
359 scheme.background( KColorScheme::PositiveBackground ).color();
360 QColor defaultEncryptedColor( 0x00, 0x80, 0xFF );
361 QColor signedColor = defaultSignedColor;
362 QColor encryptedColor = defaultEncryptedColor;
363 if ( !MessageCore::GlobalSettings::self()->useDefaultColors() ) {
364 signedColor = MessageCore::GlobalSettings::self()->pgpSignedMessageColor();
365 encryptedColor = MessageCore::GlobalSettings::self()->pgpEncryptedMessageColor();
368 p.setColor( QPalette::Window, signedColor );
369 mSignatureStateIndicator->setPalette( p );
370 mSignatureStateIndicator->setAutoFillBackground(
true );
372 mEncryptionStateIndicator =
new QLabel( editorAndCryptoStateIndicators );
373 mEncryptionStateIndicator->setAlignment( Qt::AlignHCenter );
374 hbox->addWidget( mEncryptionStateIndicator );
375 p.setColor( QPalette::Window, encryptedColor);
376 mEncryptionStateIndicator->setPalette( p );
377 mEncryptionStateIndicator->setAutoFillBackground(
true );
381 connect( editor, SIGNAL(textChanged()),
382 this, SLOT(slotEditorTextChanged()) );
383 mComposerBase->setEditor( editor );
384 vbox->addLayout( hbox );
385 vbox->addWidget( editor );
387 mSnippetSplitter->insertWidget( 0, editorAndCryptoStateIndicators );
388 mSnippetSplitter->setOpaqueResize(
true );
389 sigController->setEditor( editor );
391 mHeadersToEditorSplitter->addWidget( mSplitter );
392 editor->setAcceptDrops(
true );
393 connect(sigController, SIGNAL(signatureAdded()), mComposerBase->editor(), SLOT(startExternalEditor()));
395 connect( mDictionaryCombo, SIGNAL(dictionaryChanged(QString)),
396 this, SLOT(slotSpellCheckingLanguage(QString)) );
398 connect( editor, SIGNAL(languageChanged(QString)),
399 this, SLOT(slotLanguageChanged(QString)) );
400 connect( editor, SIGNAL(spellCheckStatus(QString)),
401 this, SLOT(slotSpellCheckingStatus(QString)) );
402 connect( editor, SIGNAL(insertModeChanged()),
403 this, SLOT(slotOverwriteModeChanged()) );
404 #ifdef HAVE_FORCESPELLCHECKING
405 connect(editor,SIGNAL(spellCheckingFinished()),
this,SLOT(slotCheckSendNow()));
407 mSnippetWidget =
new SnippetWidget( editor, actionCollection(), mSnippetSplitter );
409 mSnippetSplitter->addWidget( mSnippetWidget );
410 mSnippetSplitter->setCollapsible( 0,
false );
412 mSplitter->setOpaqueResize(
true );
420 setMinimumSize( 200, 200 );
422 mBtnIdentity->setFocusPolicy( Qt::NoFocus );
423 mBtnFcc->setFocusPolicy( Qt::NoFocus );
424 mBtnTransport->setFocusPolicy( Qt::NoFocus );
425 mBtnDictionary->setFocusPolicy( Qt::NoFocus );
427 mTranslatorWidget =
new PimCommon::TranslatorWidget(
this);
428 connect(mTranslatorWidget,SIGNAL(translatorWasClosed()),
this,SLOT(slotTranslatorWasClosed()));
429 mSplitter->addWidget(mTranslatorWidget);
431 MessageComposer::AttachmentModel* attachmentModel =
new MessageComposer::AttachmentModel(
this );
434 connect(attachmentView,SIGNAL(modified(
bool)),SLOT(
setModified(
bool)));
437 mComposerBase->setAttachmentModel( attachmentModel );
438 mComposerBase->setAttachmentController( attachmentController );
441 connect(mAttachmentMissing, SIGNAL(attachMissingFile()),
this, SLOT(slotAttachMissingFile()));
442 connect(mAttachmentMissing, SIGNAL(closeAttachMissingFile()),
this, SLOT(slotCloseAttachMissingFile()));
443 connect(mAttachmentMissing, SIGNAL(explicitClosedMissingAttachment()),
this, SLOT(slotExplicitClosedMissingAttachment()));
444 v->addWidget(mAttachmentMissing);
446 m_verifyMissingAttachment =
new QTimer(
this);
447 m_verifyMissingAttachment->start(1000*5);
448 connect( m_verifyMissingAttachment, SIGNAL(timeout()),
this, SLOT(slotVerifyMissingAttachmentTimeout()) );
449 connect( attachmentController, SIGNAL(fileAttached()), mAttachmentMissing, SLOT(slotFileAttached()) );
452 v->addWidget(mExternalEditorWarning);
455 setupStatusBar(attachmentView->
widget());
459 slotUpdateSignatureAndEncrypionStateIndicators();
461 applyMainWindowSettings(
KMKernel::self()->config()->group(
"Composer") );
463 connect( mEdtSubject, SIGNAL(textChanged()),
464 SLOT(slotUpdWinTitle()) );
466 SLOT(slotIdentityChanged(uint)) );
467 connect(
kmkernel->identityManager(), SIGNAL(changed(uint)),
468 SLOT(slotIdentityChanged(uint)) );
470 connect( mEdtFrom, SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
471 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)) );
472 connect(
kmkernel->folderCollectionMonitor(), SIGNAL(collectionRemoved(Akonadi::Collection)),
473 SLOT(slotFolderRemoved(Akonadi::Collection)) );
474 connect(
kmkernel, SIGNAL(configChanged()),
475 this, SLOT(slotConfigChanged()) );
477 mMainWidget->resize( 480, 510 );
478 setCentralWidget( mMainWidget );
483 disableHtml( MessageComposer::ComposerViewBase::LetUserConfirm );
486 editor->setUseExternalEditor(
true );
491 setMessage( aMsg, lastSignState, lastEncryptState );
494 mComposerBase->recipientsEditor()->setFocus();
495 editor->updateActionStates();
499 mDummyComposer =
new MessageComposer::Composer(
this );
500 mDummyComposer->globalPart()->setParentWidgetForGui(
this );
504 KMComposeWin::~KMComposeWin()
511 if ( mFolder.isValid() && mMsg && isModified() ) {
513 item.setPayload( mMsg );
514 item.setMimeType( KMime::Message::mimeType() );
515 MessageStatus status;
517 item.setFlags( status.statusFlags() );
518 new Akonadi::ItemCreateJob( item, mFolder );
523 delete mComposerBase;
527 void KMComposeWin::slotSpellCheckingLanguage(
const QString& language)
529 mComposerBase->editor()->setSpellCheckingLanguage(language );
530 mEdtSubject->setSpellCheckingLanguage(language );
535 return mdbusObjectPath;
538 void KMComposeWin::slotEditorTextChanged()
540 const bool textIsNotEmpty = !mComposerBase->editor()->document()->isEmpty();
541 mFindText->setEnabled( textIsNotEmpty );
542 mFindNextText->setEnabled( textIsNotEmpty );
543 mReplaceText->setEnabled( textIsNotEmpty );
544 mSelectAll->setEnabled( textIsNotEmpty );
566 kDebug() <<
"addAttachment and sending!";
567 const int nbUrl = urls.count();
568 for (
int i =0; i < nbUrl; ++i ) {
569 mComposerBase->addAttachmentUrlSync( urls[i], comment );
578 mComposerBase->addAttachment( url, comment );
583 KMime::Headers::contentEncoding cte,
584 const QString& charset,
585 const QByteArray& data,
586 const QByteArray& mimeType )
589 mComposerBase->addAttachment( name, name, charset, data, mimeType );
593 void KMComposeWin::readConfig(
bool reload )
596 if (mBtnIdentity->isChecked()) {
605 mEdtFrom->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
606 mComposerBase->recipientsEditor()->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
607 mEdtReplyTo->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
609 if ( MessageCore::GlobalSettings::self()->useDefaultFonts() ) {
610 mBodyFont = KGlobalSettings::generalFont();
611 mFixedFont = KGlobalSettings::fixedFont();
614 mFixedFont = MessageViewer::GlobalSettings::self()->fixedFont();
618 mEdtFrom->setFont( mBodyFont );
619 mEdtReplyTo->setFont( mBodyFont );
620 mEdtSubject->setFont( mBodyFont );
624 if ( siz.width() < 200 ) {
627 if ( siz.height() < 200 ) {
628 siz.setHeight( 200 );
636 defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
637 mSnippetSplitter->setSizes( defaults );
641 mComposerBase->identityCombo()->setCurrentIdentity( mId );
642 kDebug() << mComposerBase->identityCombo()->currentIdentityName();
643 const KPIMIdentities::Identity & ident =
644 kmkernel->identityManager()->identityForUoid( mId );
646 if ( mBtnTransport->isChecked() && currentTransport != -1 ) {
647 const Transport *transport = TransportManager::self()->transportById( currentTransport );
649 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
655 if ( mBtnDictionary->isChecked() ) {
658 mDictionaryCombo->setCurrentByDictionaryName( ident.dictionary() );
662 if ( mBtnFcc->isChecked() ) {
664 }
else if ( !ident.fcc().isEmpty() ) {
665 fccName = ident.fcc();
671 void KMComposeWin::writeConfig(
void )
675 if ( !mIgnoreStickyFields ) {
676 GlobalSettings::self()->setCurrentTransport( mComposerBase->transportComboBox()->currentText() );
680 GlobalSettings::self()->setPreviousIdentity( mComposerBase->identityCombo()->currentIdentity() );
685 mAutoSpellCheckingAction->isChecked() );
686 MessageViewer::GlobalSettings::self()->setUseFixedFont( mFixedFontAction->isChecked() );
687 if ( !mForceDisableHtml )
688 GlobalSettings::self()->setUseHtmlMarkup( mComposerBase->editor()->textMode() == KMeditor::Rich );
692 saveMainWindowSettings(
KMKernel::self()->config()->group(
"Composer" ) );
693 if ( mSnippetAction->isChecked() )
694 GlobalSettings::setSnippetSplitterPosition( mSnippetSplitter->sizes() );
700 MessageComposer::Composer* KMComposeWin::createSimpleComposer()
703 if( !mOriginalPreferredCharset.isEmpty() ) {
704 charsets.insert( 0, mOriginalPreferredCharset );
706 mComposerBase->setFrom( from() );
707 mComposerBase->setReplyTo( replyTo() );
708 mComposerBase->setSubject( subject() );
709 mComposerBase->setCharsets( charsets );
710 return mComposerBase->createSimpleComposer();
714 void KMComposeWin::slotView(
void )
723 KToggleAction *act = ::qobject_cast<KToggleAction *>( sender() );
729 if ( act == mAllFieldsAction ) {
731 }
else if ( act == mIdentityAction ) {
733 }
else if ( act == mTransportAction ) {
735 }
else if ( act == mFromAction ) {
737 }
else if ( act == mReplyToAction ) {
739 }
else if ( act == mSubjectAction ) {
741 }
else if ( act == mFccAction ) {
743 }
else if ( act == mDictionaryAction ) {
747 kDebug() <<
"Something is wrong (Oh, yeah?)";
754 if ( !act->isChecked() ) {
757 mShowHeaders = mShowHeaders & ~id;
759 mShowHeaders = abs( mShowHeaders );
766 mShowHeaders = -abs( mShowHeaders );
769 rethinkFields(
true );
772 int KMComposeWin::calcColumnWidth(
int which,
long allShowing,
int width )
const
774 if ( ( allShowing & which ) == 0 ) {
782 w = mDictionaryLabel;
783 }
else if ( which ==
HDR_FCC ) {
797 w->setBuddy( mComposerBase->editor() );
800 return qMax( width, w->sizeHint().width() );
803 void KMComposeWin::rethinkFields(
bool fromSlot )
809 if ( mShowHeaders < 0 ) {
812 showHeaders = mShowHeaders;
815 for ( mask=1, mNumHeaders=0; mask<=showHeaders; mask<<=1 ) {
816 if ( ( showHeaders & mask ) != 0 ) {
822 mGrid =
new QGridLayout( mHeadersArea );
823 mGrid->setSpacing( KDialog::spacingHint() );
824 mGrid->setMargin( KDialog::marginHint() / 2 );
825 mGrid->setColumnStretch( 0, 1 );
826 mGrid->setColumnStretch( 1, 100 );
827 mGrid->setColumnStretch( 2, 1 );
828 mGrid->setRowStretch( mNumHeaders + 1, 100 );
833 mLabelWidth = mComposerBase->recipientsEditor()->setFirstColumnWidth( 0 );
834 mLabelWidth = calcColumnWidth(
HDR_IDENTITY, showHeaders, mLabelWidth );
835 mLabelWidth = calcColumnWidth(
HDR_DICTIONARY, showHeaders, mLabelWidth );
836 mLabelWidth = calcColumnWidth(
HDR_FCC, showHeaders, mLabelWidth );
837 mLabelWidth = calcColumnWidth(
HDR_TRANSPORT, showHeaders, mLabelWidth );
838 mLabelWidth = calcColumnWidth(
HDR_FROM, showHeaders, mLabelWidth );
839 mLabelWidth = calcColumnWidth(
HDR_REPLY_TO, showHeaders, mLabelWidth );
840 mLabelWidth = calcColumnWidth(
HDR_SUBJECT, showHeaders, mLabelWidth );
843 mAllFieldsAction->setChecked( showHeaders ==
HDR_ALL );
847 mIdentityAction->setChecked( abs( mShowHeaders )&
HDR_IDENTITY );
849 rethinkHeaderLine( showHeaders,
HDR_IDENTITY, row, mLblIdentity, mComposerBase->identityCombo(),
853 mDictionaryAction->setChecked( abs( mShowHeaders )&
HDR_DICTIONARY );
855 rethinkHeaderLine( showHeaders,
HDR_DICTIONARY, row, mDictionaryLabel,
856 mDictionaryCombo, mBtnDictionary );
859 mFccAction->setChecked( abs( mShowHeaders )&
HDR_FCC );
861 rethinkHeaderLine( showHeaders,
HDR_FCC, row, mLblFcc, mFccFolder, mBtnFcc );
864 mTransportAction->setChecked( abs( mShowHeaders )&
HDR_TRANSPORT );
866 rethinkHeaderLine( showHeaders,
HDR_TRANSPORT, row, mLblTransport, mComposerBase->transportComboBox(),
870 mFromAction->setChecked( abs( mShowHeaders )&
HDR_FROM );
872 rethinkHeaderLine( showHeaders,
HDR_FROM, row, mLblFrom, mEdtFrom );
877 mReplyToAction->setChecked( abs( mShowHeaders )&
HDR_REPLY_TO );
879 rethinkHeaderLine( showHeaders,
HDR_REPLY_TO, row, mLblReplyTo, mEdtReplyTo );
881 prevFocus = connectFocusMoving( prevFocus, mEdtReplyTo );
884 mGrid->addWidget( mComposerBase->recipientsEditor(), row, 0, 1, 3 );
886 if ( showHeaders & HDR_REPLY_TO ) {
887 connect( mEdtReplyTo, SIGNAL(focusDown()), mComposerBase->recipientsEditor(),
888 SLOT(setFocusTop()) );
889 connect( mComposerBase->recipientsEditor(), SIGNAL(focusUp()), mEdtReplyTo,
892 connect( mEdtFrom, SIGNAL(focusDown()), mComposerBase->recipientsEditor(),
893 SLOT(setFocusTop()) );
894 connect( mComposerBase->recipientsEditor(), SIGNAL(focusUp()), mEdtFrom,
898 connect( mComposerBase->recipientsEditor(), SIGNAL(focusDown()), mEdtSubject,
900 connect( mEdtSubject, SIGNAL(focusUp()), mComposerBase->recipientsEditor(),
901 SLOT(setFocusBottom()) );
903 prevFocus = mComposerBase->recipientsEditor();
906 mSubjectAction->setChecked( abs( mShowHeaders )&
HDR_SUBJECT );
908 rethinkHeaderLine(showHeaders,
HDR_SUBJECT, row, mLblSubject, mEdtSubject );
909 connectFocusMoving( mEdtSubject, mComposerBase->editor() );
911 assert( row <= mNumHeaders + 1 );
914 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
916 mIdentityAction->setEnabled(!mAllFieldsAction->isChecked());
917 mDictionaryAction->setEnabled( !mAllFieldsAction->isChecked() );
918 mTransportAction->setEnabled(!mAllFieldsAction->isChecked());
919 mFromAction->setEnabled(!mAllFieldsAction->isChecked());
920 if ( mReplyToAction ) {
921 mReplyToAction->setEnabled( !mAllFieldsAction->isChecked() );
923 mFccAction->setEnabled( !mAllFieldsAction->isChecked() );
924 mSubjectAction->setEnabled( !mAllFieldsAction->isChecked() );
925 mComposerBase->recipientsEditor()->setFirstColumnWidth( mLabelWidth );
930 connect( prev, SIGNAL(focusDown()), next, SLOT(setFocus()) );
931 connect( next, SIGNAL(focusUp()), prev, SLOT(setFocus()) );
937 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int &aRow,
941 if ( aValue & aMask ) {
942 aLbl->setFixedWidth( mLabelWidth );
943 aLbl->setBuddy( aEdt );
944 mGrid->addWidget( aLbl, aRow, 0 );
948 mGrid->addWidget( aEdt, aRow, 1 );
949 mGrid->addWidget( aBtn, aRow, 2 );
952 mGrid->addWidget( aEdt, aRow, 1, 1, 2 );
965 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int &aRow,
969 if ( aValue & aMask ) {
970 aLbl->setBuddy( aCbx );
971 mGrid->addWidget( aLbl, aRow, 0 );
973 mGrid->addWidget( aCbx, aRow, 1 );
976 mGrid->addWidget( aChk, aRow, 2 );
990 void KMComposeWin::applyTemplate( uint uoid, uint uOldId )
992 const KPIMIdentities::Identity &ident =
kmkernel->identityManager()->identityForUoid( uoid );
993 if ( ident.isNull() )
995 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-Templates", mMsg.get(), ident.templates(),
"utf-8" );
996 mMsg->setHeader( header );
998 TemplateParser::TemplateParser::Mode mode;
999 switch ( mContext ) {
1001 mode = TemplateParser::TemplateParser::NewMessage;
1004 mode = TemplateParser::TemplateParser::Reply;
1007 mode = TemplateParser::TemplateParser::ReplyAll;
1010 mode = TemplateParser::TemplateParser::Forward;
1016 if ( mode == TemplateParser::TemplateParser::NewMessage ) {
1017 TemplateParser::TemplateParser parser( mMsg, mode );
1018 parser.setSelection( mTextSelection );
1019 parser.setAllowDecryption( MessageViewer::GlobalSettings::self()->automaticDecrypt() );
1020 parser.setIdentityManager(
KMKernel::self()->identityManager() );
1021 if ( !mCustomTemplate.isEmpty() )
1022 parser.process( mCustomTemplate, mMsg, mCollectionForNewMessage );
1024 parser.processWithIdentity( uoid, mMsg, mCollectionForNewMessage );
1025 mComposerBase->updateTemplate( mMsg );
1026 updateSignature(uoid, uOldId);
1030 if ( mMsg->headerByType(
"X-KMail-Link-Message" ) ) {
1031 Akonadi::Item::List items;
1032 foreach(
const QString& serNumStr, mMsg->headerByType(
"X-KMail-Link-Message" )->asUnicodeString().split( QLatin1Char(
',') ) )
1033 items << Akonadi::Item( serNumStr.toLongLong() );
1036 Akonadi::ItemFetchJob *job =
new Akonadi::ItemFetchJob( items,
this );
1037 job->fetchScope().fetchFullPayload(
true );
1038 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
1039 job->setProperty(
"mode", (
int)mode );
1040 job->setProperty(
"uoid", uoid );
1041 job->setProperty(
"uOldid", uOldId );
1042 connect( job, SIGNAL(result(
KJob*)), SLOT(slotDelayedApplyTemplate(
KJob*)) );
1046 void KMComposeWin::slotDelayedApplyTemplate(
KJob *job )
1048 const Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job );
1049 const Akonadi::Item::List items = fetchJob->items();
1051 const TemplateParser::TemplateParser::Mode mode =
static_cast<TemplateParser::TemplateParser::Mode
>( fetchJob->property(
"mode" ).toInt() );
1052 const uint uoid = fetchJob->property(
"uoid" ).toUInt();
1053 const uint uOldId = fetchJob->property(
"uOldid" ).toUInt();
1055 TemplateParser::TemplateParser parser( mMsg, mode );
1056 parser.setSelection( mTextSelection );
1057 parser.setAllowDecryption( MessageViewer::GlobalSettings::self()->automaticDecrypt() );
1058 parser.setWordWrap( MessageComposer::MessageComposerSettings::self()->wordWrap(), MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
1059 parser.setIdentityManager(
KMKernel::self()->identityManager() );
1060 foreach (
const Akonadi::Item &item, items ) {
1061 if ( !mCustomTemplate.isEmpty() )
1062 parser.process( mCustomTemplate, MessageCore::Util::message( item ) );
1064 parser.processWithIdentity( uoid, MessageCore::Util::message( item ) );
1066 mComposerBase->updateTemplate( mMsg );
1067 updateSignature(uoid, uOldId);
1070 void KMComposeWin::updateSignature(uint uoid, uint uOldId)
1072 const KPIMIdentities::Identity &ident =
kmkernel->identityManager()->identityForUoid( uoid );
1073 const KPIMIdentities::Identity &oldIdentity =
kmkernel->identityManager()->identityForUoid( uOldId );
1074 mComposerBase->identityChanged( ident, oldIdentity,
true );
1079 mCollectionForNewMessage = folder;
1082 void KMComposeWin::setQuotePrefix( uint uoid )
1084 QString quotePrefix = mMsg->headerByType(
"X-KMail-QuotePrefix" ) ? mMsg->headerByType(
"X-KMail-QuotePrefix" )->asUnicodeString() : QString();
1085 if ( quotePrefix.isEmpty() ) {
1089 if ( mCustomTemplate.isEmpty() ) {
1090 const KPIMIdentities::Identity &identity =
kmkernel->identityManager()->identityForUoidOrDefault( uoid );
1093 TemplateParser::Templates quoteTemplate(
1094 TemplateParser::TemplatesConfiguration::configIdString( identity.uoid() ) );
1095 quotePrefix = quoteTemplate.quoteString();
1098 mComposerBase->editor()->setQuotePrefixName( MessageCore::StringUtil::formatString( quotePrefix,
1099 mMsg->from()->asUnicodeString() ) );
1103 void KMComposeWin::getTransportMenu()
1105 mActNowMenu->clear();
1106 mActLaterMenu->clear();
1109 foreach ( Transport *transport, transports ) {
1110 const QString name = transport->name().replace( QLatin1Char(
'&'), QLatin1String(
"&&") );
1111 QAction *action1 =
new QAction( name, mActNowMenu );
1112 QAction *action2 =
new QAction( name, mActLaterMenu );
1113 action1->setData( transport->id() );
1114 action2->setData( transport->id() );
1115 mActNowMenu->addAction( action1 );
1116 mActLaterMenu->addAction( action2 );
1121 void KMComposeWin::setupActions(
void )
1123 KActionMenu *actActionNowMenu, *actActionLaterMenu;
1125 if ( MessageComposer::MessageComposerSettings::self()->sendImmediate() ) {
1127 KAction *action =
new KAction(KIcon(QLatin1String(
"mail-send")), i18n(
"&Send Mail"),
this);
1128 actionCollection()->addAction(QLatin1String(
"send_default"), action );
1129 action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Return ) );
1130 connect( action, SIGNAL(triggered(
bool)), SLOT(
slotSendNow()));
1133 actActionNowMenu =
new KActionMenu( KIcon( QLatin1String(
"mail-send") ), i18n(
"&Send Mail Via"),
this );
1134 actActionNowMenu->setIconText( i18n(
"Send" ) );
1135 actionCollection()->addAction( QLatin1String(
"send_default_via"), actActionNowMenu );
1137 action =
new KAction( KIcon( QLatin1String(
"mail-queue") ), i18n(
"Send &Later"),
this );
1138 actionCollection()->addAction( QLatin1String(
"send_alternative"), action );
1139 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSendLater()) );
1140 actActionLaterMenu =
new KActionMenu( KIcon( QLatin1String(
"mail-queue") ), i18n(
"Send &Later Via"),
this );
1141 actActionLaterMenu->setIconText( i18nc(
"Queue the message for sending at a later date",
"Queue" ) );
1142 actionCollection()->addAction( QLatin1String(
"send_alternative_via"), actActionLaterMenu );
1146 KAction *action =
new KAction( KIcon( QLatin1String(
"mail-queue") ), i18n(
"Send &Later"),
this );
1147 actionCollection()->addAction( QLatin1String(
"send_default"), action );
1148 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSendLater()) );
1149 action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Return ) );
1150 actActionLaterMenu =
new KActionMenu( KIcon( QLatin1String(
"mail-queue") ), i18n(
"Send &Later Via"),
this );
1151 actionCollection()->addAction( QLatin1String(
"send_default_via"), actActionLaterMenu );
1153 action =
new KAction( KIcon( QLatin1String(
"mail-send") ), i18n(
"&Send Mail"),
this );
1154 actionCollection()->addAction( QLatin1String(
"send_alternative"), action );
1155 connect( action, SIGNAL(triggered(
bool)), SLOT(
slotSendNow()) );
1158 actActionNowMenu =
new KActionMenu( KIcon( QLatin1String(
"mail-send") ), i18n(
"&Send Mail Via"),
this );
1159 actionCollection()->addAction( QLatin1String(
"send_alternative_via"), actActionNowMenu );
1164 actActionNowMenu->setDelayed(
true );
1165 actActionLaterMenu->setDelayed(
true );
1167 connect( actActionNowMenu, SIGNAL(triggered(
bool)),
this,
1169 connect( actActionLaterMenu, SIGNAL(triggered(
bool)),
this,
1170 SLOT(slotSendLater()) );
1172 mActNowMenu = actActionNowMenu->menu();
1173 mActLaterMenu = actActionLaterMenu->menu();
1175 connect( mActNowMenu, SIGNAL(triggered(QAction*)),
this,
1176 SLOT(slotSendNowVia(QAction*)) );
1177 connect( mActNowMenu, SIGNAL(aboutToShow()),
this,
1178 SLOT(getTransportMenu()) );
1180 connect( mActLaterMenu, SIGNAL(triggered(QAction*)),
this,
1181 SLOT(slotSendLaterVia(QAction*)) );
1182 connect( mActLaterMenu, SIGNAL(aboutToShow()),
this,
1183 SLOT(getTransportMenu()) );
1185 KAction *action =
new KAction( KIcon( QLatin1String(
"document-save") ), i18n(
"Save as &Draft"),
this );
1186 actionCollection()->addAction(QLatin1String(
"save_in_drafts"), action );
1187 action->setHelpText(i18n(
"Save email in Draft folder"));
1188 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
1189 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveDraft()) );
1191 action =
new KAction( KIcon( QLatin1String(
"document-save") ), i18n(
"Save as &Template"),
this );
1192 action->setHelpText(i18n(
"Save email in Template folder"));
1193 actionCollection()->addAction( QLatin1String(
"save_in_templates"), action );
1194 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveTemplate()) );
1196 action =
new KAction( KIcon( QLatin1String(
"document-save") ), i18n(
"Save as &File"),
this );
1197 action->setHelpText(i18n(
"Save email as text or html file"));
1198 actionCollection()->addAction( QLatin1String(
"save_as_file"), action );
1199 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveAsFile()) );
1201 action =
new KAction(KIcon( QLatin1String(
"contact-new" ) ), i18n(
"New AddressBook Contact..."),
this);
1202 actionCollection()->addAction(QLatin1String(
"kmail_new_addressbook_contact"), action );
1203 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(slotCreateAddressBookContact()));
1207 action =
new KAction(KIcon(QLatin1String(
"document-open")), i18n(
"&Insert Text File..."),
this);
1208 actionCollection()->addAction(QLatin1String(
"insert_file"), action );
1209 connect(action, SIGNAL(triggered(
bool)), SLOT(slotInsertFile()));
1211 mRecentAction =
new KRecentFilesAction( KIcon( QLatin1String(
"document-open") ),
1212 i18n(
"&Insert Recent Text File" ),
this );
1213 actionCollection()->addAction(QLatin1String(
"insert_file_recent"), mRecentAction );
1214 connect(mRecentAction, SIGNAL(urlSelected(KUrl)),
1215 SLOT(slotInsertRecentFile(KUrl)));
1216 connect(mRecentAction, SIGNAL(recentListCleared()),
1217 SLOT(slotRecentListFileClear()));
1218 mRecentAction->loadEntries(
KMKernel::self()->config()->group( QString() ) );
1220 action =
new KAction(KIcon(QLatin1String(
"x-office-address-book")), i18n(
"&Address Book"),
this);
1221 action->setHelpText(i18n(
"Open Address Book"));
1222 actionCollection()->addAction(QLatin1String(
"addressbook"), action );
1223 if (KStandardDirs::findExe(QLatin1String(
"kaddressbook")).isEmpty())
1224 action->setEnabled(
false);
1225 connect(action, SIGNAL(triggered(
bool)), SLOT(slotAddrBook()));
1226 action =
new KAction(KIcon(QLatin1String(
"mail-message-new")), i18n(
"&New Composer"),
this);
1227 actionCollection()->addAction(QLatin1String(
"new_composer"), action );
1228 connect(action, SIGNAL(triggered(
bool)), SLOT(slotNewComposer()));
1229 action->setShortcuts( KStandardShortcut::shortcut( KStandardShortcut::New ) );
1230 action =
new KAction( KIcon( QLatin1String(
"window-new") ), i18n(
"New Main &Window"),
this );
1231 actionCollection()->addAction( QLatin1String(
"open_mailreader"), action );
1232 connect( action, SIGNAL(triggered(
bool)), SLOT(slotNewMailReader()) );
1234 action =
new KAction( i18n(
"Select &Recipients..."),
this );
1235 actionCollection()->addAction( QLatin1String(
"select_recipients"), action );
1236 connect( action, SIGNAL(triggered(
bool)),
1237 mComposerBase->recipientsEditor(), SLOT(selectRecipients()) );
1238 action =
new KAction( i18n(
"Save &Distribution List..."),
this );
1239 actionCollection()->addAction( QLatin1String(
"save_distribution_list"), action );
1240 connect( action, SIGNAL(triggered(
bool)),
1241 mComposerBase->recipientsEditor(), SLOT(saveDistributionList()) );
1243 KStandardAction::print(
this, SLOT(slotPrint()), actionCollection() );
1244 if(KPrintPreview::isAvailable())
1245 KStandardAction::printPreview(
this, SLOT(slotPrintPreview()), actionCollection() );
1246 KStandardAction::close(
this, SLOT(slotClose()), actionCollection() );
1248 KStandardAction::undo(
this, SLOT(slotUndo()), actionCollection() );
1249 KStandardAction::redo(
this, SLOT(slotRedo()), actionCollection() );
1250 KStandardAction::cut(
this, SLOT(slotCut()), actionCollection() );
1251 KStandardAction::copy(
this, SLOT(slotCopy()), actionCollection() );
1252 KStandardAction::pasteText(
this, SLOT(slotPaste()), actionCollection() );
1253 mSelectAll = KStandardAction::selectAll(
this, SLOT(slotMarkAll()), actionCollection() );
1255 mFindText = KStandardAction::find( mComposerBase->editor(), SLOT(slotFind()), actionCollection() );
1256 mFindNextText = KStandardAction::findNext( mComposerBase->editor(), SLOT(slotFindNext()), actionCollection() );
1258 mReplaceText = KStandardAction::replace( mComposerBase->editor(), SLOT(slotReplace()), actionCollection() );
1259 actionCollection()->addAction( KStandardAction::Spelling, QLatin1String(
"spellcheck"),
1260 mComposerBase->editor(), SLOT(checkSpelling()) );
1262 action =
new KAction( i18n(
"Paste as Attac&hment"),
this );
1263 actionCollection()->addAction( QLatin1String(
"paste_att"), action );
1264 connect( action, SIGNAL(triggered(
bool)), SLOT(slotPasteAsAttachment()) );
1266 action =
new KAction( i18n(
"Cl&ean Spaces"),
this );
1267 actionCollection()->addAction( QLatin1String(
"clean_spaces"), action );
1268 connect( action, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(cleanSpace()) );
1270 mFixedFontAction =
new KToggleAction( i18n(
"Use Fi&xed Font"),
this );
1271 actionCollection()->addAction( QLatin1String(
"toggle_fixedfont"), mFixedFontAction );
1272 connect( mFixedFontAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateFont()) );
1273 mFixedFontAction->setChecked( MessageViewer::GlobalSettings::self()->useFixedFont() );
1276 mUrgentAction =
new KToggleAction(
1277 i18nc(
"@action:inmenu Mark the email as urgent.",
"&Urgent"),
this );
1278 actionCollection()->addAction( QLatin1String(
"urgent"), mUrgentAction );
1279 mRequestMDNAction =
new KToggleAction( i18n(
"&Request Disposition Notification"),
this );
1280 actionCollection()->addAction(QLatin1String(
"options_request_mdn"), mRequestMDNAction );
1284 actionCollection()->addAction( QLatin1String(
"charsets"), mCodecAction );
1285 mWordWrapAction =
new KToggleAction( i18n(
"&Wordwrap" ),
this );
1286 actionCollection()->addAction( QLatin1String(
"wordwrap"), mWordWrapAction );
1287 mWordWrapAction->setChecked( MessageComposer::MessageComposerSettings::self()->wordWrap() );
1290 mSnippetAction =
new KToggleAction( i18n(
"&Snippets"),
this );
1291 actionCollection()->addAction( QLatin1String(
"snippets"), mSnippetAction );
1292 connect( mSnippetAction, SIGNAL(toggled(
bool)),
1293 mSnippetWidget, SLOT(setVisible(
bool)) );
1296 mAutoSpellCheckingAction =
new KToggleAction( KIcon( QLatin1String(
"tools-check-spelling") ),
1297 i18n(
"&Automatic Spellchecking"),
1299 actionCollection()->addAction( QLatin1String(
"options_auto_spellchecking"), mAutoSpellCheckingAction );
1302 const bool spellCheckingEnabled = useKmailEditor && spellChecking;
1303 mAutoSpellCheckingAction->setEnabled( useKmailEditor );
1305 mAutoSpellCheckingAction->setChecked( spellCheckingEnabled );
1306 slotAutoSpellCheckingToggled( spellCheckingEnabled );
1307 connect( mAutoSpellCheckingAction, SIGNAL(toggled(
bool)),
1308 this, SLOT(slotAutoSpellCheckingToggled(
bool)) );
1309 connect( mComposerBase->editor(), SIGNAL(checkSpellingChanged(
bool)),
1310 this, SLOT(slotAutoSpellCheckingToggled(
bool)) );
1312 connect( mComposerBase->editor(), SIGNAL(textModeChanged(KRichTextEdit::Mode)),
1314 connect( mComposerBase->editor(), SIGNAL(externalEditorClosed()),
this, SLOT(slotExternalEditorClosed()));
1315 connect( mComposerBase->editor(), SIGNAL(externalEditorStarted()),
this, SLOT(slotExternalEditorStarted()));
1317 markupAction =
new KToggleAction( i18n(
"Rich Text Editing"),
this );
1318 markupAction->setIcon( KIcon( QLatin1String(
"preferences-desktop-font" )) );
1319 markupAction->setIconText( i18n(
"Rich Text") );
1320 markupAction->setToolTip( i18n(
"Toggle rich text editing mode" ) );
1321 actionCollection()->addAction( QLatin1String(
"html"), markupAction );
1322 connect( markupAction, SIGNAL(triggered(
bool)), SLOT(
slotToggleMarkup()) );
1324 mAllFieldsAction =
new KToggleAction( i18n(
"&All Fields"),
this);
1325 actionCollection()->addAction( QLatin1String(
"show_all_fields"), mAllFieldsAction );
1326 connect( mAllFieldsAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1327 mIdentityAction =
new KToggleAction(i18n(
"&Identity"),
this);
1328 actionCollection()->addAction(QLatin1String(
"show_identity"), mIdentityAction );
1329 connect( mIdentityAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1330 mDictionaryAction =
new KToggleAction(i18n(
"&Dictionary"),
this);
1331 actionCollection()->addAction(QLatin1String(
"show_dictionary"), mDictionaryAction );
1332 connect( mDictionaryAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1333 mFccAction =
new KToggleAction(i18n(
"&Sent-Mail Folder"),
this);
1334 actionCollection()->addAction(QLatin1String(
"show_fcc"), mFccAction );
1335 connect( mFccAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1336 mTransportAction =
new KToggleAction(i18n(
"&Mail Transport"),
this);
1337 actionCollection()->addAction(QLatin1String(
"show_transport"), mTransportAction );
1338 connect( mTransportAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1339 mFromAction =
new KToggleAction(i18n(
"&From"),
this);
1340 actionCollection()->addAction(QLatin1String(
"show_from"), mFromAction );
1341 connect( mFromAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1342 mReplyToAction =
new KToggleAction(i18n(
"&Reply To"),
this);
1343 actionCollection()->addAction(QLatin1String(
"show_reply_to"), mReplyToAction );
1344 connect( mReplyToAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1345 mSubjectAction =
new KToggleAction(
1346 i18nc(
"@action:inmenu Show the subject in the composer window.",
"S&ubject"),
this);
1347 actionCollection()->addAction(QLatin1String(
"show_subject"), mSubjectAction );
1348 connect(mSubjectAction, SIGNAL(triggered(
bool)), SLOT(slotView()));
1351 action =
new KAction( i18n(
"Append S&ignature"),
this );
1352 actionCollection()->addAction( QLatin1String(
"append_signature"), action );
1353 connect( action, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(appendSignature()));
1354 action =
new KAction( i18n(
"Pr&epend Signature"),
this );
1355 actionCollection()->addAction( QLatin1String(
"prepend_signature"), action );
1356 connect( action, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(prependSignature()) );
1357 action =
new KAction( i18n(
"Insert Signature At C&ursor Position"),
this );
1358 actionCollection()->addAction( QLatin1String(
"insert_signature_at_cursor_position"), action );
1359 connect( action, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(insertSignatureAtCursor()) );
1362 action =
new KAction( i18n(
"Insert Special Character..."),
this );
1363 actionCollection()->addAction( QLatin1String(
"insert_special_character"), action );
1364 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(insertSpecialCharacter()) );
1366 mUpperCase =
new KAction( i18n(
"Uppercase"),
this );
1367 actionCollection()->addAction( QLatin1String(
"change_to_uppercase"), mUpperCase );
1368 connect( mUpperCase, SIGNAL(triggered(
bool)),
this, SLOT(slotUpperCase()) );
1370 mLowerCase =
new KAction( i18n(
"Lowercase"),
this );
1371 actionCollection()->addAction( QLatin1String(
"change_to_lowercase"), mLowerCase );
1372 connect( mLowerCase, SIGNAL(triggered(
bool)),
this, SLOT(slotLowerCase()) );
1374 mComposerBase->attachmentController()->createActions();
1376 setStandardToolBarMenuEnabled(
true );
1378 KStandardAction::keyBindings(
this, SLOT(slotEditKeys()), actionCollection());
1379 KStandardAction::configureToolbars(
this, SLOT(slotEditToolbars()), actionCollection());
1380 KStandardAction::preferences(
kmkernel, SLOT(slotShowConfigurationDialog()), actionCollection() );
1382 action =
new KAction( i18n(
"&Spellchecker..."),
this );
1383 action->setIconText( i18n(
"Spellchecker") );
1384 actionCollection()->addAction( QLatin1String(
"setup_spellchecker"), action );
1385 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSpellcheckConfig()) );
1387 mTranslateAction =
new KToggleAction( i18n(
"&Translator"),
this );
1388 action->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_T ) );
1389 actionCollection()->addAction( QLatin1String(
"translator"), mTranslateAction );
1390 mTranslateAction->setChecked(
false);
1391 connect(mTranslateAction, SIGNAL(triggered(
bool)), mTranslatorWidget,SLOT(setVisible(
bool)));
1395 if ( Kleo::CryptoBackendFactory::instance()->protocol( QLatin1String(
"Chiasmus") ) ) {
1396 KToggleAction *a =
new KToggleAction( KIcon(
"chiasmus_chi" ), i18n(
"Encrypt Message with Chiasmus..."),
this );
1397 actionCollection()->addAction(
"encrypt_message_chiasmus", a );
1398 a->setCheckedState( KGuiItem( i18n(
"Encrypt Message with Chiasmus..." ),
"chiencrypted" ) );
1399 mEncryptChiasmusAction = a;
1400 connect( mEncryptChiasmusAction, SIGNAL(toggled(
bool)),
1401 this, SLOT(slotEncryptChiasmusToggled(
bool)) );
1403 mEncryptChiasmusAction = 0;
1407 mEncryptAction =
new KToggleAction(KIcon(QLatin1String(
"document-encrypt")), i18n(
"&Encrypt Message"),
this);
1408 mEncryptAction->setIconText( i18n(
"Encrypt" ) );
1409 actionCollection()->addAction(QLatin1String(
"encrypt_message"), mEncryptAction );
1410 mSignAction =
new KToggleAction(KIcon(QLatin1String(
"document-sign")), i18n(
"&Sign Message"),
this);
1411 mSignAction->setIconText( i18n(
"Sign" ) );
1412 actionCollection()->addAction(QLatin1String(
"sign_message"), mSignAction );
1413 const KPIMIdentities::Identity &ident =
1417 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1418 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1420 mLastEncryptActionState =
false;
1421 mLastSignActionState = ident.pgpAutoSign();
1423 changeCryptoAction();
1425 connect( mEncryptAction, SIGNAL(triggered(
bool)),
1426 SLOT(slotEncryptToggled(
bool)) );
1427 connect( mSignAction, SIGNAL(triggered(
bool)),
1428 SLOT(slotSignToggled(
bool)) );
1431 for (
int i=0 ; i<numCryptoMessageFormats ; ++i ) {
1432 l.push_back( Kleo::cryptoMessageFormatToLabel( cryptoMessageFormats[i] ) );
1435 mCryptoModuleAction =
new KSelectAction(i18n(
"&Cryptographic Message Format"),
this);
1436 actionCollection()->addAction(QLatin1String(
"options_select_crypto"), mCryptoModuleAction );
1437 connect(mCryptoModuleAction, SIGNAL(triggered(
int)), SLOT(slotSelectCryptoModule()));
1438 mCryptoModuleAction->setItems( l );
1439 mCryptoModuleAction->setToolTip( i18n(
"Select a cryptographic format for this message" ) );
1441 mComposerBase->editor()->createActions( actionCollection() );
1443 createGUI( QLatin1String(
"kmcomposerui.rc") );
1444 connect( toolBar( QLatin1String(
"htmlToolBar") )->toggleViewAction(),
1445 SIGNAL(toggled(
bool)),
1451 QAction *configureAction = actionCollection()->action( QLatin1String(
"options_configure") );
1452 if ( configureAction ) {
1453 configureAction->setText( i18n(
"Configure KMail..." ) );
1457 void KMComposeWin::changeCryptoAction()
1459 const KPIMIdentities::Identity &ident =
1461 if ( !Kleo::CryptoBackendFactory::instance()->openpgp() && !Kleo::CryptoBackendFactory::instance()->smime() ) {
1463 mEncryptAction->setEnabled(
false );
1464 setEncryption(
false );
1465 mSignAction->setEnabled(
false );
1466 setSigning(
false );
1468 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp() &&
1469 !ident.pgpSigningKey().isEmpty();
1470 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime() &&
1471 !ident.smimeSigningKey().isEmpty();
1473 setEncryption(
false );
1474 setSigning( ( canOpenPGPSign || canSMIMESign ) && ident.pgpAutoSign() );
1480 void KMComposeWin::setupStatusBar(
QWidget *w )
1482 statusBar()->addWidget(w);
1483 statusBar()->insertItem( QString(), 0, 1 );
1484 statusBar()->setItemAlignment( 0, Qt::AlignLeft | Qt::AlignVCenter );
1485 statusBar()->insertPermanentItem( overwriteModeStr(), 4,0 );
1487 statusBar()->insertPermanentItem( i18n(
" Spellcheck: %1 ", QLatin1String(
" " )), 3, 0) ;
1488 statusBar()->insertPermanentItem( i18n(
" Column: %1 ", QLatin1String(
" " ) ), 2, 0 );
1489 statusBar()->insertPermanentItem(
1490 i18nc(
"Shows the linenumber of the cursor position.",
" Line: %1 "
1491 , QLatin1String(
" " ) ), 1, 0 );
1495 void KMComposeWin::setupEditor(
void )
1497 QFontMetrics fm( mBodyFont );
1498 mComposerBase->editor()->setTabStopWidth( fm.width( QLatin1Char(
' ') ) * 8 );
1505 connect( mComposerBase->editor(), SIGNAL(cursorPositionChanged()),
1506 this, SLOT(slotCursorPositionChanged()) );
1507 slotCursorPositionChanged();
1511 QString KMComposeWin::subject()
const
1513 return MessageComposer::Util::cleanedUpHeaderString( mEdtSubject->toPlainText() );
1517 QString KMComposeWin::from()
const
1519 return MessageComposer::Util::cleanedUpHeaderString( mEdtFrom->text() );
1523 QString KMComposeWin::replyTo()
const
1525 if ( mEdtReplyTo ) {
1526 return MessageComposer::Util::cleanedUpHeaderString( mEdtReplyTo->text() );
1533 void KMComposeWin::decryptOrStripOffCleartextSignature( QByteArray &body )
1537 if ( Kpgp::Module::prepareMessageForDecryption( body,
1538 pgpBlocks, nonPgpBlocks ) ) {
1541 if ( pgpBlocks.count() == 1 ) {
1542 Kpgp::Block &block = pgpBlocks.first();
1543 if ( ( block.type() == Kpgp::PgpMessageBlock ) ||
1544 ( block.type() == Kpgp::ClearsignedBlock ) ) {
1545 if ( block.type() == Kpgp::PgpMessageBlock ) {
1552 body = nonPgpBlocks.first();
1553 body.append( block.text() );
1554 body.append( nonPgpBlocks.last() );
1562 mComposerBase->transportComboBox()->setCurrentTransport( transportId );
1567 if ( mEdtReplyTo ) {
1568 mEdtReplyTo->setText( replyTo );
1574 bool allowDecryption,
bool isModified )
1577 kDebug() <<
"newMsg == 0!";
1582 mLastSignActionState =
true;
1584 if ( lastEncryptState )
1585 mLastEncryptActionState =
true;
1587 mComposerBase->setMessage( newMsg );
1591 mEdtFrom->setText( mMsg->from()->asUnicodeString() );
1592 mEdtSubject->setText( mMsg->subject()->asUnicodeString() );
1598 if ( mMsg->headerByType(
"X-KMail-QuotePrefix" ) )
1599 mComposerBase->editor()->setQuotePrefixName( mMsg->headerByType(
"X-KMail-QuotePrefix" )->asUnicodeString() );
1601 const bool stickyIdentity = mBtnIdentity->isChecked() && !mIgnoreStickyFields;
1602 bool messageHasIdentity =
false;
1603 if( newMsg->headerByType(
"X-KMail-Identity") &&
1604 !newMsg->headerByType(
"X-KMail-Identity")->asUnicodeString().isEmpty() )
1605 messageHasIdentity =
true;
1606 if ( !stickyIdentity && messageHasIdentity )
1607 mId = newMsg->headerByType(
"X-KMail-Identity" )->asUnicodeString().toUInt();
1611 if ( !stickyIdentity ) {
1612 disconnect( mComposerBase->identityCombo(),SIGNAL(
identityChanged(uint)),
1613 this, SLOT(slotIdentityChanged(uint)) ) ;
1617 mComposerBase->identityCombo()->setCurrentIdentity( mId );
1618 const uint idToApply = mId;
1619 if ( !stickyIdentity ) {
1620 connect( mComposerBase->identityCombo(),SIGNAL(
identityChanged(uint)),
1621 this, SLOT(slotIdentityChanged(uint)) );
1626 if ( messageHasIdentity ) {
1627 mId = newMsg->headerByType(
"X-KMail-Identity")->asUnicodeString().toUInt();
1629 mId = im->defaultIdentity().uoid();
1636 slotIdentityChanged( idToApply,
true );
1638 const KPIMIdentities::Identity &ident = im->identityForUoid( mComposerBase->identityCombo()->currentIdentity() );
1640 const bool stickyTransport = mBtnTransport->isChecked() && !mIgnoreStickyFields;
1641 if( stickyTransport ) {
1642 mComposerBase->transportComboBox()->setCurrentTransport( ident.transport().toInt() );
1649 if( newMsg->headerByType(
"Disposition-Notification-To" ) ) {
1650 QString mdnAddr = newMsg->headerByType(
"Disposition-Notification-To" )->asUnicodeString();
1651 mRequestMDNAction->setChecked( ( !mdnAddr.isEmpty() &&
1652 im->thatIsMe( mdnAddr ) ) ||
1656 if ( newMsg->headerByType(
"X-PRIORITY" ) && newMsg->headerByType(
"Priority" ) )
1658 const QString xpriority = newMsg->headerByType(
"X-PRIORITY" )->asUnicodeString();
1659 const QString priority = newMsg->headerByType(
"Priority" )->asUnicodeString();
1660 if ( xpriority == QLatin1String(
"2 (High)" ) && priority == QLatin1String(
"urgent" ) )
1661 mUrgentAction->setChecked(
true );
1664 if ( !ident.isXFaceEnabled() || ident.xface().isEmpty() ) {
1665 if( mMsg->headerByType(
"X-Face" ) )
1666 mMsg->headerByType(
"X-Face" )->clear();
1668 QString xface = ident.xface();
1669 if ( !xface.isEmpty() ) {
1670 int numNL = ( xface.length() - 1 ) / 70;
1671 for (
int i = numNL; i > 0; --i ) {
1672 xface.insert( i * 70, QLatin1String(
"\n\t") );
1674 mMsg->setHeader(
new KMime::Headers::Generic(
"X-Face", mMsg.get(), xface,
"utf-8" ) );
1679 if ( mMsg->headerByType(
"X-KMail-SignatureActionEnabled" ) )
1680 mLastSignActionState = (mMsg->headerByType(
"X-KMail-SignatureActionEnabled" )->as7BitString().contains(
"true" ));
1681 if ( mMsg->headerByType(
"X-KMail-EncryptActionEnabled" ) )
1682 mLastEncryptActionState = (mMsg->headerByType(
"X-KMail-EncryptActionEnabled" )->as7BitString().contains(
"true") );
1683 if ( mMsg->headerByType(
"X-KMail-CryptoMessageFormat" ) ) {
1684 mCryptoModuleAction->setCurrentItem( format2cb( static_cast<Kleo::CryptoMessageFormat>(
1685 mMsg->headerByType(
"X-KMail-CryptoMessageFormat" )->asUnicodeString().toInt() ) ) );
1688 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1689 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1691 if ( Kleo::CryptoBackendFactory::instance()->openpgp() || Kleo::CryptoBackendFactory::instance()->smime() ) {
1692 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp() &&
1693 !ident.pgpSigningKey().isEmpty();
1694 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime() &&
1695 !ident.smimeSigningKey().isEmpty();
1697 setEncryption( mLastEncryptActionState );
1698 setSigning( ( canOpenPGPSign || canSMIMESign ) && mLastSignActionState );
1700 slotUpdateSignatureAndEncrypionStateIndicators();
1703 if ( mMsg->headerByType(
"X-KMail-Fcc" ) ) {
1704 kmailFcc = mMsg->headerByType(
"X-KMail-Fcc" )->asUnicodeString();
1706 if ( !mBtnFcc->isChecked() ) {
1707 if ( kmailFcc.isEmpty() ) {
1714 const bool stickyDictionary = mBtnDictionary->isChecked() && !mIgnoreStickyFields;
1715 if ( !stickyDictionary ) {
1716 mDictionaryCombo->setCurrentByDictionaryName( ident.dictionary() );
1719 mEdtReplyTo->setText( mMsg->replyTo()->asUnicodeString() );
1721 KMime::Content *msgContent =
new KMime::Content;
1722 msgContent->setContent( mMsg->encodedContent() );
1723 msgContent->parse();
1724 MessageViewer::EmptySource emptySource;
1725 MessageViewer::ObjectTreeParser otp( &emptySource );
1726 emptySource.setAllowDecryption( allowDecryption );
1727 otp.parseObjectTree( msgContent );
1729 bool shouldSetCharset =
false;
1730 if ( ( mContext ==
Reply || mContext ==
ReplyToAll || mContext ==
Forward ) && MessageComposer::MessageComposerSettings::forceReplyCharset() )
1731 shouldSetCharset =
true;
1732 if ( shouldSetCharset && !otp.plainTextContentCharset().isEmpty() )
1733 mOriginalPreferredCharset = otp.plainTextContentCharset();
1738 #if 0 //TODO port to kmime
1741 if ( mMsg->numBodyParts() == 0 && otp.textualContent().isEmpty() ) {
1742 mCharset=mMsg->charset();
1743 if ( mCharset.isEmpty() || mCharset ==
"default" ) {
1744 mCharset = Util::defaultCharset();
1747 QByteArray bodyDecoded = mMsg->bodyDecoded();
1749 if ( allowDecryption ) {
1750 decryptOrStripOffCleartextSignature( bodyDecoded );
1753 const QTextCodec *codec = KMail::Util::codecForName( mCharset );
1755 mEditor->setText( codec->toUnicode( bodyDecoded ) );
1757 mEditor->setText( QString::fromLocal8Bit( bodyDecoded ) );
1762 if( (MessageComposer::MessageComposerSettings::self()->autoTextSignature()==QLatin1String(
"auto" )) && mayAutoSign ) {
1769 if ( MessageComposer::MessageComposerSettings::self()->prependSignature() ) {
1770 QTimer::singleShot( 0, mComposerBase->signatureController(), SLOT(prependSignature()) );
1772 QTimer::singleShot( 0, mComposerBase->signatureController(), SLOT(appendSignature()) );
1775 mComposerBase->editor()->startExternalEditor();
1781 mPreventFccOverwrite = ( !kmailFcc.isEmpty() && ident.fcc() != kmailFcc );
1782 QTimer::singleShot( 0,
this, SLOT(forceAutoSaveMessage()) );
1785 void KMComposeWin::setAutoSaveFileName(
const QString& fileName)
1787 mComposerBase->setAutoSaveFileName( fileName );
1793 mTextSelection = selection;
1799 mCustomTemplate = customTemplate;
1806 Akonadi::Collection col;
1807 if ( idString.isEmpty() )
1808 col = CommonKernel->sentCollectionFolder();
1810 col = Akonadi::Collection( idString.toLongLong() );
1812 mComposerBase->setFcc( col );
1813 mFccFolder->setCollection( col );
1816 bool KMComposeWin::isComposerModified()
const
1818 return ( mComposerBase->editor()->document()->isModified() ||
1819 mEdtFrom->isModified() ||
1820 ( mEdtReplyTo && mEdtReplyTo->isModified() ) ||
1821 mComposerBase->recipientsEditor()->isModified() ||
1822 mEdtSubject->document()->isModified() );
1826 bool KMComposeWin::isModified()
const
1828 return mWasModified || isComposerModified();
1834 mWasModified = modified;
1835 changeModifiedState( modified );
1839 void KMComposeWin::changeModifiedState(
bool modified )
1841 mComposerBase->editor()->document()->setModified( modified );
1843 mEdtFrom->setModified(
false );
1844 if ( mEdtReplyTo ) mEdtReplyTo->setModified(
false );
1845 mComposerBase->recipientsEditor()->clearModified();
1846 mEdtSubject->document()->setModified(
false );
1851 bool KMComposeWin::queryClose ()
1853 if ( !mComposerBase->editor()->checkExternalEditorFinished() ) {
1856 if (
kmkernel->shuttingDown() || kapp->sessionSaving() ) {
1860 if ( isModified() ) {
1861 const bool istemplate = ( mFolder.isValid() && CommonKernel->folderIsTemplates( mFolder ) );
1862 const QString savebut = ( istemplate ?
1863 i18n(
"Re&save as Template") :
1864 i18n(
"&Save as Draft") );
1865 const QString savetext = ( istemplate ?
1866 i18n(
"Resave this message in the Templates folder. "
1867 "It can then be used at a later time.") :
1868 i18n(
"Save this message in the Drafts folder. "
1869 "It can then be edited and sent at a later time.") );
1871 const int rc = KMessageBox::warningYesNoCancel(
this,
1872 i18n(
"Do you want to save the message for later or discard it?"),
1873 i18n(
"Close Composer"),
1874 KGuiItem(savebut, QLatin1String(
"document-save"), QString(), savetext),
1875 KStandardGuiItem::discard(),
1876 KStandardGuiItem::cancel());
1877 if ( rc == KMessageBox::Cancel ) {
1879 }
else if ( rc == KMessageBox::Yes ) {
1889 mComposerBase->cleanupAutoSave();
1891 if( !mMiscComposers.isEmpty() ) {
1892 kWarning() <<
"Tried to close while composer was active";
1899 MessageComposer::ComposerViewBase::MissingAttachment KMComposeWin::userForgotAttachment()
1901 bool checkForForgottenAttachments = mCheckForForgottenAttachments &&
GlobalSettings::self()->showForgottenAttachmentWarning();
1903 if ( !checkForForgottenAttachments )
1904 return MessageComposer::ComposerViewBase::NoMissingAttachmentFound;
1906 mComposerBase->setSubject( subject() );
1907 MessageComposer::ComposerViewBase::MissingAttachment missingAttachments = mComposerBase->checkForMissingAttachments(
GlobalSettings::self()->attachmentKeywords() );
1909 return missingAttachments;
1912 void KMComposeWin::forceAutoSaveMessage()
1919 if ( isComposerModified() || force ) {
1920 applyComposerSetting( mComposerBase );
1921 mComposerBase->autoSaveMessage();
1923 mWasModified =
true;
1924 changeModifiedState(
false );
1927 mComposerBase->updateAutoSave();
1931 bool KMComposeWin::encryptToSelf()
1934 return MessageComposer::MessageComposerSettings::self()->cryptoEncryptToSelf();
1939 void KMComposeWin::slotSendFailed(
const QString& msg,MessageComposer::ComposerViewBase::FailedType type)
1943 KMessageBox::sorry( mMainWidget, msg,
1944 (type == MessageComposer::ComposerViewBase::AutoSave) ? i18n(
"Autosave Message Failed" ) : i18n(
"Sending Message Failed" ) );
1947 void KMComposeWin::slotSendSuccessful()
1950 mComposerBase->cleanupAutoSave();
1951 mFolder = Akonadi::Collection();
1961 Kleo::CryptoMessageFormat KMComposeWin::cryptoMessageFormat()
const
1963 if ( !mCryptoModuleAction ) {
1964 return Kleo::AutoFormat;
1966 return cb2format( mCryptoModuleAction->currentItem() );
1972 mComposerBase->addAttachmentPart( msgPart );
1977 QString KMComposeWin::prettyMimeType(
const QString &type )
1979 const QString t = type.toLower();
1980 const KMimeType::Ptr st = KMimeType::mimeType( t );
1983 kWarning() <<
"unknown mimetype" << t;
1987 const QString pretty = !st->isDefault() ? st->comment() : t;
1988 if ( pretty.isEmpty() )
1994 void KMComposeWin::setAutoCharset()
1996 mCodecAction->setCurrentItem( 0 );
2003 foreach( QAction *action, root->actions() ) {
2004 KSelectAction *subMenu =
dynamic_cast<KSelectAction *
>( action );
2006 const QString codecNameToSet =
selectCharset( subMenu, encoding );
2007 if ( !codecNameToSet.isEmpty() )
2008 return codecNameToSet;
2011 const QString fixedActionText = MessageViewer::NodeHelper::fixEncoding( action->text() );
2012 if ( KGlobal::charsets()->codecForName(
2013 KGlobal::charsets()->encodingForName( fixedActionText ) )
2014 == KGlobal::charsets()->codecForName( encoding ) ) {
2015 return action->text();
2023 void KMComposeWin::setCharset(
const QByteArray &charset )
2025 const QString codecNameToSet =
selectCharset( mCodecAction, QString::fromLatin1(charset) );
2026 if ( codecNameToSet.isEmpty() ) {
2027 kWarning() <<
"Could not find charset" << charset;
2031 mCodecAction->setCurrentCodec( codecNameToSet );
2035 void KMComposeWin::slotAddrBook()
2037 KRun::runCommand(QLatin1String(
"kaddressbook"), window());
2041 void KMComposeWin::slotInsertFile()
2043 KUrl u = mComposerBase->editor()->insertFile();
2047 mRecentAction->addUrl( u );
2050 const QString encoding = MessageViewer::NodeHelper::encodingForName( u.fileEncoding() );
2055 const int mMaxRecentFiles = 30;
2056 while ( urls.count() > mMaxRecentFiles )
2058 while ( encodings.count() > mMaxRecentFiles )
2059 encodings.removeLast();
2061 if ( urls.count() != encodings.count() ) {
2065 urls.prepend( u.prettyUrl() );
2066 encodings.prepend( encoding );
2069 mRecentAction->saveEntries(
KMKernel::self()->config()->group( QString() ) );
2071 slotInsertRecentFile( u );
2075 void KMComposeWin::slotRecentListFileClear()
2078 KConfigGroup group( config,
"Composer" );
2079 group.deleteEntry(
"recent-urls");
2080 group.deleteEntry(
"recent-encodings");
2081 mRecentAction->saveEntries( config->group( QString() ) );
2084 void KMComposeWin::slotInsertRecentFile(
const KUrl &u )
2086 if ( u.fileName().isEmpty() ) {
2094 const int index = urls.indexOf( u.prettyUrl() );
2095 if ( index != -1 ) {
2096 encoding = encodings[ index ];
2098 kDebug()<<
" encoding not found so we can't insert text";
2103 MessageComposer::InsertTextFileJob *job =
new MessageComposer::InsertTextFileJob( mComposerBase->editor(), u );
2104 job->setEncoding( encoding );
2111 void KMComposeWin::slotSelectCryptoModule(
bool init )
2116 mComposerBase->attachmentModel()->setEncryptEnabled( canSignEncryptAttachments() );
2117 mComposerBase->attachmentModel()->setSignEnabled( canSignEncryptAttachments() );
2121 void KMComposeWin::slotUpdateFont()
2124 if ( !mFixedFontAction ) {
2127 mComposerBase->editor()->setFontForWholeText( mFixedFontAction->isChecked() ?
2128 mFixedFont : mBodyFont );
2133 return MessageCore::StringUtil::smartQuote( msg, MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
2140 if ( source->hasImage() && source->hasFormat( QLatin1String(
"image/png") ) ) {
2143 const QByteArray imageData = source->data( QLatin1String(
"image/png") );
2144 if ( imageData.isEmpty() ) {
2147 if ( !forceAttachment ) {
2148 if ( mComposerBase->editor()->textMode() == KRichTextEdit::Rich && mComposerBase->editor()->isEnableImageActions() ) {
2149 QImage image = qvariant_cast<QImage>( source->imageData() );
2150 QFileInfo fi( source->text() );
2153 const QAction *addAsInlineImageAction = menu.addAction( i18n(
"Add as &Inline Image") );
2154 menu.addAction( i18n(
"Add as &Attachment") );
2155 const QAction *selectedAction = menu.exec( QCursor::pos() );
2156 if ( selectedAction == addAsInlineImageAction ) {
2158 mComposerBase->editor()->insertImage( image, fi );
2160 }
else if( !selectedAction ) {
2169 const QString attName =
2170 KInputDialog::getText( i18n(
"KMail"), i18n(
"Name of the attachment:" ), QString(), &ok,
this );
2174 addAttachment( attName, KMime::Headers::CEbase64, QString(), imageData,
"image/png" );
2180 if ( !urlList.isEmpty() ) {
2182 Akonadi::Item::List items;
2183 Akonadi::Collection::List collections;
2184 bool allLocalURLs =
true;
2186 foreach (
const KUrl &url, urlList ) {
2187 if ( !url.isLocalFile() ) {
2188 allLocalURLs =
false;
2190 const Akonadi::Item item = Akonadi::Item::fromUrl( url );
2191 if ( item.isValid() ) {
2194 const Akonadi::Collection collection = Akonadi::Collection::fromUrl( url );
2195 if ( collection.isValid() )
2196 collections << collection;
2200 if ( items.isEmpty() && collections.isEmpty() ) {
2201 if ( allLocalURLs || forceAttachment ) {
2202 foreach(
const KUrl &url, urlList ) {
2207 const QAction *addAsTextAction = p.addAction( i18np(
"Add URL into Message as &Text",
"Add URLs into Message as &Text", urlList.size() ) );
2208 const QAction *addAsAttachmentAction = p.addAction( i18np(
"Add File as &Attachment",
"Add Files as &Attachment", urlList.size() ) );
2209 const QAction *selectedAction = p.exec( QCursor::pos() );
2211 if ( selectedAction == addAsTextAction ) {
2212 foreach(
const KUrl &url, urlList ) {
2213 mComposerBase->editor()->textCursor().insertText(url.url() + QLatin1Char(
'\n'));
2215 }
else if ( selectedAction == addAsAttachmentAction ) {
2216 foreach(
const KUrl &url, urlList ) {
2223 if ( !items.isEmpty() ){
2224 Akonadi::ItemFetchJob *itemFetchJob =
new Akonadi::ItemFetchJob( items,
this );
2225 itemFetchJob->fetchScope().fetchFullPayload(
true );
2226 itemFetchJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
2229 if ( !collections.isEmpty() ) {
2238 void KMComposeWin::slotPasteAsAttachment()
2240 const QMimeData *mimeData = QApplication::clipboard()->mimeData();
2243 if( mimeData->hasText() ) {
2245 const QString attName = KInputDialog::getText(
2246 i18n(
"Insert clipboard text as attachment" ),
2247 i18n(
"Name of the attachment:" ),
2248 QString(), &ok,
this );
2250 mComposerBase->addAttachment( attName, attName, QLatin1String(
"utf-8"), QApplication::clipboard()->
text().toUtf8(),
"text/plain" );
2259 if ( job->error() ) {
2260 if ( static_cast<KIO::Job*>(job)->ui() )
2261 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
2263 kDebug()<<
" job->errorString() :"<<job->errorString();
2266 Akonadi::ItemFetchJob *fjob =
dynamic_cast<Akonadi::ItemFetchJob*
>( job );
2269 const Akonadi::Item::List items = fjob->items();
2271 if ( items.isEmpty() )
2274 if ( items.first().mimeType() == KMime::Message::mimeType() ) {
2276 if ( items.at( 0 ).isValid() && items.at( 0 ).parentCollection().isValid() ) {
2279 identity = fd->identity();
2284 foreach (
const Akonadi::Item &item, items ) {
2285 QString attachmentName = QLatin1String(
"attachment" );
2286 if ( item.hasPayload<KABC::Addressee>() ) {
2287 const KABC::Addressee contact = item.payload<KABC::Addressee>();
2288 attachmentName = contact.realName() + QLatin1String(
".vcf" );
2290 QByteArray data = item.payloadData();
2291 data.replace(
"X-messaging/aim-All",(
"X-AIM"));
2292 data.replace(
"X-messaging/icq-All",(
"X-ICQ"));
2293 data.replace(
"X-messaging/xmpp-All",(
"X-JABBER"));
2294 data.replace(
"X-messaging/msn-All",(
"X-MSN"));
2295 data.replace(
"X-messaging/yahoo-All",(
"X-YAHOO"));
2296 data.replace(
"X-messaging/gadu-All",(
"X-GADUGADU"));
2297 data.replace(
"X-messaging/skype-All",(
"X-SKYPE"));
2298 data.replace(
"X-messaging/groupwise-All",(
"X-GROUPWISE"));
2299 data.replace((
"X-messaging/sms-All"),(
"X-SMS"));
2300 data.replace((
"X-messaging/meanwhile-All"),(
"X-MEANWHILE"));
2301 data.replace((
"X-messaging/irc-All"),(
"X-IRC"));
2302 data.replace((
"X-messaging/googletalk-All"),(
"X-GOOGLETALK"));
2303 addAttachment( attachmentName, KMime::Headers::CEbase64, QString(), data, item.mimeType().toLatin1() );
2305 addAttachment( attachmentName, KMime::Headers::CEbase64, QString(), item.payloadData(), item.mimeType().toLatin1() );
2311 QString KMComposeWin::addQuotesToText(
const QString &inputText )
const
2313 QString answer( inputText );
2314 const QString indentStr = mComposerBase->editor()->quotePrefixName();
2315 answer.replace( QLatin1Char(
'\n'), QLatin1Char(
'\n') + indentStr );
2316 answer.prepend( indentStr );
2317 answer += QLatin1Char(
'\n');
2318 return MessageCore::StringUtil::smartQuote( answer, MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
2322 void KMComposeWin::slotUndo()
2329 if (::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw )) {
2330 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->undo();
2331 }
else if ( ::qobject_cast<KMComposerEditor*>( fw ) ) {
2333 }
else if (::qobject_cast<KLineEdit*>( fw )) {
2338 void KMComposeWin::slotRedo()
2345 if (::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw )) {
2346 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->redo();
2347 }
else if ( ::qobject_cast<KMComposerEditor*>( fw ) ) {
2349 }
else if (::qobject_cast<KLineEdit*>( fw )) {
2355 void KMComposeWin::slotCut()
2362 if ( ::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw ) ) {
2363 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->cut();
2364 }
else if ( ::qobject_cast<KMComposerEditor*>( fw ) ) {
2366 }
else if ( ::qobject_cast<KLineEdit*>( fw ) ) {
2372 void KMComposeWin::slotCopy()
2379 if ( ::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw ) ) {
2380 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->copy();
2381 }
else if ( ::qobject_cast<KMComposerEditor*>( fw ) ) {
2383 }
else if ( ::qobject_cast<KLineEdit*>( fw ) ) {
2389 void KMComposeWin::slotPaste()
2391 QWidget *
const fw = focusWidget();
2395 if ( ::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw ) ) {
2396 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->paste();
2397 }
else if ( ::qobject_cast<KMComposerEditor*>( fw ) ) {
2399 }
else if ( ::qobject_cast<KLineEdit*>( fw ) ) {
2405 void KMComposeWin::slotMarkAll()
2412 if (::qobject_cast<MessageComposer::SubjectLineEditWithAutoCorrection*>( fw )) {
2413 static_cast<MessageComposer::SubjectLineEditWithAutoCorrection*
>( fw )->selectAll();
2414 }
else if ( ::qobject_cast<KLineEdit*>( fw ) ) {
2415 static_cast<KLineEdit*
>( fw )->selectAll();
2416 }
else if (::qobject_cast<KMComposerEditor*>( fw )) {
2417 static_cast<KTextEdit*
>( fw )->selectAll();
2422 void KMComposeWin::slotClose()
2428 void KMComposeWin::slotNewComposer()
2431 KMime::Message::Ptr msg(
new KMime::Message );
2433 MessageHelper::initHeader( msg,
KMKernel::self()->identityManager() );
2439 void KMComposeWin::slotNewMailReader()
2446 void KMComposeWin::slotUpdWinTitle()
2448 QString s( mEdtSubject->toPlainText() );
2451 if ( s.isEmpty() ) {
2452 setCaption( QLatin1Char(
'(') + i18n(
"unnamed") + QLatin1Char(
')') );
2454 setCaption( s.replace( QLatin1Char(
'\n'), QLatin1Char(
' ') ) );
2459 void KMComposeWin::slotEncryptToggled(
bool on )
2461 setEncryption( on,
true );
2462 slotUpdateSignatureAndEncrypionStateIndicators();
2466 void KMComposeWin::setEncryption(
bool encrypt,
bool setByUser )
2468 bool wasModified = isModified();
2472 if ( !mEncryptAction->isEnabled() ) {
2477 else if ( encrypt && encryptToSelf() && !mLastIdentityHasEncryptionKey ) {
2479 KMessageBox::sorry(
this,
2480 i18n(
"<qt><p>You have requested that messages be "
2481 "encrypted to yourself, but the currently selected "
2482 "identity does not define an (OpenPGP or S/MIME) "
2483 "encryption key to use for this.</p>"
2484 "<p>Please select the key(s) to use "
2485 "in the identity configuration.</p>"
2487 i18n(
"Undefined Encryption Key") );
2494 mEncryptAction->setChecked( encrypt );
2496 slotUpdateSignatureAndEncrypionStateIndicators();
2500 mEncryptAction->setIcon( KIcon( QLatin1String(
"document-encrypt") ) );
2502 mEncryptAction->setIcon( KIcon( QLatin1String(
"document-decrypt") ) );
2506 if( canSignEncryptAttachments() ) {
2507 mComposerBase->attachmentModel()->setEncryptSelected( encrypt );
2512 void KMComposeWin::slotSignToggled(
bool on )
2514 setSigning( on,
true );
2515 slotUpdateSignatureAndEncrypionStateIndicators();
2519 void KMComposeWin::setSigning(
bool sign,
bool setByUser )
2521 bool wasModified = isModified();
2525 if ( !mSignAction->isEnabled() ) {
2530 if ( sign && !mLastIdentityHasSigningKey ) {
2532 KMessageBox::sorry(
this,
2533 i18n(
"<qt><p>In order to be able to sign "
2534 "this message you first have to "
2535 "define the (OpenPGP or S/MIME) signing key "
2537 "<p>Please select the key to use "
2538 "in the identity configuration.</p>"
2540 i18n(
"Undefined Signing Key") );
2547 mSignAction->setChecked( sign );
2550 slotUpdateSignatureAndEncrypionStateIndicators();
2553 if ( canSignEncryptAttachments() ) {
2554 mComposerBase->attachmentModel()->setSignSelected( sign );
2562 mComposerBase->editor()->enableWordWrap( MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
2570 mComposerBase->editor()->disableWordWrap();
2576 mForceDisableHtml =
true;
2577 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2578 markupAction->setEnabled(
false );
2584 mCheckForForgottenAttachments =
false;
2589 mIgnoreStickyFields =
true;
2590 mBtnTransport->setChecked(
false );
2591 mBtnDictionary->setChecked(
false );
2592 mBtnIdentity->setChecked(
false );
2593 mBtnTransport->setEnabled(
false );
2594 mBtnDictionary->setEnabled(
false );
2595 mBtnIdentity->setEnabled(
false );
2599 void KMComposeWin::slotPrint()
2601 printComposer(
false);
2604 void KMComposeWin::slotPrintPreview()
2606 printComposer(
true);
2609 void KMComposeWin::printComposer(
bool preview)
2611 MessageComposer::Composer* composer = createSimpleComposer();
2612 mMiscComposers.append( composer );
2613 composer->setProperty(
"preview",preview);
2614 connect( composer, SIGNAL(result(
KJob*)),
2615 this, SLOT(slotPrintComposeResult(
KJob*)) );
2619 void KMComposeWin::slotPrintComposeResult(
KJob *job )
2621 const bool preview = job->property(
"preview").toBool();
2622 printComposeResult( job, preview );
2625 void KMComposeWin::printComposeResult(
KJob *job,
bool preview )
2627 Q_ASSERT( dynamic_cast< MessageComposer::Composer* >( job ) );
2628 MessageComposer::Composer* composer =
dynamic_cast< MessageComposer::Composer*
>( job );
2629 Q_ASSERT( mMiscComposers.contains( composer ) );
2630 mMiscComposers.removeAll( composer );
2632 if( composer->error() == MessageComposer::Composer::NoError ) {
2634 Q_ASSERT( composer->resultMessages().size() == 1 );
2635 Akonadi::Item printItem;
2636 printItem.setPayload<KMime::Message::Ptr>( composer->resultMessages().first() );
2637 const bool isHtml = ( mComposerBase->editor()->textMode() == KMeditor::Rich );
2639 0, isHtml, isHtml );
2643 if ( static_cast<KIO::Job*>(job)->ui() ) {
2644 static_cast<KIO::Job*
>(job)->ui()->showErrorMessage();
2646 kWarning() <<
"Composer for printing failed:" << composer->errorString();
2653 void KMComposeWin::doSend( MessageComposer::MessageSender::SendMethod method,
2654 MessageComposer::MessageSender::SaveIn saveIn )
2657 if ( method == MessageComposer::MessageSender::SendImmediate ) {
2658 if( !MessageComposer::Util::sendMailDispatcherIsOnline() ) {
2659 method = MessageComposer::MessageSender::SendLater;
2664 if ( saveIn == MessageComposer::MessageSender::SaveInNone ) {
2665 if ( KPIMUtils::firstEmailAddress( from() ).isEmpty() ) {
2666 if ( !( mShowHeaders &
HDR_FROM ) ) {
2668 rethinkFields(
false );
2670 mEdtFrom->setFocus();
2671 KMessageBox::sorry(
this,
2672 i18n(
"You must enter your email address in the "
2673 "From: field. You should also set your email "
2674 "address for all identities, so that you do "
2675 "not have to enter it for each message.") );
2678 if ( mComposerBase->to().isEmpty() ) {
2679 if ( mComposerBase->cc().isEmpty() && mComposerBase->bcc().isEmpty() ) {
2680 KMessageBox::information(
this,
2681 i18n(
"You must specify at least one receiver, "
2682 "either in the To: field or as CC or as BCC.") );
2686 int rc = KMessageBox::questionYesNo(
this,
2687 i18n(
"To: field is empty. "
2688 "Send message anyway?"),
2689 i18n(
"No To: specified"),
2690 KStandardGuiItem::yes(),
2691 KStandardGuiItem::no(),
2692 QLatin1String(
":kmail_no_to_field_specified") );
2693 if ( rc == KMessageBox::No ) {
2699 if ( subject().isEmpty() ) {
2700 mEdtSubject->setFocus();
2702 KMessageBox::questionYesNo(
this,
2703 i18n(
"You did not specify a subject. "
2704 "Send message anyway?"),
2705 i18n(
"No Subject Specified"),
2706 KGuiItem(i18n(
"S&end as Is")),
2707 KGuiItem(i18n(
"&Specify the Subject")),
2708 QLatin1String(
"no_subject_specified") );
2709 if ( rc == KMessageBox::No ) {
2714 const MessageComposer::ComposerViewBase::MissingAttachment forgotAttachment = userForgotAttachment();
2715 if ( (forgotAttachment == MessageComposer::ComposerViewBase::FoundMissingAttachmentAndAddedAttachment) ||
2716 (forgotAttachment == MessageComposer::ComposerViewBase::FoundMissingAttachmentAndCancel) ) {
2721 setEnabled(
false );
2723 const QStringList recipients = QStringList() << mComposerBase->to().trimmed() << mComposerBase->cc().trimmed() << mComposerBase->bcc().trimmed();
2726 job->setProperty(
"method", static_cast<int>( method ) );
2727 job->setProperty(
"saveIn", static_cast<int>( saveIn ) );
2728 connect( job, SIGNAL(result(
KJob*)), SLOT(slotDoDelayedSend(
KJob*)) );
2733 if( saveIn == MessageComposer::MessageSender::SaveInDrafts && mEncryptAction->isChecked() &&
2735 mComposerBase->to().isEmpty() && mComposerBase->cc().isEmpty() ) {
2737 KMessageBox::information(
this, i18n(
"You must specify at least one receiver "
2738 "in order to be able to encrypt a draft.")
2742 doDelayedSend( method, saveIn );
2746 void KMComposeWin::slotDoDelayedSend(
KJob *job )
2748 if ( job->error() ) {
2749 KMessageBox::error(
this, job->errorText() );
2757 if ( !validateJob->
isValid() ) {
2763 const MessageComposer::MessageSender::SendMethod method =
static_cast<MessageComposer::MessageSender::SendMethod
>( job->property(
"method" ).toInt() );
2764 const MessageComposer::MessageSender::SaveIn saveIn =
static_cast<MessageComposer::MessageSender::SaveIn
>( job->property(
"saveIn" ).toInt() );
2766 doDelayedSend( method, saveIn );
2769 void KMComposeWin::applyComposerSetting( MessageComposer::ComposerViewBase* mComposerBase )
2773 if( !mOriginalPreferredCharset.isEmpty() ) {
2774 charsets.insert( 0, mOriginalPreferredCharset );
2776 mComposerBase->setFrom( from() );
2777 mComposerBase->setReplyTo( replyTo() );
2778 mComposerBase->setSubject( subject() );
2779 mComposerBase->setCharsets( charsets );
2780 mComposerBase->setUrgent( mUrgentAction->isChecked() );
2781 mComposerBase->setMDNRequested( mRequestMDNAction->isChecked() );
2785 void KMComposeWin::doDelayedSend( MessageComposer::MessageSender::SendMethod method, MessageComposer::MessageSender::SaveIn saveIn )
2787 #ifndef QT_NO_CURSOR
2788 MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
2790 applyComposerSetting( mComposerBase );
2791 if ( mForceDisableHtml )
2792 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2793 bool sign = mSignAction->isChecked();
2794 bool encrypt = mEncryptAction->isChecked();
2796 mComposerBase->setCryptoOptions( sign, encrypt, cryptoMessageFormat(),
2797 ( ( saveIn != MessageComposer::MessageSender::SaveInNone &&
GlobalSettings::self()->neverEncryptDrafts() )
2798 || mSigningAndEncryptionExplicitlyDisabled ) );
2802 for (
int ix=0; ix<num; ++ix) {
2804 customMimeHeader.readConfig();
2805 customHeader.insert(customMimeHeader.custHeaderName().toLatin1(), customMimeHeader.custHeaderValue() );
2808 QMapIterator<QByteArray, QString> extraCustomHeader(mExtraHeaders);
2809 while (extraCustomHeader.hasNext()) {
2810 extraCustomHeader.next();
2811 customHeader.insert(extraCustomHeader.key(), extraCustomHeader.value() );
2814 mComposerBase->setCustomHeader( customHeader );
2815 mComposerBase->send( method, saveIn,
false );
2819 void KMComposeWin::slotSendLater()
2821 if ( !TransportManager::self()->showTransportCreationDialog(
this, TransportManager::IfNoTransportExists ) )
2823 if ( !checkRecipientNumber() )
2825 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2826 const bool wasRegistered = (SendLater::SendLaterUtil::sentLaterAgentWasRegistered() && SendLater::SendLaterUtil::sentLaterAgentEnabled());
2827 if (wasRegistered) {
2828 SendLater::SendLaterInfo *info = 0;
2829 QPointer<SendLater::SendLaterDialog> dlg =
new SendLater::SendLaterDialog(info,
this);
2832 const SendLater::SendLaterDialog::SendLaterAction action = dlg->action();
2835 case SendLater::SendLaterDialog::Unknown:
2836 kDebug()<<
"Sendlater action \"Unknown\": Need to fix it.";
2838 case SendLater::SendLaterDialog::Canceled:
2841 case SendLater::SendLaterDialog::PutInOutbox:
2842 doSend( MessageComposer::MessageSender::SendLater );
2844 case SendLater::SendLaterDialog::SendDeliveryAtTime:
2846 mComposerBase->setSendLaterInfo(info);
2847 if (info->isRecurrence()) {
2848 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInTemplates );
2850 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInDrafts );
2859 doSend( MessageComposer::MessageSender::SendLater );
2865 void KMComposeWin::slotSaveDraft()
2867 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2868 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInDrafts );
2873 void KMComposeWin::slotSaveTemplate()
2875 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2876 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInTemplates );
2881 void KMComposeWin::slotSendNowVia( QAction *item )
2883 const QList<int> availTransports= TransportManager::self()->transportIds();
2884 const int transport = item->data().toInt();
2885 if ( availTransports.contains( transport ) ) {
2886 mComposerBase->transportComboBox()->setCurrentTransport( transport );
2892 void KMComposeWin::slotSendLaterVia( QAction *item )
2894 const QList<int> availTransports= TransportManager::self()->transportIds();
2895 const int transport = item->data().toInt();
2896 if ( availTransports.contains( transport ) ) {
2897 mComposerBase->transportComboBox()->setCurrentTransport( transport );
2905 if ( !mComposerBase->editor()->checkExternalEditorFinished() ) {
2908 if ( !TransportManager::self()->showTransportCreationDialog(
this, TransportManager::IfNoTransportExists ) )
2910 if ( !checkRecipientNumber() )
2914 #ifdef HAVE_FORCESPELLCHECKING
2915 mComposerBase->editor()->forceSpellChecking();
2924 void KMComposeWin::slotCheckSendNow()
2927 int rc = KMessageBox::warningYesNoCancel( mMainWidget,
2928 i18n(
"About to send email..."),
2929 i18n(
"Send Confirmation"),
2930 KGuiItem( i18n(
"&Send Now") ),
2931 KGuiItem( i18n(
"Send &Later") ) );
2933 if ( rc == KMessageBox::Yes ) {
2934 doSend( MessageComposer::MessageSender::SendImmediate );
2935 }
else if ( rc == KMessageBox::No ) {
2936 doSend( MessageComposer::MessageSender::SendLater );
2939 doSend( MessageComposer::MessageSender::SendImmediate );
2944 bool KMComposeWin::checkRecipientNumber()
const
2947 if (
GlobalSettings::self()->tooManyRecipients() && mComposerBase->recipientsEditor()->recipients().count() > thresHold ) {
2948 if ( KMessageBox::questionYesNo( mMainWidget,
2949 i18n(
"You are trying to send the mail to more than %1 recipients. Send message anyway?", thresHold),
2950 i18n(
"Too many recipients"),
2951 KGuiItem( i18n(
"&Send as Is") ),
2952 KGuiItem( i18n(
"&Edit Recipients") ) ) == KMessageBox::No ) {
2960 void KMComposeWin::slotHelp()
2962 KToolInvocation::invokeHelp();
2966 void KMComposeWin::enableHtml()
2968 if ( mForceDisableHtml ) {
2969 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2973 mComposerBase->editor()->enableRichTextMode();
2974 if ( !toolBar( QLatin1String(
"htmlToolBar") )->isVisible() ) {
2979 QTimer::singleShot( 0, toolBar( QLatin1String(
"htmlToolBar") ), SLOT(show()) );
2981 if ( !markupAction->isChecked() )
2982 markupAction->setChecked(
true );
2984 mComposerBase->editor()->updateActionStates();
2985 mComposerBase->editor()->setActionsEnabled(
true );
2991 void KMComposeWin::disableHtml( MessageComposer::ComposerViewBase::Confirmation confirmation )
2993 bool forcePlainTextMarkup =
false;
2994 if ( confirmation == MessageComposer::ComposerViewBase::LetUserConfirm && mComposerBase->editor()->isFormattingUsed() && !mForceDisableHtml ) {
2995 int choice = KMessageBox::warningYesNoCancel(
this, i18n(
"Turning HTML mode off "
2996 "will cause the text to lose the formatting. Are you sure?" ),
2997 i18n(
"Lose the formatting?" ), KGuiItem( i18n(
"Lose Formatting" ) ), KGuiItem( i18n(
"Add Markup Plain Text" ) ) , KStandardGuiItem::cancel(),
2998 QLatin1String(
"LoseFormattingWarning") );
3001 case KMessageBox::Cancel:
3004 case KMessageBox::No:
3005 forcePlainTextMarkup =
true;
3007 case KMessageBox::Yes:
3012 mComposerBase->editor()->forcePlainTextMarkup(forcePlainTextMarkup);
3013 mComposerBase->editor()->switchToPlainText();
3014 mComposerBase->editor()->setActionsEnabled(
false );
3017 if ( toolBar( QLatin1String(
"htmlToolBar") )->isVisible() ) {
3019 QTimer::singleShot( 0, toolBar( QLatin1String(
"htmlToolBar") ), SLOT(hide()) );
3021 if ( markupAction->isChecked() )
3022 markupAction->setChecked(
false );
3034 if ( mode == KMeditor::Plain )
3035 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
3046 disableHtml( MessageComposer::ComposerViewBase::LetUserConfirm );
3050 void KMComposeWin::slotAutoSpellCheckingToggled(
bool on )
3052 mAutoSpellCheckingAction->setChecked( on );
3053 if ( on != mComposerBase->editor()->checkSpellingEnabled() )
3054 mComposerBase->editor()->setCheckSpellingEnabled( on );
3055 if ( on != mEdtSubject->checkSpellingEnabled() )
3056 mEdtSubject->setCheckSpellingEnabled( on );
3061 temp = i18n(
"Spellcheck: on" );
3063 temp = i18n(
"Spellcheck: off" );
3065 statusBar()->changeItem( temp, 3 );
3068 void KMComposeWin::slotSpellCheckingStatus(
const QString & status)
3070 statusBar()->changeItem( status, 0 );
3076 statusBar()->changeItem(QString(), 0);
3080 void KMComposeWin::slotIdentityChanged( uint uoid,
bool initalChange )
3083 kDebug() <<
"Trying to change identity but mMsg == 0!";
3087 const KPIMIdentities::Identity &ident =
3089 if ( ident.isNull() ) {
3092 bool wasModified(isModified());
3094 if ( !ident.fullEmailAddr().isNull() ) {
3095 mEdtFrom->setText( ident.fullEmailAddr() );
3099 if ( KPIMUtils::firstEmailAddress( from() ).isEmpty() ) {
3102 if ( mEdtReplyTo ) {
3103 mEdtReplyTo->setText( ident.replyToAddr() );
3107 const KPIMIdentities::Identity &oldIdentity =
3111 if ( ident.organization().isEmpty() ) {
3112 mMsg->organization()->clear();
3114 KMime::Headers::Organization *
const organization
3115 =
new KMime::Headers::Organization( mMsg.get(), ident.organization(),
"utf-8" );
3116 mMsg->setHeader( organization );
3118 if ( !ident.isXFaceEnabled() || ident.xface().isEmpty() ) {
3119 mMsg->removeHeader(
"X-Face" );
3121 QString xface = ident.xface();
3122 if ( !xface.isEmpty() ) {
3123 int numNL = ( xface.length() - 1 ) / 70;
3124 for (
int i = numNL; i > 0; --i ) {
3125 xface.insert( i*70, QLatin1String(
"\n\t") );
3127 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-Face", mMsg.get(), xface,
"utf-8" );
3128 mMsg->setHeader( header );
3133 if ( !mBtnTransport->isChecked() && !mIgnoreStickyFields ) {
3134 const int transportId = ident.transport().isEmpty() ? -1 : ident.transport().toInt();
3135 const Transport *transport = TransportManager::self()->transportById( transportId,
true );
3137 mMsg->removeHeader(
"X-KMail-Transport" );
3138 mComposerBase->transportComboBox()->setCurrentTransport( TransportManager::self()->defaultTransportId() );
3140 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-Transport", mMsg.get(), QString::number( transport->id() ),
"utf-8" );
3141 mMsg->setHeader( header );
3142 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
3146 const bool fccIsDisabled = ident.disabledFcc();
3147 if (fccIsDisabled) {
3148 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-FccDisabled", mMsg.get(), QLatin1String(
"true"),
"utf-8" );
3149 mMsg->setHeader( header );
3151 mMsg->removeHeader(
"X-KMail-FccDisabled" );
3153 mFccFolder->setEnabled(!fccIsDisabled);
3156 if ( !mBtnDictionary->isChecked() && !mIgnoreStickyFields ) {
3157 mDictionaryCombo->setCurrentByDictionaryName( ident.dictionary() );
3159 slotSpellCheckingLanguage( mDictionaryCombo->currentDictionary() );
3160 if ( !mBtnFcc->isChecked() && !mPreventFccOverwrite ) {
3165 if ( !wasModified && !( ident.templates().isEmpty() && mCustomTemplate.isEmpty() ) &&
3167 applyTemplate( uoid, mId );
3169 mComposerBase->identityChanged( ident, oldIdentity,
false );
3170 mEdtSubject->setAutocorrectionLanguage(ident.autocorrectionLanguage());
3176 bool bNewIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
3177 bool bNewIdentityHasEncryptionKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
3179 if ( !bNewIdentityHasEncryptionKey && mLastIdentityHasEncryptionKey ) {
3180 mLastEncryptActionState = mEncryptAction->isChecked();
3181 setEncryption(
false );
3183 if ( !bNewIdentityHasSigningKey && mLastIdentityHasSigningKey ) {
3184 mLastSignActionState = mSignAction->isChecked();
3185 setSigning(
false );
3188 if ( bNewIdentityHasEncryptionKey && !mLastIdentityHasEncryptionKey ) {
3189 setEncryption( mLastEncryptActionState );
3191 if ( bNewIdentityHasSigningKey && !mLastIdentityHasSigningKey ) {
3192 setSigning( mLastSignActionState );
3195 mCryptoModuleAction->setCurrentItem( format2cb(
3196 Kleo::stringToCryptoMessageFormat( ident.preferredCryptoMessageFormat() ) ) );
3197 slotSelectCryptoModule(
true );
3199 mLastIdentityHasSigningKey = bNewIdentityHasSigningKey;
3200 mLastIdentityHasEncryptionKey = bNewIdentityHasEncryptionKey;
3203 changeCryptoAction();
3205 rethinkFields(
false );
3210 void KMComposeWin::slotSpellcheckConfig()
3212 static_cast<KMComposerEditor *
>(mComposerBase->editor())->showSpellConfigDialog( QLatin1String(
"kmail2rc") );
3216 void KMComposeWin::slotEditToolbars()
3218 saveMainWindowSettings(
KMKernel::self()->config()->group(
"Composer") );
3219 KEditToolBar dlg( guiFactory(),
this );
3221 connect( &dlg, SIGNAL(newToolBarConfig()),
3222 SLOT(slotUpdateToolbars()) );
3227 void KMComposeWin::slotUpdateToolbars()
3229 createGUI( QLatin1String(
"kmcomposerui.rc") );
3230 applyMainWindowSettings(
KMKernel::self()->config()->group(
"Composer") );
3233 void KMComposeWin::slotEditKeys()
3235 KShortcutsDialog::configure( actionCollection(),
3236 KShortcutsEditor::LetterShortcutsDisallowed );
3243 mComposerBase->editor()->setFocus();
3248 mEdtSubject->setFocus();
3251 void KMComposeWin::slotCompletionModeChanged( KGlobalSettings::Completion mode )
3256 mEdtFrom->setCompletionMode( mode );
3257 mEdtReplyTo->setCompletionMode( mode );
3258 mComposerBase->recipientsEditor()->setCompletionMode( mode );
3261 void KMComposeWin::slotConfigChanged()
3264 mComposerBase->updateAutoSave();
3273 void KMComposeWin::slotFolderRemoved(
const Akonadi::Collection & col )
3275 kDebug() <<
"you killed me.";
3277 if ( ( mFolder.isValid() ) && ( col.id() == mFolder.id() ) ) {
3278 mFolder = CommonKernel->draftsCollectionFolder();
3279 kDebug() <<
"restoring drafts to" << mFolder.id();
3284 void KMComposeWin::slotOverwriteModeChanged()
3286 mComposerBase->editor()->setCursorWidth( mComposerBase->editor()->overwriteMode () ? 5 : 1 );
3287 statusBar()->changeItem( overwriteModeStr(), 4 );
3290 QString KMComposeWin::overwriteModeStr()
const
3292 return mComposerBase->editor()->overwriteMode () ? i18n(
"OVR") : i18n (
"INS");
3295 void KMComposeWin::slotCursorPositionChanged()
3300 line = mComposerBase->editor()->linePosition();
3301 col = mComposerBase->editor()->columnNumber();
3302 temp = i18nc(
"Shows the linenumber of the cursor position.",
" Line: %1 ", line + 1 );
3303 statusBar()->changeItem( temp, 1 );
3304 temp = i18n(
" Column: %1 ", col + 1 );
3305 statusBar()->changeItem( temp, 2 );
3308 if ( mComposerBase->editor()->textCursor().charFormat().isAnchor() ) {
3309 const QString
text = mComposerBase->editor()->currentLinkText();
3310 const QString url = mComposerBase->editor()->currentLinkUrl();
3311 statusBar()->changeItem( text + QLatin1String(
" -> ") + url, 0 );
3314 statusBar()->changeItem( QString(), 0 );
3320 class KToggleActionResetter {
3321 KToggleAction *mAction;
3325 KToggleActionResetter( KToggleAction *action,
bool on )
3326 : mAction( action ), mOn( on ) {}
3327 ~KToggleActionResetter() {
3329 mAction->setChecked( mOn );
3332 void disable() { mAction = 0; }
3336 void KMComposeWin::slotEncryptChiasmusToggled(
bool on )
3342 KToggleActionResetter resetter( mEncryptChiasmusAction,
false );
3344 const Kleo::CryptoBackend::Protocol *chiasmus =
3345 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" );
3348 const QString msg = Kleo::CryptoBackendFactory::instance()->knowsAboutProtocol(
"Chiasmus" ) ?
3349 i18n(
"Please configure a Crypto Backend to use for "
3350 "Chiasmus encryption first.\n"
3351 "You can do this in the Crypto Backends tab of "
3352 "the configure dialog's Security page." ) :
3353 i18n(
"It looks as though libkleopatra was compiled without "
3354 "Chiasmus support. You might want to recompile "
3355 "libkleopatra with --enable-chiasmus.");
3356 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Backend Configured" ) );
3360 std::auto_ptr<Kleo::SpecialJob> job( chiasmus->specialJob(
"x-obtain-keys",
QMap<QString,QVariant>() ) );
3362 const QString msg = i18n(
"Chiasmus backend does not offer the "
3363 "\"x-obtain-keys\" function. Please report this bug." );
3364 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
3368 if ( job->exec() ) {
3369 job->showErrorDialog(
this, i18n(
"Chiasmus Backend Error" ) );
3373 const QVariant result = job->property(
"result" );
3374 if ( result.type() != QVariant::StringList ) {
3375 const QString msg = i18n(
"Unexpected return value from Chiasmus backend: "
3376 "The \"x-obtain-keys\" function did not return a "
3377 "string list. Please report this bug." );
3378 KMessageBox::error(
this, msg, i18n(
"Chiasmus Backend Error" ) );
3382 const QStringList keys = result.toStringList();
3383 if ( keys.empty() ) {
3384 const QString msg = i18n(
"No keys have been found. Please check that a "
3385 "valid key path has been set in the Chiasmus "
3387 KMessageBox::information(
this, msg, i18n(
"No Chiasmus Keys Found" ) );
3391 MessageViewer::ChiasmusKeySelector selectorDlg(
this, i18n(
"Chiasmus Encryption Key Selection" ),
3392 keys, GlobalSettings::chiasmusKey(),
3393 GlobalSettings::chiasmusOptions() );
3395 if ( selectorDlg.exec() != KDialog::Accepted ) {
3399 GlobalSettings::setChiasmusOptions( selectorDlg.options() );
3400 GlobalSettings::setChiasmusKey( selectorDlg.key() );
3401 assert( !GlobalSettings::chiasmusKey().isEmpty() );
3406 void KMComposeWin::recipientEditorSizeHintChanged()
3408 QTimer::singleShot( 1,
this, SLOT(setMaximumHeaderSize()) );
3411 void KMComposeWin::setMaximumHeaderSize()
3413 mHeadersArea->setMaximumHeight( mHeadersArea->sizeHint().height() );
3416 void KMComposeWin::slotUpdateSignatureAndEncrypionStateIndicators()
3418 const bool showIndicatorsAlways =
false;
3419 mSignatureStateIndicator->setText( mSignAction->isChecked() ?
3420 i18n(
"Message will be signed") :
3421 i18n(
"Message will not be signed") );
3422 mEncryptionStateIndicator->setText( mEncryptAction->isChecked() ?
3423 i18n(
"Message will be encrypted") :
3424 i18n(
"Message will not be encrypted") );
3425 if ( !showIndicatorsAlways ) {
3426 mSignatureStateIndicator->setVisible( mSignAction->isChecked() );
3427 mEncryptionStateIndicator->setVisible( mEncryptAction->isChecked() );
3431 void KMComposeWin::slotLanguageChanged(
const QString &language )
3433 mDictionaryCombo->setCurrentByDictionary( language );
3437 void KMComposeWin::slotFccFolderChanged(
const Akonadi::Collection& collection)
3439 mComposerBase->setFcc( collection );
3442 void KMComposeWin::slotTranslatorWasClosed()
3444 mTranslateAction->setChecked(
false);
3447 void KMComposeWin::insertSpecialCharacter()
3449 if(!mSelectSpecialChar) {
3450 mSelectSpecialChar =
new KPIMTextEdit::SelectSpecialChar(
this);
3451 mSelectSpecialChar->setCaption(i18n(
"Insert Special Character"));
3452 mSelectSpecialChar->setOkButtonText(i18n(
"Insert"));
3453 connect(mSelectSpecialChar,SIGNAL(charSelected(QChar)),
this,SLOT(charSelected(QChar)));
3455 mSelectSpecialChar->show();
3458 void KMComposeWin::charSelected(
const QChar& c)
3460 mComposerBase->editor()->insertPlainText(c);
3463 void KMComposeWin::slotSaveAsFile()
3465 QPointer<KFileDialog> dlg =
new KFileDialog(KUrl(),QString(),
this);
3466 dlg->setOperationMode(KFileDialog::Saving);
3467 dlg->setConfirmOverwrite(
true);
3468 if(mComposerBase->editor()->textMode() == KMeditor::Rich ) {
3469 dlg->setFilter( QString::fromLatin1(
"text/html text/plain application/vnd.oasis.opendocument.text") );
3471 dlg->setFilter( QString::fromLatin1(
"text/plain") );
3475 QTextDocumentWriter writer;
3476 const QString filename = dlg->selectedUrl().path();
3477 writer.setFileName(dlg->selectedUrl().path());
3478 if (dlg->currentFilter() == QString::fromLatin1(
"text/plain") || filename.endsWith(QLatin1String(
".txt"))) {
3479 writer.setFormat(
"plaintext");
3480 }
else if (dlg->currentFilter() == QString::fromLatin1(
"text/html")|| filename.endsWith(QLatin1String(
".html"))) {
3481 writer.setFormat(
"HTML");
3482 }
else if (dlg->currentFilter() == QString::fromLatin1(
"application/vnd.oasis.opendocument.text") || filename.endsWith(QLatin1String(
".odf"))) {
3483 writer.setFormat(
"ODF");
3485 writer.setFormat(
"plaintext");
3487 if (!writer.write(mComposerBase->editor()->document())) {
3488 qDebug()<<
" Error during writing";
3494 void KMComposeWin::slotCreateAddressBookContact()
3500 void KMComposeWin::slotAttachMissingFile()
3502 mComposerBase->attachmentController()->showAddAttachmentDialog();
3505 void KMComposeWin::slotCloseAttachMissingFile()
3507 if(m_verifyMissingAttachment) {
3508 m_verifyMissingAttachment->start();
3512 void KMComposeWin::slotVerifyMissingAttachmentTimeout()
3515 mAttachmentMissing->animatedShow();
3517 m_verifyMissingAttachment->start();
3521 void KMComposeWin::slotExplicitClosedMissingAttachment()
3523 if(m_verifyMissingAttachment) {
3524 m_verifyMissingAttachment->stop();
3525 delete m_verifyMissingAttachment;
3526 m_verifyMissingAttachment = 0;
3532 mExtraHeaders = headers;
3535 void KMComposeWin::slotUpperCase()
3537 QTextCursor textCursor = mComposerBase->editor()->textCursor();
3538 if (textCursor.hasSelection()) {
3539 const QString newText = textCursor.selectedText().toUpper();
3540 textCursor.insertText(newText);
3544 void KMComposeWin::slotLowerCase()
3546 QTextCursor textCursor = mComposerBase->editor()->textCursor();
3547 if (textCursor.hasSelection()) {
3548 const QString newText = textCursor.selectedText().toLower();
3549 textCursor.insertText(newText);
3553 void KMComposeWin::slotExternalEditorStarted()
3555 mComposerBase->identityCombo()->setEnabled(
false);
3556 mExternalEditorWarning->show();
3559 void KMComposeWin::slotExternalEditorClosed()
3561 mComposerBase->identityCombo()->setEnabled(
true);
3562 mExternalEditorWarning->hide();
void htmlToolBarVisibilityChanged(bool visible)
void slotSpellcheckDoneClearStatus()
void setTextSelection(const QString &selection)
Set the text selection the message is a response to.
void disableWordWrap()
Disables word wrap completely.
void slotWordWrapToggled(bool)
Switch wordWrap on/off.
virtual QByteArray text(quint32 serialNumber) const =0
static Composer * create(const KMime::Message::Ptr &msg, bool lastSignState, bool lastEncryptState, TemplateContext context=NoTemplate, uint identity=0, const QString &textSelection=QString(), const QString &customTemplate=QString())
virtual void setCaption(const QString &caption)
Reimplement because we have this bug #Bug 163978.
Q_SCRIPTABLE void addAttachmentsAndSend(const KUrl::List &urls, const QString &comment, int how)
void setCollectionForNewMessage(const Akonadi::Collection &folder)
const KPIMIdentities::Identity & identity() const
Q_SCRIPTABLE void addAttachment(const KUrl &url, const QString &comment)
void disableForgottenAttachmentsCheck()
Don't check for forgotten attachments for a mail, eg.
static KMKernel * self()
normal control stuff
KSharedConfig::Ptr config()
void identityChanged(const KPIMIdentities::Identity &identity)
End of D-Bus callable stuff.
static bool missingNepomukWarning(const char *neverShowAgainKey)
void forceDisableHtml()
Disables HTML completely.
static MailList fromMimeData(const QMimeData *md)
void setCurrentReplyTo(const QString &)
void setCustomTemplate(const QString &customTemplate)
Set custom template to be used for the message.
Small helper structure which encapsulates the KMMessage created when creating a reply, and.
QString smartQuote(const QString &msg)
void setModified(bool modified)
Set whether the message should be treated as modified or not.
void slotFetchJob(KJob *)
void setFcc(const QString &idString)
Use the given folder as sent-mail folder if the given folder exists.
void slotTextModeChanged(KRichTextEdit::Mode)
static QString selectCharset(KSelectAction *root, const QString &encoding)
Q_SCRIPTABLE void send(int how)
Start of D-Bus callable stuff.
void setMissingFeatures(const QStringList &features)
void setMessage(const KMime::Message::Ptr &newMsg, bool lastSignState=false, bool lastEncryptState=false, bool mayAutoSign=true, bool allowDecryption=false, bool isModified=false)
Set the message the composer shall work with.
void setFocusToSubject()
Sets the focus to the subject line edit.
static GlobalSettings * self()
void setCurrentTransport(int transportId)
void addAttach(KMime::Content *msgPart)
Add an attachment to the list.
void setPrintPreview(bool preview)
void setFocusToEditor()
Sets the focus to the edit-widget.
void addExtraCustomHeaders(const QMap< QByteArray, QString > &header)
KPIMIdentities::IdentityManager * identityManager()
return the pointer to the identity manager
void autoSaveMessage(bool force=false)
void ignoreStickyFields()
Ignore the "sticky" setting of the transport combo box and prefer the X-KMail-Transport header field ...
void slotSyncConfig()
Sync the config immediatley.
bool insertFromMimeData(const QMimeData *source, bool forceAttachment=false)
QString dbusObjectPath() const
QList< QByteArray > mimeCharsets() const
The name of the charset, if a specific encoding was selected, or a list containing the names of the p...