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"
50 #include "custommimeheader.h"
51 #include "pimcommon/autocorrection/widgets/lineeditwithautocorrection.h"
52 #include "pimcommon/translator/translatorwidget.h"
53 #include "pimcommon/widgets/customtoolswidget.h"
64 #include "agents/followupreminderagent/followupreminderutil.h"
65 #include "pimcommon/util/vcardutil.h"
74 #include "pimcommon/util/editorutil.h"
75 #include "pimcommon/storageservice/storageservicemanager.h"
76 #include "pimcommon/storageservice/storageserviceprogressmanager.h"
78 #include "messagecomposer/utils/util.h"
80 #include <kabc/vcardconverter.h>
81 #include "agents/sendlateragent/sendlaterutil.h"
82 #include "agents/sendlateragent/sendlaterdialog.h"
83 #include "agents/sendlateragent/sendlaterinfo.h"
86 #include <libkpgp/kpgpblock.h>
87 #include <libkleo/ui/progressdialog.h>
88 #include <libkleo/ui/keyselectiondialog.h>
89 #include "kleo/cryptobackendfactory.h"
90 #include "kleo/exportjob.h"
91 #include "kleo/specialjob.h"
92 #include <messageviewer/viewer/objecttreeemptysource.h>
95 #include <messageviewer/utils/kcursorsaver.h>
98 #include <messageviewer/viewer/objecttreeparser.h>
99 #include <messageviewer/viewer/nodehelper.h>
100 #include <messageviewer/settings/globalsettings.h>
101 #include <messagecomposer/composer/composer.h>
102 #include <messagecomposer/part/globalpart.h>
103 #include <messagecomposer/part/infopart.h>
104 #include <messagecomposer/part/textpart.h>
105 #include <settings/messagecomposersettings.h>
106 #include <messagecomposer/helper/messagehelper.h>
107 #include <messagecomposer/composer/signaturecontroller.h>
108 #include <messagecomposer/job/inserttextfilejob.h>
109 #include <messagecomposer/composer/composerlineedit.h>
110 #include <messagecore/attachment/attachmentpart.h>
111 #include "messagecore/settings/globalsettings.h"
112 #include <templateparser/templateparser.h>
113 #include <templatesconfiguration.h>
114 #include "messagecore/helpers/nodehelper.h"
115 #include <akonadi/kmime/messagestatus.h>
116 #include "messagecore/helpers/messagehelpers.h"
117 #include "mailcommon/folder/folderrequester.h"
118 #include "mailcommon/folder/foldercollection.h"
126 #include <akonadi/changerecorder.h>
127 #include <akonadi/itemcreatejob.h>
128 #include <akonadi/entitymimetypefiltermodel.h>
129 #include <akonadi/kmime/messageflags.h>
130 #include <akonadi/itemfetchjob.h>
131 #include <kpimutils/email.h>
132 #include <kpimidentities/identitymanager.h>
133 #include <kpimidentities/identitycombo.h>
134 #include <kpimidentities/identity.h>
135 #include <kpimidentities/signature.h>
136 #include <mailtransport/transportcombobox.h>
137 #include <mailtransport/transportmanager.h>
138 #include <mailtransport/transport.h>
139 #include <kmime/kmime_codecs.h>
140 #include <kmime/kmime_message.h>
141 #include <kpimtextedit/selectspecialchar.h>
145 #include <kactioncollection.h>
146 #include <kactionmenu.h>
147 #include <kapplication.h>
148 #include <kcharsets.h>
150 #include <kdescendantsproxymodel.h>
151 #include <kedittoolbar.h>
152 #include <kinputdialog.h>
154 #include <kmimetype.h>
155 #include <kmessagebox.h>
156 #include <krecentfilesaction.h>
157 #include <kshortcutsdialog.h>
158 #include <kstandarddirs.h>
159 #include <kstandardshortcut.h>
160 #include <kstatusbar.h>
161 #include <ktempdir.h>
162 #include <ktoggleaction.h>
163 #include <ktoolbar.h>
164 #include <ktoolinvocation.h>
165 #include <sonnet/dictionarycombobox.h>
167 #include <KIO/JobUiDelegate>
168 #include <KPrintPreview>
169 #include <KFileDialog>
172 #include <QClipboard>
175 #include <QTextDocumentWriter>
181 #include <widgets/splittercollapser.h>
182 #include <Akonadi/Contact/ContactGroupExpandJob>
185 using Sonnet::DictionaryComboBox;
186 using MailTransport::TransportManager;
187 using MailTransport::Transport;
189 using MessageComposer::KMeditor;
191 KMail::Composer *KMail::makeComposer(
const KMime::Message::Ptr &msg,
bool lastSignState,
bool lastEncryptState, Composer::TemplateContext context,
192 uint identity,
const QString & textSelection,
193 const QString & customTemplate ) {
194 return KMComposeWin::create( msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate );
198 uint identity,
const QString & textSelection,
199 const QString & customTemplate ) {
200 return new KMComposeWin( msg, lastSignState, lastEncryptState, context, identity, textSelection, customTemplate );
203 int KMComposeWin::s_composerNumber = 0;
206 KMComposeWin::KMComposeWin(
const KMime::Message::Ptr &aMsg,
bool lastSignState,
bool lastEncryptState, Composer::TemplateContext context, uint
id,
208 : KMail::Composer(
"kmail-composer#" ),
210 mTextSelection( textSelection ),
211 mCustomTemplate( customTemplate ),
212 mSigningAndEncryptionExplicitlyDisabled( false ),
213 mFolder( Akonadi::Collection( -1 ) ),
214 mForceDisableHtml( false ),
217 mSignAction( 0 ), mEncryptAction( 0 ), mRequestMDNAction( 0 ),
218 mUrgentAction( 0 ), mAllFieldsAction( 0 ), mFromAction( 0 ),
219 mReplyToAction( 0 ), mSubjectAction( 0 ),
220 mIdentityAction( 0 ), mTransportAction( 0 ), mFccAction( 0 ),
221 mWordWrapAction( 0 ), mFixedFontAction( 0 ), mAutoSpellCheckingAction( 0 ),
222 mDictionaryAction( 0 ), mSnippetAction( 0 ), mTranslateAction(0),
223 mAppendSignature( 0 ), mPrependSignature( 0 ), mInsertSignatureAtCursorPosition( 0 ),
224 mGenerateShortenUrl( 0 ),
226 mCryptoModuleAction( 0 ),
234 mSelectSpecialChar( 0 ),
235 m_verifyMissingAttachment( 0 ),
236 mPreventFccOverwrite( false ),
237 mCheckForForgottenAttachments( true ),
238 mIgnoreStickyFields( false ),
239 mWasModified( false ),
240 mCryptoStateIndicatorWidget(0),
242 mSendNowByShortcutUsed(false),
243 mFollowUpToggleAction(0),
244 mStatusBarLabelToggledOverrideMode(0),
245 mStatusBarLabelSpellCheckingChangeMode(0)
248 mComposerBase =
new MessageComposer::ComposerViewBase(
this,
this );
249 mComposerBase->setIdentityManager(
kmkernel->identityManager() );
251 connect( mComposerBase, SIGNAL(disableHtml(MessageComposer::ComposerViewBase::Confirmation)),
252 this, SLOT(disableHtml(MessageComposer::ComposerViewBase::Confirmation)) );
254 connect( mComposerBase, SIGNAL(enableHtml()),
255 this, SLOT(enableHtml()) );
256 connect( mComposerBase, SIGNAL(failed(
QString,MessageComposer::ComposerViewBase::FailedType)),
this, SLOT(slotSendFailed(
QString,MessageComposer::ComposerViewBase::FailedType)) );
257 connect( mComposerBase, SIGNAL(sentSuccessfully(
QString)),
this, SLOT(slotSendSuccessful(
QString)) );
258 connect( mComposerBase, SIGNAL(modified(
bool)),
this, SLOT(
setModified(
bool)) );
260 (void)
new MailcomposerAdaptor(
this );
264 MessageComposer::SignatureController* sigController =
new MessageComposer::SignatureController(
this );
265 connect( sigController, SIGNAL(enableHtml()), SLOT(enableHtml()) );
266 mComposerBase->setSignatureController( sigController );
268 if (
kmkernel->xmlGuiInstance().isValid() ) {
269 setComponentData(
kmkernel->xmlGuiInstance() );
271 mMainWidget =
new QWidget(
this );
273 mHeadersToEditorSplitter =
new QSplitter( Qt::Vertical, mMainWidget );
276 mHeadersArea =
new QWidget( mHeadersToEditorSplitter );
278 QSizePolicy::Expanding );
279 mHeadersToEditorSplitter->
addWidget( mHeadersArea );
282 mHeadersToEditorSplitter->
setSizes( defaultSizes );
288 v->
addWidget( mHeadersToEditorSplitter );
289 KPIMIdentities::IdentityCombo*
identity =
new KPIMIdentities::IdentityCombo(
kmkernel->identityManager(),
291 identity->setToolTip( i18n(
"Select an identity for this message" ) );
292 mComposerBase->setIdentityCombo( identity );
294 sigController->setIdentityCombo( identity );
295 sigController->suspend();
297 Sonnet::DictionaryComboBox *dictionaryCombo =
new DictionaryComboBox( mHeadersArea );
298 dictionaryCombo->setToolTip( i18n(
"Select the dictionary to use when spell-checking this message" ) );
299 mComposerBase->setDictionary(dictionaryCombo);
301 mFccFolder =
new MailCommon::FolderRequester( mHeadersArea );
302 mFccFolder->setNotAllowToCreateNewFolder(
true );
303 mFccFolder->setMustBeReadWrite(
true );
306 mFccFolder->setToolTip( i18n(
"Select the sent-mail folder where a copy of this message will be saved" ) );
307 connect( mFccFolder, SIGNAL(folderChanged(Akonadi::Collection)),
308 this, SLOT(slotFccFolderChanged(Akonadi::Collection)) );
310 MailTransport::TransportComboBox* transport =
new MailTransport::TransportComboBox( mHeadersArea );
311 transport->setToolTip( i18n(
"Select the outgoing account to use for sending this message" ) );
312 mComposerBase->setTransportCombo( transport );
313 connect(transport, SIGNAL(activated(
int)),
this, SLOT(slotTransportChanged()));
315 mEdtFrom =
new MessageComposer::ComposerLineEdit(
false, mHeadersArea );
317 mEdtFrom->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
318 mEdtFrom->setToolTip( i18n(
"Set the \"From:\" email address for this message" ) );
319 mEdtReplyTo =
new MessageComposer::ComposerLineEdit(
true, mHeadersArea );
321 mEdtReplyTo->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
322 mEdtReplyTo->setToolTip( i18n(
"Set the \"Reply-To:\" email address for this message" ) );
323 connect( mEdtReplyTo, SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
324 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)) );
326 MessageComposer::RecipientsEditor* recipientsEditor =
new MessageComposer::RecipientsEditor( mHeadersArea );
327 recipientsEditor->setRecentAddressConfig( MessageComposer::MessageComposerSettings::self()->config() );
328 connect( recipientsEditor,
329 SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
330 SLOT(slotCompletionModeChanged(KGlobalSettings::Completion)) );
331 connect( recipientsEditor, SIGNAL(sizeHintChanged()), SLOT(recipientEditorSizeHintChanged()) );
332 mComposerBase->setRecipientsEditor( recipientsEditor );
334 mEdtSubject =
new PimCommon::LineEditWithAutoCorrection( mHeadersArea,
QLatin1String(
"kmail2rc" ) );
335 mEdtSubject->setActivateLanguageMenu(
false);
336 mEdtSubject->setToolTip( i18n(
"Set a subject for this message" ) );
337 mEdtSubject->setAutocorrection(
KMKernel::self()->composerAutoCorrection());
338 mLblIdentity =
new QLabel( i18n(
"&Identity:"), mHeadersArea );
339 mDictionaryLabel =
new QLabel( i18n(
"&Dictionary:"), mHeadersArea );
340 mLblFcc =
new QLabel( i18n(
"&Sent-Mail folder:"), mHeadersArea );
341 mLblTransport =
new QLabel( i18n(
"&Mail transport:"), mHeadersArea );
342 mLblFrom =
new QLabel( i18nc(
"sender address field",
"&From:"), mHeadersArea );
343 mLblReplyTo =
new QLabel( i18n(
"&Reply to:"), mHeadersArea );
344 mLblSubject =
new QLabel( i18nc(
"@label:textbox Subject of email.",
"S&ubject:"), mHeadersArea );
345 QString sticky = i18nc(
"@option:check Sticky identity.",
"Sticky");
346 mBtnIdentity =
new QCheckBox( sticky, mHeadersArea );
347 mBtnIdentity->
setToolTip( i18n(
"Use the selected value as your identity for future messages" ) );
348 mBtnFcc =
new QCheckBox( sticky, mHeadersArea );
349 mBtnFcc->
setToolTip( i18n(
"Use the selected value as your sent-mail folder for future messages" ) );
350 mBtnTransport =
new QCheckBox( sticky, mHeadersArea );
351 mBtnTransport->
setToolTip( i18n(
"Use the selected value as your outgoing account for future messages" ) );
352 mBtnDictionary =
new QCheckBox( sticky, mHeadersArea );
353 mBtnDictionary->
setToolTip( i18n(
"Use the selected value as your dictionary for future messages" ) );
358 mFixedFontAction = 0;
360 mSplitter =
new QSplitter( Qt::Vertical, mMainWidget );
363 mSnippetSplitter =
new QSplitter( Qt::Horizontal, mSplitter );
365 mSplitter->
addWidget( mSnippetSplitter );
367 QWidget *editorAndCryptoStateIndicators =
new QWidget( mSplitter );
375 connect( editor, SIGNAL(textChanged()),
376 this, SLOT(slotEditorTextChanged()) );
377 mComposerBase->setEditor( editor );
378 vbox->
addWidget( mCryptoStateIndicatorWidget );
381 mSnippetSplitter->
insertWidget( 0, editorAndCryptoStateIndicators );
383 sigController->setEditor( editor );
385 mHeadersToEditorSplitter->
addWidget( mSplitter );
386 editor->setAcceptDrops(
true );
387 connect(sigController, SIGNAL(signatureAdded()), mComposerBase->editor(), SLOT(startExternalEditor()));
389 connect( mComposerBase->dictionary(), SIGNAL(dictionaryChanged(
QString)),
390 this, SLOT(slotSpellCheckingLanguage(
QString)) );
392 connect( editor, SIGNAL(languageChanged(
QString)),
393 this, SLOT(slotLanguageChanged(
QString)) );
394 connect( editor, SIGNAL(spellCheckStatus(
QString)),
395 this, SLOT(slotSpellCheckingStatus(
QString)) );
396 connect( editor, SIGNAL(insertModeChanged()),
397 this, SLOT(slotOverwriteModeChanged()) );
398 connect(editor,SIGNAL(spellCheckingFinished()),
this,SLOT(slotCheckSendNow()));
399 mSnippetWidget =
new SnippetWidget( editor, actionCollection(), mSnippetSplitter );
401 mSnippetSplitter->
addWidget( mSnippetWidget );
403 mSnippetSplitterCollapser =
new PimCommon::SplitterCollapser(mSnippetWidget, mSnippetSplitter);
414 setMinimumSize( 200, 200 );
421 mCustomToolsWidget =
new PimCommon::CustomToolsWidget(
this);
422 mSplitter->
addWidget(mCustomToolsWidget);
423 connect(mCustomToolsWidget, SIGNAL(insertShortUrl(
QString)),
this, SLOT(slotInsertShortUrl(
QString)));
425 MessageComposer::AttachmentModel* attachmentModel =
new MessageComposer::AttachmentModel(
this );
428 connect(attachmentView,SIGNAL(modified(
bool)),SLOT(
setModified(
bool)));
431 mComposerBase->setAttachmentModel( attachmentModel );
432 mComposerBase->setAttachmentController( attachmentController );
435 connect(mAttachmentMissing, SIGNAL(attachMissingFile()),
this, SLOT(slotAttachMissingFile()));
436 connect(mAttachmentMissing, SIGNAL(explicitClosedMissingAttachment()),
this, SLOT(slotExplicitClosedMissingAttachment()));
440 connect(mPotentialPhishingEmailWarning, SIGNAL(sendNow()),
this, SLOT(slotCheckSendNowStep2()));
441 v->
addWidget(mPotentialPhishingEmailWarning);
444 m_verifyMissingAttachment =
new QTimer(
this);
447 connect( m_verifyMissingAttachment, SIGNAL(timeout()),
this, SLOT(slotVerifyMissingAttachmentTimeout()) );
449 connect( attachmentController, SIGNAL(fileAttached()), mAttachmentMissing, SLOT(slotFileAttached()) );
455 setupStatusBar(attachmentView->
widget());
459 updateSignatureAndEncryptionStateIndicators();
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 );
502 connect(mStorageService, SIGNAL(insertShareLink(
QString)),
this, SLOT(slotShareLinkDone(
QString)));
506 KMComposeWin::~KMComposeWin()
513 if ( mFolder.isValid() && mMsg && isModified() ) {
515 saveDraftJob->
start();
518 delete mComposerBase;
522 void KMComposeWin::slotSpellCheckingLanguage(
const QString& language)
524 mComposerBase->editor()->setSpellCheckingLanguage(language );
525 mEdtSubject->setSpellCheckingLanguage(language );
530 return mdbusObjectPath;
533 void KMComposeWin::slotEditorTextChanged()
535 const bool textIsNotEmpty = !mComposerBase->editor()->document()->isEmpty();
536 mFindText->setEnabled( textIsNotEmpty );
537 mFindNextText->setEnabled( textIsNotEmpty );
538 mReplaceText->setEnabled( textIsNotEmpty );
539 mSelectAll->setEnabled( textIsNotEmpty );
540 if (m_verifyMissingAttachment && !m_verifyMissingAttachment->
isActive()) {
541 m_verifyMissingAttachment->
start();
564 kDebug() <<
"addAttachment and sending!";
565 const int nbUrl = urls.count();
566 for (
int i =0; i < nbUrl; ++i ) {
567 mComposerBase->addAttachment( urls.at(i), comment, true );
576 mComposerBase->addAttachment( url, comment,
false );
581 KMime::Headers::contentEncoding cte,
587 mComposerBase->addAttachment( name, name, charset, data, mimeType );
591 void KMComposeWin::readConfig(
bool reload )
603 mEdtFrom->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
604 mComposerBase->recipientsEditor()->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
605 mEdtReplyTo->setCompletionMode( (KGlobalSettings::Completion)
GlobalSettings::self()->completionMode() );
607 if ( MessageCore::GlobalSettings::self()->useDefaultFonts() ) {
608 mBodyFont = KGlobalSettings::generalFont();
609 mFixedFont = KGlobalSettings::fixedFont();
612 mFixedFont = MessageViewer::GlobalSettings::self()->fixedFont();
616 mEdtFrom->setFont( mBodyFont );
617 mEdtReplyTo->setFont( mBodyFont );
618 mEdtSubject->setFont( mBodyFont );
622 if ( siz.
width() < 200 ) {
625 if ( siz.
height() < 200 ) {
634 defaults << (int)(width() * 0.8) << (int)(width() * 0.2);
635 mSnippetSplitter->
setSizes( defaults );
639 mComposerBase->identityCombo()->setCurrentIdentity( mId );
640 kDebug() << mComposerBase->identityCombo()->currentIdentityName();
641 const KPIMIdentities::Identity & ident =
642 kmkernel->identityManager()->identityForUoid( mId );
644 if ( mBtnTransport->
isChecked() && currentTransport != -1 ) {
645 const Transport *transport = TransportManager::self()->transportById( currentTransport );
647 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
654 mComposerBase->dictionary()->setCurrentByDictionaryName(
GlobalSettings::self()->previousDictionary() );
656 mComposerBase->dictionary()->setCurrentByDictionaryName( ident.dictionary() );
662 }
else if ( !ident.fcc().isEmpty() ) {
663 fccName = ident.fcc();
669 void KMComposeWin::writeConfig(
void )
673 if ( !mIgnoreStickyFields ) {
674 GlobalSettings::self()->setCurrentTransport( mComposerBase->transportComboBox()->currentText() );
678 GlobalSettings::self()->setPreviousIdentity( mComposerBase->identityCombo()->currentIdentity() );
681 GlobalSettings::self()->setPreviousDictionary( mComposerBase->dictionary()->currentDictionaryName() );
683 mAutoSpellCheckingAction->isChecked() );
684 MessageViewer::GlobalSettings::self()->setUseFixedFont( mFixedFontAction->isChecked() );
685 if ( !mForceDisableHtml )
686 GlobalSettings::self()->setUseHtmlMarkup( mComposerBase->editor()->textMode() == KMeditor::Rich );
690 saveMainWindowSettings(
KMKernel::self()->config()->group(
"Composer" ) );
691 if ( mSnippetAction->isChecked() )
692 GlobalSettings::setSnippetSplitterPosition( mSnippetSplitter->
sizes() );
698 MessageComposer::Composer* KMComposeWin::createSimpleComposer()
701 if( !mOriginalPreferredCharset.
isEmpty() ) {
702 charsets.
insert( 0, mOriginalPreferredCharset );
704 mComposerBase->setFrom( from() );
705 mComposerBase->setReplyTo( replyTo() );
706 mComposerBase->setSubject( subject() );
707 mComposerBase->setCharsets( charsets );
708 return mComposerBase->createSimpleComposer();
711 bool KMComposeWin::canSignEncryptAttachments()
const
713 return cryptoMessageFormat() != Kleo::InlineOpenPGPFormat;
717 void KMComposeWin::slotUpdateView(
void )
726 KToggleAction *act = ::qobject_cast<KToggleAction *>( sender() );
732 if ( act == mAllFieldsAction ) {
734 }
else if ( act == mIdentityAction ) {
736 }
else if ( act == mTransportAction ) {
738 }
else if ( act == mFromAction ) {
740 }
else if ( act == mReplyToAction ) {
742 }
else if ( act == mSubjectAction ) {
744 }
else if ( act == mFccAction ) {
746 }
else if ( act == mDictionaryAction ) {
749 kDebug() <<
"Something is wrong (Oh, yeah?)";
756 if ( !act->isChecked() ) {
759 mShowHeaders = mShowHeaders & ~id;
761 mShowHeaders = abs( mShowHeaders );
768 mShowHeaders = -abs( mShowHeaders );
771 rethinkFields(
true );
774 int KMComposeWin::calcColumnWidth(
int which,
long allShowing,
int width )
const
776 if ( ( allShowing & which ) == 0 ) {
784 w = mDictionaryLabel;
785 }
else if ( which ==
HDR_FCC ) {
799 w->
setBuddy( mComposerBase->editor() );
805 void KMComposeWin::rethinkFields(
bool fromSlot )
811 if ( mShowHeaders < 0 ) {
814 showHeaders = mShowHeaders;
817 for ( mask=1, mNumHeaders=0; mask<=showHeaders; mask<<=1 ) {
818 if ( ( showHeaders & mask ) != 0 ) {
826 mGrid->
setMargin( KDialog::marginHint() / 2 );
835 mLabelWidth = mComposerBase->recipientsEditor()->setFirstColumnWidth( 0 );
836 mLabelWidth = calcColumnWidth(
HDR_IDENTITY, showHeaders, mLabelWidth );
837 mLabelWidth = calcColumnWidth(
HDR_DICTIONARY, showHeaders, mLabelWidth );
838 mLabelWidth = calcColumnWidth(
HDR_FCC, showHeaders, mLabelWidth );
839 mLabelWidth = calcColumnWidth(
HDR_TRANSPORT, showHeaders, mLabelWidth );
840 mLabelWidth = calcColumnWidth(
HDR_FROM, showHeaders, mLabelWidth );
841 mLabelWidth = calcColumnWidth(
HDR_REPLY_TO, showHeaders, mLabelWidth );
842 mLabelWidth = calcColumnWidth(
HDR_SUBJECT, showHeaders, mLabelWidth );
845 mAllFieldsAction->setChecked( showHeaders ==
HDR_ALL );
849 mIdentityAction->setChecked( abs( mShowHeaders )&
HDR_IDENTITY );
851 rethinkHeaderLine( showHeaders,
HDR_IDENTITY, row, mLblIdentity, mComposerBase->identityCombo(),
855 mDictionaryAction->setChecked( abs( mShowHeaders )&
HDR_DICTIONARY );
857 rethinkHeaderLine( showHeaders,
HDR_DICTIONARY, row, mDictionaryLabel,
858 mComposerBase->dictionary(), mBtnDictionary );
861 mFccAction->setChecked( abs( mShowHeaders )&
HDR_FCC );
863 rethinkHeaderLine( showHeaders,
HDR_FCC, row, mLblFcc, mFccFolder, mBtnFcc );
866 mTransportAction->setChecked( abs( mShowHeaders )&
HDR_TRANSPORT );
868 rethinkHeaderLine( showHeaders,
HDR_TRANSPORT, row, mLblTransport, mComposerBase->transportComboBox(),
872 mFromAction->setChecked( abs( mShowHeaders )&
HDR_FROM );
874 rethinkHeaderLine( showHeaders,
HDR_FROM, row, mLblFrom, mEdtFrom );
879 mReplyToAction->setChecked( abs( mShowHeaders )&
HDR_REPLY_TO );
881 rethinkHeaderLine( showHeaders,
HDR_REPLY_TO, row, mLblReplyTo, mEdtReplyTo );
883 prevFocus = connectFocusMoving( prevFocus, mEdtReplyTo );
886 mGrid->
addWidget( mComposerBase->recipientsEditor(), row, 0, 1, 3 );
888 if ( showHeaders & HDR_REPLY_TO ) {
889 connect( mEdtReplyTo, SIGNAL(focusDown()), mComposerBase->recipientsEditor(),
890 SLOT(setFocusTop()) );
891 connect( mComposerBase->recipientsEditor(), SIGNAL(focusUp()), mEdtReplyTo,
894 connect( mEdtFrom, SIGNAL(focusDown()), mComposerBase->recipientsEditor(),
895 SLOT(setFocusTop()) );
896 connect( mComposerBase->recipientsEditor(), SIGNAL(focusUp()), mEdtFrom,
900 connect( mComposerBase->recipientsEditor(), SIGNAL(focusDown()), mEdtSubject,
902 connect( mEdtSubject, SIGNAL(focusUp()), mComposerBase->recipientsEditor(),
903 SLOT(setFocusBottom()) );
905 prevFocus = mComposerBase->recipientsEditor();
908 mSubjectAction->setChecked( abs( mShowHeaders )&
HDR_SUBJECT );
910 rethinkHeaderLine(showHeaders,
HDR_SUBJECT, row, mLblSubject, mEdtSubject );
911 connectFocusMoving( mEdtSubject, mComposerBase->editor() );
913 assert( row <= mNumHeaders + 1 );
918 mIdentityAction->setEnabled(!mAllFieldsAction->isChecked());
919 mDictionaryAction->setEnabled( !mAllFieldsAction->isChecked() );
920 mTransportAction->setEnabled(!mAllFieldsAction->isChecked());
921 mFromAction->setEnabled(!mAllFieldsAction->isChecked());
922 if ( mReplyToAction ) {
923 mReplyToAction->setEnabled( !mAllFieldsAction->isChecked() );
925 mFccAction->setEnabled( !mAllFieldsAction->isChecked() );
926 mSubjectAction->setEnabled( !mAllFieldsAction->isChecked() );
927 mComposerBase->recipientsEditor()->setFirstColumnWidth( mLabelWidth );
932 connect( prev, SIGNAL(focusDown()), next, SLOT(setFocus()) );
933 connect( next, SIGNAL(focusUp()), prev, SLOT(setFocus()) );
939 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int &aRow,
943 if ( aValue & aMask ) {
967 void KMComposeWin::rethinkHeaderLine(
int aValue,
int aMask,
int &aRow,
971 if ( aValue & aMask ) {
992 void KMComposeWin::applyTemplate( uint uoid, uint uOldId )
994 const KPIMIdentities::Identity &ident =
kmkernel->identityManager()->identityForUoid( uoid );
995 if ( ident.isNull() )
997 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-Templates", mMsg.get(), ident.templates(),
"utf-8" );
998 mMsg->setHeader( header );
1000 TemplateParser::TemplateParser::Mode mode;
1001 switch ( mContext ) {
1003 mode = TemplateParser::TemplateParser::NewMessage;
1006 mode = TemplateParser::TemplateParser::Reply;
1009 mode = TemplateParser::TemplateParser::ReplyAll;
1012 mode = TemplateParser::TemplateParser::Forward;
1018 if ( mode == TemplateParser::TemplateParser::NewMessage ) {
1019 TemplateParser::TemplateParser parser( mMsg, mode );
1020 parser.setSelection( mTextSelection );
1021 parser.setAllowDecryption( MessageViewer::GlobalSettings::self()->automaticDecrypt() );
1022 parser.setIdentityManager(
KMKernel::self()->identityManager() );
1023 if ( !mCustomTemplate.
isEmpty() )
1024 parser.process( mCustomTemplate, mMsg, mCollectionForNewMessage );
1026 parser.processWithIdentity( uoid, mMsg, mCollectionForNewMessage );
1027 mComposerBase->updateTemplate( mMsg );
1028 updateSignature(uoid, uOldId);
1032 if ( mMsg->headerByType(
"X-KMail-Link-Message" ) ) {
1033 Akonadi::Item::List items;
1034 foreach(
const QString& serNumStr, mMsg->headerByType(
"X-KMail-Link-Message" )->asUnicodeString().split(
QLatin1Char(
',') ) )
1035 items << Akonadi::Item( serNumStr.
toLongLong() );
1038 Akonadi::ItemFetchJob *job =
new Akonadi::ItemFetchJob( items,
this );
1039 job->fetchScope().fetchFullPayload(
true );
1040 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
1041 job->setProperty(
"mode", (
int)mode );
1042 job->setProperty(
"uoid", uoid );
1043 job->setProperty(
"uOldid", uOldId );
1044 connect( job, SIGNAL(result(
KJob*)), SLOT(slotDelayedApplyTemplate(
KJob*)) );
1048 void KMComposeWin::slotDelayedApplyTemplate(
KJob *job )
1050 const Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job );
1051 const Akonadi::Item::List items = fetchJob->items();
1053 const TemplateParser::TemplateParser::Mode mode =
static_cast<TemplateParser::TemplateParser::Mode
>( fetchJob->property(
"mode" ).toInt() );
1054 const uint uoid = fetchJob->property(
"uoid" ).toUInt();
1055 const uint uOldId = fetchJob->property(
"uOldid" ).toUInt();
1057 TemplateParser::TemplateParser parser( mMsg, mode );
1058 parser.setSelection( mTextSelection );
1059 parser.setAllowDecryption( MessageViewer::GlobalSettings::self()->automaticDecrypt() );
1060 parser.setWordWrap( MessageComposer::MessageComposerSettings::self()->wordWrap(), MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
1061 parser.setIdentityManager(
KMKernel::self()->identityManager() );
1062 foreach (
const Akonadi::Item &item, items ) {
1063 if ( !mCustomTemplate.
isEmpty() )
1064 parser.process( mCustomTemplate, MessageCore::Util::message( item ) );
1066 parser.processWithIdentity( uoid, MessageCore::Util::message( item ) );
1068 mComposerBase->updateTemplate( mMsg );
1069 updateSignature(uoid, uOldId);
1072 void KMComposeWin::updateSignature(uint uoid, uint uOldId)
1074 const KPIMIdentities::Identity &ident =
kmkernel->identityManager()->identityForUoid( uoid );
1075 const KPIMIdentities::Identity &oldIdentity =
kmkernel->identityManager()->identityForUoid( uOldId );
1076 mComposerBase->identityChanged( ident, oldIdentity,
true );
1081 mCollectionForNewMessage = folder;
1084 void KMComposeWin::setQuotePrefix( uint uoid )
1086 QString quotePrefix = mMsg->headerByType(
"X-KMail-QuotePrefix" ) ? mMsg->headerByType(
"X-KMail-QuotePrefix" )->asUnicodeString() :
QString();
1087 if ( quotePrefix.
isEmpty() ) {
1091 if ( mCustomTemplate.
isEmpty() ) {
1092 const KPIMIdentities::Identity &identity =
kmkernel->identityManager()->identityForUoidOrDefault( uoid );
1095 TemplateParser::Templates quoteTemplate(
1096 TemplateParser::TemplatesConfiguration::configIdString( identity.uoid() ) );
1097 quotePrefix = quoteTemplate.quoteString();
1100 mComposerBase->editor()->setQuotePrefixName( MessageCore::StringUtil::formatString( quotePrefix,
1101 mMsg->from()->asUnicodeString() ) );
1105 void KMComposeWin::setupActions(
void )
1109 if ( MessageComposer::MessageComposerSettings::self()->sendImmediate() ) {
1111 KAction *action =
new KAction(KIcon(
QLatin1String(
"mail-send")), i18n(
"&Send Mail"),
this);
1112 actionCollection()->addAction(
QLatin1String(
"send_mail_default"), action );
1113 connect( action, SIGNAL(triggered(
bool)), SLOT(
slotSendNow()));
1115 action =
new KAction(KIcon(
QLatin1String(
"mail-send")), i18n(
"Send Mail Using Shortcut"),
this);
1116 actionCollection()->addAction(
QLatin1String(
"send_mail"), action );
1117 action->setShortcut(
QKeySequence( Qt::CTRL + Qt::Key_Return ) );
1118 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSendNowByShortcut()));
1123 actActionNowMenu->setIcon(KIcon(
QLatin1String(
"mail-send") ));
1124 actActionNowMenu->setText( i18n(
"&Send Mail Via") );
1125 actActionNowMenu->setIconText( i18n(
"Send" ) );
1126 actionCollection()->addAction(
QLatin1String(
"send_default_via"), actActionNowMenu );
1128 action =
new KAction( KIcon(
QLatin1String(
"mail-queue") ), i18n(
"Send &Later"),
this );
1129 actionCollection()->addAction(
QLatin1String(
"send_alternative"), action );
1130 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSendLater()) );
1132 actActionLaterMenu->setIcon(KIcon(
QLatin1String(
"mail-queue") ));
1133 actActionLaterMenu->setText(i18n(
"Send &Later Via"));
1134 actActionLaterMenu->setIconText( i18nc(
"Queue the message for sending at a later date",
"Queue" ) );
1135 actionCollection()->addAction(
QLatin1String(
"send_alternative_via"), actActionLaterMenu );
1139 KAction *action =
new KAction( KIcon(
QLatin1String(
"mail-queue") ), i18n(
"Send &Later"),
this );
1140 actionCollection()->addAction(
QLatin1String(
"send_mail"), action );
1141 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSendLater()) );
1142 action->setShortcut(
QKeySequence( Qt::CTRL + Qt::Key_Return ) );
1144 actActionLaterMenu->setIcon(KIcon(
QLatin1String(
"mail-queue") ));
1145 actActionLaterMenu->setText( i18n(
"Send &Later Via") );
1146 actionCollection()->addAction(
QLatin1String(
"send_default_via"), actActionLaterMenu );
1148 action =
new KAction( KIcon(
QLatin1String(
"mail-send") ), i18n(
"&Send Mail"),
this );
1149 actionCollection()->addAction(
QLatin1String(
"send_alternative"), action );
1150 connect( action, SIGNAL(triggered(
bool)), SLOT(
slotSendNow()) );
1154 actActionNowMenu->setIcon(KIcon(
QLatin1String(
"mail-send") ));
1155 actActionNowMenu->setText(i18n(
"&Send Mail Via"));
1156 actionCollection()->addAction(
QLatin1String(
"send_alternative_via"), actActionNowMenu );
1160 connect( actActionNowMenu, SIGNAL(triggered(
bool)),
this,
1162 connect( actActionLaterMenu, SIGNAL(triggered(
bool)),
this,
1163 SLOT(slotSendLater()) );
1164 connect( actActionNowMenu, SIGNAL(transportSelected(MailTransport::Transport*)),
this,
1165 SLOT(slotSendNowVia(MailTransport::Transport*)));
1166 connect( actActionLaterMenu, SIGNAL(transportSelected(MailTransport::Transport*)),
this,
1167 SLOT(slotSendLaterVia(MailTransport::Transport*)));
1170 KAction *action =
new KAction( KIcon(
QLatin1String(
"document-save") ), i18n(
"Save as &Draft"),
this );
1171 actionCollection()->addAction(
QLatin1String(
"save_in_drafts"), action );
1172 action->setHelpText(i18n(
"Save email in Draft folder"));
1173 action->setShortcut(
QKeySequence(Qt::CTRL + Qt::Key_S));
1174 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveDraft()) );
1176 action =
new KAction( KIcon(
QLatin1String(
"document-save") ), i18n(
"Save as &Template"),
this );
1177 action->setHelpText(i18n(
"Save email in Template folder"));
1178 actionCollection()->addAction(
QLatin1String(
"save_in_templates"), action );
1179 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveTemplate()) );
1181 action =
new KAction( KIcon(
QLatin1String(
"document-save") ), i18n(
"Save as &File"),
this );
1182 action->setHelpText(i18n(
"Save email as text or html file"));
1183 actionCollection()->addAction(
QLatin1String(
"save_as_file"), action );
1184 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSaveAsFile()) );
1186 action =
new KAction(KIcon(
QLatin1String(
"contact-new" ) ), i18n(
"New AddressBook Contact..."),
this);
1187 actionCollection()->addAction(
QLatin1String(
"kmail_new_addressbook_contact"), action );
1188 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(slotCreateAddressBookContact()));
1192 action =
new KAction(KIcon(
QLatin1String(
"document-open")), i18n(
"&Insert Text File..."),
this);
1193 actionCollection()->addAction(
QLatin1String(
"insert_file"), action );
1194 connect(action, SIGNAL(triggered(
bool)), SLOT(slotInsertFile()));
1196 mRecentAction =
new KRecentFilesAction( KIcon(
QLatin1String(
"document-open") ),
1197 i18n(
"&Insert Recent Text File" ),
this );
1198 actionCollection()->addAction(
QLatin1String(
"insert_file_recent"), mRecentAction );
1199 connect(mRecentAction, SIGNAL(urlSelected(KUrl)),
1200 SLOT(slotInsertRecentFile(KUrl)));
1201 connect(mRecentAction, SIGNAL(recentListCleared()),
1202 SLOT(slotRecentListFileClear()));
1205 action =
new KAction(KIcon(
QLatin1String(
"x-office-address-book")), i18n(
"&Address Book"),
this);
1206 action->setHelpText(i18n(
"Open Address Book"));
1207 actionCollection()->addAction(
QLatin1String(
"addressbook"), action );
1208 if (KStandardDirs::findExe(
QLatin1String(
"kaddressbook")).isEmpty())
1209 action->setEnabled(
false);
1210 connect(action, SIGNAL(triggered(
bool)), SLOT(slotAddressBook()));
1211 action =
new KAction(KIcon(
QLatin1String(
"mail-message-new")), i18n(
"&New Composer"),
this);
1212 actionCollection()->addAction(
QLatin1String(
"new_composer"), action );
1213 connect(action, SIGNAL(triggered(
bool)), SLOT(slotNewComposer()));
1214 action->setShortcuts( KStandardShortcut::shortcut( KStandardShortcut::New ) );
1216 action =
new KAction( i18n(
"Select &Recipients..."),
this );
1217 actionCollection()->addAction(
QLatin1String(
"select_recipients"), action );
1218 connect( action, SIGNAL(triggered(
bool)),
1219 mComposerBase->recipientsEditor(), SLOT(selectRecipients()) );
1220 action =
new KAction( i18n(
"Save &Distribution List..."),
this );
1221 actionCollection()->addAction(
QLatin1String(
"save_distribution_list"), action );
1222 connect( action, SIGNAL(triggered(
bool)),
1223 mComposerBase->recipientsEditor(), SLOT(saveDistributionList()) );
1225 KStandardAction::print(
this, SLOT(slotPrint()), actionCollection() );
1226 if(KPrintPreview::isAvailable())
1227 KStandardAction::printPreview(
this, SLOT(slotPrintPreview()), actionCollection() );
1228 KStandardAction::close(
this, SLOT(slotClose()), actionCollection() );
1230 KStandardAction::undo( mGlobalAction, SLOT(slotUndo()), actionCollection() );
1231 KStandardAction::redo( mGlobalAction, SLOT(slotRedo()), actionCollection() );
1232 KStandardAction::cut( mGlobalAction, SLOT(slotCut()), actionCollection() );
1233 KStandardAction::copy( mGlobalAction, SLOT(slotCopy()), actionCollection() );
1234 KStandardAction::pasteText( mGlobalAction, SLOT(slotPaste()), actionCollection() );
1235 mSelectAll = KStandardAction::selectAll( mGlobalAction, SLOT(slotMarkAll()), actionCollection() );
1237 mFindText = KStandardAction::find( mComposerBase->editor(), SLOT(slotFind()), actionCollection() );
1238 mFindNextText = KStandardAction::findNext( mComposerBase->editor(), SLOT(slotFindNext()), actionCollection() );
1240 mReplaceText = KStandardAction::replace( mComposerBase->editor(), SLOT(slotReplace()), actionCollection() );
1241 actionCollection()->addAction( KStandardAction::Spelling,
QLatin1String(
"spellcheck"),
1242 mComposerBase->editor(), SLOT(checkSpelling()) );
1244 action =
new KAction( i18n(
"Paste as Attac&hment"),
this );
1245 actionCollection()->addAction(
QLatin1String(
"paste_att"), action );
1246 connect( action, SIGNAL(triggered(
bool)), SLOT(slotPasteAsAttachment()) );
1248 action =
new KAction( i18n(
"Cl&ean Spaces"),
this );
1249 actionCollection()->addAction(
QLatin1String(
"clean_spaces"), action );
1250 connect( action, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(cleanSpace()) );
1252 mFixedFontAction =
new KToggleAction( i18n(
"Use Fi&xed Font"),
this );
1253 actionCollection()->addAction(
QLatin1String(
"toggle_fixedfont"), mFixedFontAction );
1254 connect( mFixedFontAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateFont()) );
1255 mFixedFontAction->setChecked( MessageViewer::GlobalSettings::self()->useFixedFont() );
1258 mUrgentAction =
new KToggleAction(
1259 i18nc(
"@action:inmenu Mark the email as urgent.",
"&Urgent"),
this );
1260 actionCollection()->addAction(
QLatin1String(
"urgent"), mUrgentAction );
1261 mRequestMDNAction =
new KToggleAction( i18n(
"&Request Disposition Notification"),
this );
1262 actionCollection()->addAction(
QLatin1String(
"options_request_mdn"), mRequestMDNAction );
1266 actionCollection()->addAction(
QLatin1String(
"charsets"), mCodecAction );
1267 mWordWrapAction =
new KToggleAction( i18n(
"&Wordwrap" ),
this );
1268 actionCollection()->addAction(
QLatin1String(
"wordwrap"), mWordWrapAction );
1269 mWordWrapAction->setChecked( MessageComposer::MessageComposerSettings::self()->wordWrap() );
1272 mSnippetAction =
new KToggleAction( i18n(
"&Snippets"),
this );
1273 actionCollection()->addAction(
QLatin1String(
"snippets"), mSnippetAction );
1274 connect( mSnippetAction, SIGNAL(toggled(
bool)),
this, SLOT(slotSnippetWidgetVisibilityChanged(
bool)));
1277 mAutoSpellCheckingAction =
new KToggleAction( KIcon(
QLatin1String(
"tools-check-spelling") ),
1278 i18n(
"&Automatic Spellchecking"),
1280 actionCollection()->addAction(
QLatin1String(
"options_auto_spellchecking"), mAutoSpellCheckingAction );
1283 const bool spellCheckingEnabled = useKmailEditor && spellChecking;
1284 mAutoSpellCheckingAction->setEnabled( useKmailEditor );
1286 mAutoSpellCheckingAction->setChecked( spellCheckingEnabled );
1287 slotAutoSpellCheckingToggled( spellCheckingEnabled );
1288 connect( mAutoSpellCheckingAction, SIGNAL(toggled(
bool)),
1289 this, SLOT(slotAutoSpellCheckingToggled(
bool)) );
1290 connect( mComposerBase->editor(), SIGNAL(checkSpellingChanged(
bool)),
1291 this, SLOT(slotAutoSpellCheckingToggled(
bool)) );
1293 connect( mComposerBase->editor(), SIGNAL(textModeChanged(KRichTextEdit::Mode)),
1295 connect( mComposerBase->editor(), SIGNAL(externalEditorClosed()),
this, SLOT(slotExternalEditorClosed()));
1296 connect( mComposerBase->editor(), SIGNAL(externalEditorStarted()),
this, SLOT(slotExternalEditorStarted()));
1298 markupAction =
new KToggleAction( i18n(
"Rich Text Editing"),
this );
1299 markupAction->setIcon( KIcon(
QLatin1String(
"preferences-desktop-font" )) );
1300 markupAction->setIconText( i18n(
"Rich Text") );
1301 markupAction->setToolTip( i18n(
"Toggle rich text editing mode" ) );
1302 actionCollection()->addAction(
QLatin1String(
"html"), markupAction );
1303 connect( markupAction, SIGNAL(triggered(
bool)), SLOT(
slotToggleMarkup()) );
1305 mAllFieldsAction =
new KToggleAction( i18n(
"&All Fields"),
this);
1306 actionCollection()->addAction(
QLatin1String(
"show_all_fields"), mAllFieldsAction );
1307 connect( mAllFieldsAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1308 mIdentityAction =
new KToggleAction(i18n(
"&Identity"),
this);
1309 actionCollection()->addAction(
QLatin1String(
"show_identity"), mIdentityAction );
1310 connect( mIdentityAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1311 mDictionaryAction =
new KToggleAction(i18n(
"&Dictionary"),
this);
1312 actionCollection()->addAction(
QLatin1String(
"show_dictionary"), mDictionaryAction );
1313 connect( mDictionaryAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1314 mFccAction =
new KToggleAction(i18n(
"&Sent-Mail Folder"),
this);
1315 actionCollection()->addAction(
QLatin1String(
"show_fcc"), mFccAction );
1316 connect( mFccAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1317 mTransportAction =
new KToggleAction(i18n(
"&Mail Transport"),
this);
1318 actionCollection()->addAction(
QLatin1String(
"show_transport"), mTransportAction );
1319 connect( mTransportAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1320 mFromAction =
new KToggleAction(i18n(
"&From"),
this);
1321 actionCollection()->addAction(
QLatin1String(
"show_from"), mFromAction );
1322 connect( mFromAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1323 mReplyToAction =
new KToggleAction(i18n(
"&Reply To"),
this);
1324 actionCollection()->addAction(
QLatin1String(
"show_reply_to"), mReplyToAction );
1325 connect( mReplyToAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1326 mSubjectAction =
new KToggleAction(
1327 i18nc(
"@action:inmenu Show the subject in the composer window.",
"S&ubject"),
this);
1328 actionCollection()->addAction(
QLatin1String(
"show_subject"), mSubjectAction );
1329 connect(mSubjectAction, SIGNAL(triggered(
bool)), SLOT(slotUpdateView()));
1332 mAppendSignature =
new KAction( i18n(
"Append S&ignature"),
this );
1333 actionCollection()->addAction(
QLatin1String(
"append_signature"), mAppendSignature );
1334 connect( mAppendSignature, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(appendSignature()));
1336 mPrependSignature =
new KAction( i18n(
"Pr&epend Signature"),
this );
1337 actionCollection()->addAction(
QLatin1String(
"prepend_signature"), mPrependSignature );
1338 connect( mPrependSignature, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(prependSignature()) );
1340 mInsertSignatureAtCursorPosition =
new KAction( i18n(
"Insert Signature At C&ursor Position"),
this );
1341 actionCollection()->addAction(
QLatin1String(
"insert_signature_at_cursor_position"), mInsertSignatureAtCursorPosition );
1342 connect( mInsertSignatureAtCursorPosition, SIGNAL(triggered(
bool)), mComposerBase->signatureController(), SLOT(insertSignatureAtCursor()) );
1345 action =
new KAction( i18n(
"Insert Special Character..."),
this );
1346 actionCollection()->addAction(
QLatin1String(
"insert_special_character"), action );
1347 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(insertSpecialCharacter()) );
1351 actionCollection()->addAction(
QLatin1String(
"change_case_menu"), mChangeCaseMenu );
1352 connect(mChangeCaseMenu, SIGNAL(upperCase()),
this, SLOT(slotUpperCase()));
1353 connect(mChangeCaseMenu, SIGNAL(lowerCase()),
this, SLOT(slotLowerCase()));
1354 connect(mChangeCaseMenu, SIGNAL(sentenceCase()),
this, SLOT(slotSentenceCase()));
1356 mComposerBase->attachmentController()->createActions();
1358 setStandardToolBarMenuEnabled(
true );
1360 KStandardAction::keyBindings(
this, SLOT(slotEditKeys()), actionCollection());
1361 KStandardAction::configureToolbars(
this, SLOT(slotEditToolbars()), actionCollection());
1362 KStandardAction::preferences(
kmkernel, SLOT(slotShowConfigurationDialog()), actionCollection() );
1364 action =
new KAction( i18n(
"&Spellchecker..."),
this );
1365 action->setIconText( i18n(
"Spellchecker") );
1366 actionCollection()->addAction(
QLatin1String(
"setup_spellchecker"), action );
1367 connect( action, SIGNAL(triggered(
bool)), SLOT(slotSpellcheckConfig()) );
1369 mTranslateAction = mCustomToolsWidget->action(PimCommon::CustomToolsWidget::TranslatorTool);
1370 actionCollection()->addAction(
QLatin1String(
"translator"), mTranslateAction );
1372 mGenerateShortenUrl = mCustomToolsWidget->action(PimCommon::CustomToolsWidget::ShortUrlTool);
1373 actionCollection()->addAction(
QLatin1String(
"shorten_url"), mGenerateShortenUrl );
1375 mEncryptAction =
new KToggleAction(KIcon(
QLatin1String(
"document-encrypt")), i18n(
"&Encrypt Message"),
this);
1376 mEncryptAction->setIconText( i18n(
"Encrypt" ) );
1377 actionCollection()->addAction(
QLatin1String(
"encrypt_message"), mEncryptAction );
1378 mSignAction =
new KToggleAction(KIcon(
QLatin1String(
"document-sign")), i18n(
"&Sign Message"),
this);
1379 mSignAction->setIconText( i18n(
"Sign" ) );
1380 actionCollection()->addAction(
QLatin1String(
"sign_message"), mSignAction );
1381 const KPIMIdentities::Identity &ident =
1385 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1386 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1388 mLastEncryptActionState =
false;
1389 mLastSignActionState = ident.pgpAutoSign();
1391 changeCryptoAction();
1393 connect( mEncryptAction, SIGNAL(triggered(
bool)),
1394 SLOT(slotEncryptToggled(
bool)) );
1395 connect( mSignAction, SIGNAL(triggered(
bool)),
1396 SLOT(slotSignToggled(
bool)) );
1399 for (
int i=0 ; i<numCryptoMessageFormats ; ++i ) {
1400 listCryptoFormat.
push_back( Kleo::cryptoMessageFormatToLabel( cryptoMessageFormats[i] ) );
1403 mCryptoModuleAction =
new KSelectAction(i18n(
"&Cryptographic Message Format"),
this);
1404 actionCollection()->addAction(
QLatin1String(
"options_select_crypto"), mCryptoModuleAction );
1405 connect(mCryptoModuleAction, SIGNAL(triggered(
int)), SLOT(slotSelectCryptoModule()));
1406 mCryptoModuleAction->setItems( listCryptoFormat );
1407 mCryptoModuleAction->setToolTip( i18n(
"Select a cryptographic format for this message" ) );
1409 mComposerBase->editor()->createActions( actionCollection() );
1412 mFollowUpToggleAction =
new KToggleAction( i18n(
"Follow Up Mail..."),
this );
1413 actionCollection()->addAction(
QLatin1String(
"follow_up_mail"), mFollowUpToggleAction );
1414 connect( mFollowUpToggleAction, SIGNAL(triggered(
bool)),
this, SLOT(slotFollowUpMail(
bool)) );
1415 mFollowUpToggleAction->setEnabled(FollowUpReminder::FollowUpReminderUtil::followupReminderAgentEnabled());
1418 connect( toolBar(
QLatin1String(
"htmlToolBar") )->toggleViewAction(),
1419 SIGNAL(toggled(
bool)),
1426 if ( configureAction ) {
1427 configureAction->
setText( i18n(
"Configure KMail..." ) );
1431 void KMComposeWin::changeCryptoAction()
1433 const KPIMIdentities::Identity &ident =
1435 if ( !Kleo::CryptoBackendFactory::instance()->openpgp() && !Kleo::CryptoBackendFactory::instance()->smime() ) {
1437 mEncryptAction->setEnabled(
false );
1438 setEncryption(
false );
1439 mSignAction->setEnabled(
false );
1440 setSigning(
false );
1442 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp() &&
1443 !ident.pgpSigningKey().isEmpty();
1444 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime() &&
1445 !ident.smimeSigningKey().isEmpty();
1447 setEncryption(
false );
1448 setSigning( ( canOpenPGPSign || canSMIMESign ) && ident.pgpAutoSign() );
1454 void KMComposeWin::setupStatusBar(
QWidget *w )
1457 statusBar()->addWidget(w);
1459 statusBar()->insertItem(
QString(), 0, 1 );
1460 statusBar()->setItemAlignment( 0, Qt::AlignLeft | Qt::AlignVCenter );
1462 mStatusBarLabelToggledOverrideMode->
setStateString(i18n(
"OVR"), i18n(
"INS"));
1463 statusBar()->addPermanentWidget(mStatusBarLabelToggledOverrideMode,0 );
1464 connect(mStatusBarLabelToggledOverrideMode, SIGNAL(toggleModeChanged(
bool)),
this, SLOT(slotOverwriteModeWasChanged(
bool)));
1467 mStatusBarLabelSpellCheckingChangeMode->
setStateString(i18n(
"Spellcheck: on" ), i18n(
"Spellcheck: off" ));
1468 statusBar()->addPermanentWidget(mStatusBarLabelSpellCheckingChangeMode, 0 );
1469 connect(mStatusBarLabelSpellCheckingChangeMode, SIGNAL(toggleModeChanged(
bool)),
this, SLOT(slotAutoSpellCheckingToggled(
bool)));
1471 statusBar()->insertPermanentItem( i18n(
" Column: %1 ",
QLatin1String(
" " ) ), 2, 0 );
1472 statusBar()->insertPermanentItem(
1473 i18nc(
"Shows the linenumber of the cursor position.",
" Line: %1 "
1475 statusBar()->addPermanentWidget(progressStatusBarWidget->
littleProgress());
1479 void KMComposeWin::setupEditor(
void )
1482 mComposerBase->editor()->setTabStopWidth( fm.width(
QLatin1Char(
' ') ) * 8 );
1489 connect( mComposerBase->editor(), SIGNAL(cursorPositionChanged()),
1490 this, SLOT(slotCursorPositionChanged()) );
1491 slotCursorPositionChanged();
1495 QString KMComposeWin::subject()
const
1497 return MessageComposer::Util::cleanedUpHeaderString( mEdtSubject->toPlainText() );
1501 QString KMComposeWin::from()
const
1503 return MessageComposer::Util::cleanedUpHeaderString( mEdtFrom->text() );
1507 QString KMComposeWin::replyTo()
const
1509 if ( mEdtReplyTo ) {
1510 return MessageComposer::Util::cleanedUpHeaderString( mEdtReplyTo->text() );
1517 void KMComposeWin::decryptOrStripOffCleartextSignature(
QByteArray &body )
1521 if ( Kpgp::Module::prepareMessageForDecryption( body,
1522 pgpBlocks, nonPgpBlocks ) ) {
1525 if ( pgpBlocks.
count() == 1 ) {
1526 Kpgp::Block &block = pgpBlocks.
first();
1527 if ( ( block.type() == Kpgp::PgpMessageBlock ) ||
1528 ( block.type() == Kpgp::ClearsignedBlock ) ) {
1529 if ( block.type() == Kpgp::PgpMessageBlock ) {
1536 body = nonPgpBlocks.
first();
1537 body.
append( block.text() );
1547 mComposerBase->transportComboBox()->setCurrentTransport( transportId );
1552 if ( mEdtReplyTo ) {
1553 mEdtReplyTo->setText( replyTo );
1559 return mComposerBase->identityCombo()->currentIdentity();
1563 bool allowDecryption,
bool isModified )
1566 kDebug() <<
"newMsg == 0!";
1571 mLastSignActionState =
true;
1573 if ( lastEncryptState )
1574 mLastEncryptActionState =
true;
1576 mComposerBase->setMessage( newMsg, allowDecryption );
1580 mEdtFrom->setText( mMsg->from()->asUnicodeString() );
1581 mEdtSubject->setText( mMsg->subject()->asUnicodeString() );
1587 if ( mMsg->headerByType(
"X-KMail-QuotePrefix" ) )
1588 mComposerBase->editor()->setQuotePrefixName( mMsg->headerByType(
"X-KMail-QuotePrefix" )->asUnicodeString() );
1590 const bool stickyIdentity = mBtnIdentity->
isChecked() && !mIgnoreStickyFields;
1591 bool messageHasIdentity =
false;
1592 if( newMsg->headerByType(
"X-KMail-Identity") &&
1593 !newMsg->headerByType(
"X-KMail-Identity")->asUnicodeString().isEmpty() )
1594 messageHasIdentity =
true;
1595 if ( !stickyIdentity && messageHasIdentity )
1596 mId = newMsg->headerByType(
"X-KMail-Identity" )->asUnicodeString().toUInt();
1600 if ( !stickyIdentity ) {
1601 disconnect( mComposerBase->identityCombo(),SIGNAL(
identityChanged(uint)),
1602 this, SLOT(slotIdentityChanged(uint)) ) ;
1606 mComposerBase->identityCombo()->setCurrentIdentity( mId );
1607 const uint idToApply = mId;
1608 if ( !stickyIdentity ) {
1609 connect( mComposerBase->identityCombo(),SIGNAL(
identityChanged(uint)),
1610 this, SLOT(slotIdentityChanged(uint)) );
1615 if ( messageHasIdentity ) {
1616 mId = newMsg->headerByType(
"X-KMail-Identity")->asUnicodeString().toUInt();
1618 mId = im->defaultIdentity().uoid();
1625 slotIdentityChanged( idToApply,
true );
1627 const KPIMIdentities::Identity &ident = im->identityForUoid( mComposerBase->identityCombo()->currentIdentity() );
1629 const bool stickyTransport = mBtnTransport->
isChecked() && !mIgnoreStickyFields;
1630 if( stickyTransport ) {
1631 mComposerBase->transportComboBox()->setCurrentTransport( ident.transport().toInt() );
1638 if( newMsg->headerByType(
"Disposition-Notification-To" ) ) {
1639 QString mdnAddr = newMsg->headerByType(
"Disposition-Notification-To" )->asUnicodeString();
1640 mRequestMDNAction->setChecked( ( !mdnAddr.
isEmpty() &&
1641 im->thatIsMe( mdnAddr ) ) ||
1645 if ( newMsg->headerByType(
"X-PRIORITY" ) && newMsg->headerByType(
"Priority" ) )
1647 const QString xpriority = newMsg->headerByType(
"X-PRIORITY" )->asUnicodeString();
1648 const QString priority = newMsg->headerByType(
"Priority" )->asUnicodeString();
1650 mUrgentAction->setChecked(
true );
1653 if ( !ident.isXFaceEnabled() || ident.xface().isEmpty() ) {
1654 if( mMsg->headerByType(
"X-Face" ) )
1655 mMsg->headerByType(
"X-Face" )->clear();
1657 QString xface = ident.xface();
1659 int numNL = ( xface.
length() - 1 ) / 70;
1660 for (
int i = numNL; i > 0; --i ) {
1663 mMsg->setHeader(
new KMime::Headers::Generic(
"X-Face", mMsg.get(), xface,
"utf-8" ) );
1668 if ( mMsg->headerByType(
"X-KMail-SignatureActionEnabled" ) )
1669 mLastSignActionState = (mMsg->headerByType(
"X-KMail-SignatureActionEnabled" )->as7BitString().contains(
"true" ));
1670 if ( mMsg->headerByType(
"X-KMail-EncryptActionEnabled" ) )
1671 mLastEncryptActionState = (mMsg->headerByType(
"X-KMail-EncryptActionEnabled" )->as7BitString().contains(
"true") );
1672 if ( mMsg->headerByType(
"X-KMail-CryptoMessageFormat" ) ) {
1673 mCryptoModuleAction->setCurrentItem( format2cb( static_cast<Kleo::CryptoMessageFormat>(
1674 mMsg->headerByType(
"X-KMail-CryptoMessageFormat" )->asUnicodeString().toInt() ) ) );
1677 mLastIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
1678 mLastIdentityHasEncryptionKey = !ident.pgpEncryptionKey().isEmpty() || !ident.smimeEncryptionKey().isEmpty();
1680 if ( Kleo::CryptoBackendFactory::instance()->openpgp() || Kleo::CryptoBackendFactory::instance()->smime() ) {
1681 const bool canOpenPGPSign = Kleo::CryptoBackendFactory::instance()->openpgp() &&
1682 !ident.pgpSigningKey().isEmpty();
1683 const bool canSMIMESign = Kleo::CryptoBackendFactory::instance()->smime() &&
1684 !ident.smimeSigningKey().isEmpty();
1686 setEncryption( mLastEncryptActionState );
1687 setSigning( ( canOpenPGPSign || canSMIMESign ) && mLastSignActionState );
1689 updateSignatureAndEncryptionStateIndicators();
1692 if ( mMsg->headerByType(
"X-KMail-Fcc" ) ) {
1693 kmailFcc = mMsg->headerByType(
"X-KMail-Fcc" )->asUnicodeString();
1703 const bool stickyDictionary = mBtnDictionary->
isChecked() && !mIgnoreStickyFields;
1704 if ( !stickyDictionary ) {
1705 if ( mMsg->headerByType(
"X-KMail-Dictionary" ) ) {
1706 const QString dictionary = mMsg->headerByType(
"X-KMail-Dictionary" )->asUnicodeString();
1708 mComposerBase->dictionary()->setCurrentByDictionary( dictionary );
1711 mComposerBase->dictionary()->setCurrentByDictionaryName( ident.dictionary() );
1717 mEdtReplyTo->setText( mMsg->replyTo()->asUnicodeString() );
1719 KMime::Content *msgContent =
new KMime::Content;
1720 msgContent->setContent( mMsg->encodedContent() );
1721 msgContent->parse();
1722 MessageViewer::EmptySource emptySource;
1723 MessageViewer::ObjectTreeParser otp( &emptySource );
1724 emptySource.setAllowDecryption( allowDecryption );
1725 otp.parseObjectTree( msgContent );
1727 bool shouldSetCharset =
false;
1728 if ( ( mContext ==
Reply || mContext ==
ReplyToAll || mContext ==
Forward ) && MessageComposer::MessageComposerSettings::forceReplyCharset() )
1729 shouldSetCharset =
true;
1730 if ( shouldSetCharset && !otp.plainTextContentCharset().isEmpty() )
1731 mOriginalPreferredCharset = otp.plainTextContentCharset();
1736 #if 0 //TODO port to kmime
1739 if ( mMsg->numBodyParts() == 0 && otp.textualContent().isEmpty() ) {
1740 mCharset=mMsg->charset();
1741 if ( mCharset.isEmpty() || mCharset ==
"default" ) {
1742 mCharset = Util::defaultCharset();
1745 QByteArray bodyDecoded = mMsg->bodyDecoded();
1747 if ( allowDecryption ) {
1748 decryptOrStripOffCleartextSignature( bodyDecoded );
1751 const QTextCodec *codec = KMail::Util::codecForName( mCharset );
1753 mEditor->setText( codec->
toUnicode( bodyDecoded ) );
1760 if( (MessageComposer::MessageComposerSettings::self()->autoTextSignature()==
QLatin1String(
"auto" )) && mayAutoSign ) {
1767 if ( MessageComposer::MessageComposerSettings::self()->prependSignature() ) {
1768 QTimer::singleShot( 0, mComposerBase->signatureController(), SLOT(prependSignature()) );
1770 QTimer::singleShot( 0, mComposerBase->signatureController(), SLOT(appendSignature()) );
1773 mComposerBase->editor()->startExternalEditor();
1779 mPreventFccOverwrite = ( !kmailFcc.
isEmpty() && ident.fcc() != kmailFcc );
1783 void KMComposeWin::setAutoSaveFileName(
const QString& fileName)
1785 mComposerBase->setAutoSaveFileName( fileName );
1791 mTextSelection = selection;
1797 mCustomTemplate = customTemplate;
1802 mSigningAndEncryptionExplicitlyDisabled = v;
1814 Akonadi::Collection col;
1816 col = CommonKernel->sentCollectionFolder();
1818 col = Akonadi::Collection( idString.
toLongLong() );
1820 mComposerBase->setFcc( col );
1821 mFccFolder->setCollection( col );
1824 bool KMComposeWin::isComposerModified()
const
1826 return ( mComposerBase->editor()->document()->isModified() ||
1827 mEdtFrom->isModified() ||
1828 ( mEdtReplyTo && mEdtReplyTo->isModified() ) ||
1829 mComposerBase->recipientsEditor()->isModified() ||
1830 mEdtSubject->document()->isModified() );
1834 bool KMComposeWin::isModified()
const
1836 return mWasModified || isComposerModified();
1842 mWasModified = modified;
1843 changeModifiedState( modified );
1847 void KMComposeWin::changeModifiedState(
bool modified )
1849 mComposerBase->editor()->document()->setModified( modified );
1851 mEdtFrom->setModified(
false );
1852 if ( mEdtReplyTo ) mEdtReplyTo->setModified(
false );
1853 mComposerBase->recipientsEditor()->clearModified();
1854 mEdtSubject->document()->setModified(
false );
1859 bool KMComposeWin::queryClose ()
1861 if ( !mComposerBase->editor()->checkExternalEditorFinished() ) {
1864 if (
kmkernel->shuttingDown() || kapp->sessionSaving() ) {
1868 if ( isModified() ) {
1869 const bool istemplate = ( mFolder.isValid() && CommonKernel->folderIsTemplates( mFolder ) );
1870 const QString savebut = ( istemplate ?
1871 i18n(
"Re&save as Template") :
1872 i18n(
"&Save as Draft") );
1873 const QString savetext = ( istemplate ?
1874 i18n(
"Resave this message in the Templates folder. "
1875 "It can then be used at a later time.") :
1876 i18n(
"Save this message in the Drafts folder. "
1877 "It can then be edited and sent at a later time.") );
1879 const int rc = KMessageBox::warningYesNoCancel(
this,
1880 i18n(
"Do you want to save the message for later or discard it?"),
1881 i18n(
"Close Composer"),
1883 KStandardGuiItem::discard(),
1884 KStandardGuiItem::cancel());
1885 if ( rc == KMessageBox::Cancel ) {
1887 }
else if ( rc == KMessageBox::Yes ) {
1897 mComposerBase->cleanupAutoSave();
1899 if( !mMiscComposers.
isEmpty() ) {
1900 kWarning() <<
"Tried to close while composer was active";
1907 MessageComposer::ComposerViewBase::MissingAttachment KMComposeWin::userForgotAttachment()
1909 bool checkForForgottenAttachments = mCheckForForgottenAttachments &&
GlobalSettings::self()->showForgottenAttachmentWarning();
1911 if ( !checkForForgottenAttachments )
1912 return MessageComposer::ComposerViewBase::NoMissingAttachmentFound;
1914 mComposerBase->setSubject( subject() );
1915 MessageComposer::ComposerViewBase::MissingAttachment missingAttachments = mComposerBase->checkForMissingAttachments(
GlobalSettings::self()->attachmentKeywords() );
1917 return missingAttachments;
1920 void KMComposeWin::forceAutoSaveMessage()
1927 if ( isComposerModified() || force ) {
1928 applyComposerSetting( mComposerBase );
1929 mComposerBase->saveMailSettings();
1930 mComposerBase->autoSaveMessage();
1932 mWasModified =
true;
1933 changeModifiedState(
false );
1936 mComposerBase->updateAutoSave();
1940 bool KMComposeWin::encryptToSelf()
const
1942 return MessageComposer::MessageComposerSettings::self()->cryptoEncryptToSelf();
1947 void KMComposeWin::slotSendFailed(
const QString& msg,MessageComposer::ComposerViewBase::FailedType type)
1951 KMessageBox::sorry( mMainWidget, msg,
1952 (type == MessageComposer::ComposerViewBase::AutoSave) ? i18n(
"Autosave Message Failed" ) : i18n(
"Sending Message Failed" ) );
1959 addFollowupReminder(messageId);
1960 mComposerBase->cleanupAutoSave();
1961 mFolder = Akonadi::Collection();
1965 void KMComposeWin::addFollowupReminder(
const QString &messageId)
1967 const QDate date = mComposerBase->followUpDate();
1972 job->
setTo(replyTo());
1984 Kleo::CryptoMessageFormat KMComposeWin::cryptoMessageFormat()
const
1986 if ( !mCryptoModuleAction ) {
1987 return Kleo::AutoFormat;
1989 return cb2format( mCryptoModuleAction->currentItem() );
1995 mComposerBase->addAttachmentPart( msgPart );
1999 void KMComposeWin::slotAddressBook()
2005 void KMComposeWin::slotInsertFile()
2007 KUrl u = mComposerBase->editor()->insertFile();
2011 mRecentAction->addUrl( u );
2014 const QString encoding = MessageViewer::NodeHelper::encodingForName( u.fileEncoding() );
2019 const int mMaxRecentFiles = 30;
2020 while ( urls.count() > mMaxRecentFiles )
2022 while ( encodings.
count() > mMaxRecentFiles )
2025 if ( urls.count() != encodings.
count() ) {
2029 urls.prepend( u.prettyUrl() );
2030 encodings.
prepend( encoding );
2035 slotInsertRecentFile( u );
2039 void KMComposeWin::slotRecentListFileClear()
2042 KConfigGroup group( config,
"Composer" );
2043 group.deleteEntry(
"recent-urls");
2044 group.deleteEntry(
"recent-encodings");
2045 mRecentAction->saveEntries( config->group(
QString() ) );
2048 void KMComposeWin::slotInsertRecentFile(
const KUrl &u )
2050 if ( u.fileName().isEmpty() ) {
2058 const int index = urls.
indexOf( u.prettyUrl() );
2059 if ( index != -1 ) {
2060 encoding = encodings[ index ];
2062 kDebug()<<
" encoding not found so we can't insert text";
2067 MessageComposer::InsertTextFileJob *job =
new MessageComposer::InsertTextFileJob( mComposerBase->editor(), u );
2068 job->setEncoding( encoding );
2069 connect(job, SIGNAL(result(
KJob*)), SLOT(slotInsertTextFile(
KJob*)));
2073 bool KMComposeWin::showErrorMessage(
KJob*job)
2075 if ( job->error() ) {
2076 if ( static_cast<KIO::Job*>(job)->ui() )
2077 static_cast<KIO::Job*>(job)->ui()->showErrorMessage();
2079 kDebug()<<
" job->errorString() :"<<job->errorString();
2085 void KMComposeWin::slotInsertTextFile(
KJob*job)
2087 showErrorMessage(job);
2090 void KMComposeWin::slotSelectCryptoModule(
bool init )
2095 mComposerBase->attachmentModel()->setEncryptEnabled( canSignEncryptAttachments() );
2096 mComposerBase->attachmentModel()->setSignEnabled( canSignEncryptAttachments() );
2100 void KMComposeWin::slotUpdateFont()
2103 if ( !mFixedFontAction ) {
2106 mComposerBase->editor()->setFontForWholeText( mFixedFontAction->isChecked() ?
2107 mFixedFont : mBodyFont );
2112 return MessageCore::StringUtil::smartQuote( msg, MessageComposer::MessageComposerSettings::self()->lineWrapWidth() );
2126 if ( !forceAttachment ) {
2127 if ( mComposerBase->editor()->textMode() == KRichTextEdit::Rich && mComposerBase->editor()->isEnableImageActions() ) {
2132 const QAction *addAsInlineImageAction = menu.addAction( i18n(
"Add as &Inline Image") );
2133 menu.addAction( i18n(
"Add as &Attachment") );
2135 if ( selectedAction == addAsInlineImageAction ) {
2137 mComposerBase->editor()->insertImage( image, fi );
2139 }
else if( !selectedAction ) {
2149 KInputDialog::getText( i18n(
"KMail"), i18n(
"Name of the attachment:" ),
QString(), &ok,
this );
2159 if ( !urlList.isEmpty() ) {
2161 Akonadi::Item::List items;
2162 Akonadi::Collection::List collections;
2163 bool allLocalURLs =
true;
2165 foreach (
const KUrl &url, urlList ) {
2166 if ( !url.isLocalFile() ) {
2167 allLocalURLs =
false;
2169 const Akonadi::Item item = Akonadi::Item::fromUrl( url );
2170 if ( item.isValid() ) {
2173 const Akonadi::Collection collection = Akonadi::Collection::fromUrl( url );
2174 if ( collection.isValid() )
2175 collections << collection;
2179 if ( items.isEmpty() && collections.isEmpty() ) {
2180 if ( allLocalURLs || forceAttachment ) {
2181 foreach(
const KUrl &url, urlList ) {
2186 const QAction *addAsTextAction = p.addAction( i18np(
"Add URL into Message",
"Add URLs into Message", urlList.size() ) );
2187 const QAction *addAsAttachmentAction = p.addAction( i18np(
"Add File as &Attachment",
"Add Files as &Attachment", urlList.size() ) );
2190 if ( selectedAction == addAsTextAction ) {
2191 foreach(
const KUrl &url, urlList ) {
2192 mComposerBase->editor()->insertLink(url.url());
2194 }
else if ( selectedAction == addAsAttachmentAction ) {
2195 foreach(
const KUrl &url, urlList ) {
2202 if ( !items.isEmpty() ){
2203 Akonadi::ItemFetchJob *itemFetchJob =
new Akonadi::ItemFetchJob( items,
this );
2204 itemFetchJob->fetchScope().fetchFullPayload(
true );
2205 itemFetchJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
2208 if ( !collections.isEmpty() ) {
2217 void KMComposeWin::slotPasteAsAttachment()
2224 const QString attName = KInputDialog::getText(
2225 i18n(
"Insert clipboard text as attachment" ),
2226 i18n(
"Name of the attachment:" ),
2238 if (showErrorMessage(job)) {
2241 Akonadi::ItemFetchJob *fjob =
dynamic_cast<Akonadi::ItemFetchJob*
>( job );
2244 const Akonadi::Item::List items = fjob->items();
2246 if ( items.isEmpty() )
2249 if ( items.first().mimeType() == KMime::Message::mimeType() ) {
2251 if ( items.at( 0 ).isValid() && items.at( 0 ).parentCollection().isValid() ) {
2254 identity = fd->identity();
2259 foreach (
const Akonadi::Item &item, items ) {
2261 if ( item.hasPayload<KABC::Addressee>() ) {
2262 const KABC::Addressee contact = item.payload<KABC::Addressee>();
2263 attachmentName = contact.realName() +
QLatin1String(
".vcf" );
2266 PimCommon::VCardUtil vcardUtil;
2267 vcardUtil.adaptVcard(data);
2269 }
else if ( item.hasPayload<KABC::ContactGroup>() ) {
2270 const KABC::ContactGroup group = item.payload<KABC::ContactGroup>();
2272 Akonadi::ContactGroupExpandJob *expandJob =
new Akonadi::ContactGroupExpandJob( group,
this );
2273 expandJob->setProperty(
"groupName", attachmentName);
2274 connect( expandJob, SIGNAL(result(
KJob*)),
this, SLOT(slotExpandGroupResult(
KJob*)) );
2283 void KMComposeWin::slotExpandGroupResult(
KJob *job)
2285 Akonadi::ContactGroupExpandJob *expandJob = qobject_cast<Akonadi::ContactGroupExpandJob*>( job );
2286 Q_ASSERT( expandJob );
2288 const QString attachmentName = expandJob->property(
"groupName").toString();
2289 KABC::VCardConverter converter;
2290 const QByteArray groupData = converter.exportVCards(expandJob->contacts(), KABC::VCardConverter::v3_0);
2292 addAttachment( attachmentName, KMime::Headers::CEbase64,
QString(), groupData,
"text/x-vcard" );
2296 void KMComposeWin::slotClose()
2302 void KMComposeWin::slotNewComposer()
2305 KMime::Message::Ptr msg(
new KMime::Message );
2308 TemplateParser::TemplateParser parser(msg, TemplateParser::TemplateParser::NewMessage);
2310 parser.process(msg, mCollectionForNewMessage);
2313 bool forceCursorPosition = parser.cursorPositionWasSet();
2314 if (forceCursorPosition) {
2320 void KMComposeWin::slotUpdWinTitle()
2322 QString s( mEdtSubject->toPlainText() );
2325 if ( s.isEmpty() ) {
2333 void KMComposeWin::slotEncryptToggled(
bool on )
2335 setEncryption( on,
true );
2336 updateSignatureAndEncryptionStateIndicators();
2340 void KMComposeWin::setEncryption(
bool encrypt,
bool setByUser )
2342 bool wasModified = isModified();
2346 if ( !mEncryptAction->isEnabled() ) {
2351 else if ( encrypt && encryptToSelf() && !mLastIdentityHasEncryptionKey ) {
2353 KMessageBox::sorry(
this,
2354 i18n(
"<qt><p>You have requested that messages be "
2355 "encrypted to yourself, but the currently selected "
2356 "identity does not define an (OpenPGP or S/MIME) "
2357 "encryption key to use for this.</p>"
2358 "<p>Please select the key(s) to use "
2359 "in the identity configuration.</p>"
2361 i18n(
"Undefined Encryption Key") );
2368 mEncryptAction->setChecked( encrypt );
2370 updateSignatureAndEncryptionStateIndicators();
2374 mEncryptAction->setIcon( KIcon(
QLatin1String(
"document-encrypt") ) );
2376 mEncryptAction->setIcon( KIcon(
QLatin1String(
"document-decrypt") ) );
2380 if( canSignEncryptAttachments() ) {
2381 mComposerBase->attachmentModel()->setEncryptSelected( encrypt );
2386 void KMComposeWin::slotSignToggled(
bool on )
2388 setSigning( on,
true );
2389 updateSignatureAndEncryptionStateIndicators();
2393 void KMComposeWin::setSigning(
bool sign,
bool setByUser )
2395 bool wasModified = isModified();
2399 if ( !mSignAction->isEnabled() ) {
2404 if ( sign && !mLastIdentityHasSigningKey ) {
2406 KMessageBox::sorry(
this,
2407 i18n(
"<qt><p>In order to be able to sign "
2408 "this message you first have to "
2409 "define the (OpenPGP or S/MIME) signing key "
2411 "<p>Please select the key to use "
2412 "in the identity configuration.</p>"
2414 i18n(
"Undefined Signing Key") );
2421 mSignAction->setChecked( sign );
2424 updateSignatureAndEncryptionStateIndicators();
2427 if ( canSignEncryptAttachments() ) {
2428 mComposerBase->attachmentModel()->setSignSelected( sign );
2436 mComposerBase->editor()->enableWordWrap( validateLineWrapWidth() );
2441 int KMComposeWin::validateLineWrapWidth()
2443 int lineWrap = MessageComposer::MessageComposerSettings::self()->lineWrapWidth();
2444 if ((lineWrap == 0) || (lineWrap > 78))
2446 else if (lineWrap < 30)
2454 mComposerBase->editor()->disableWordWrap();
2460 mForceDisableHtml =
true;
2461 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2462 markupAction->setEnabled(
false );
2468 return mComposerBase && mComposerBase->isComposing();
2473 mCheckForForgottenAttachments =
false;
2478 mIgnoreStickyFields =
true;
2488 void KMComposeWin::slotPrint()
2490 printComposer(
false);
2493 void KMComposeWin::slotPrintPreview()
2495 printComposer(
true);
2498 void KMComposeWin::printComposer(
bool preview)
2500 MessageComposer::Composer* composer = createSimpleComposer();
2501 mMiscComposers.
append( composer );
2502 composer->setProperty(
"preview",preview);
2503 connect( composer, SIGNAL(result(
KJob*)),
2504 this, SLOT(slotPrintComposeResult(
KJob*)) );
2508 void KMComposeWin::slotPrintComposeResult(
KJob *job )
2510 const bool preview = job->property(
"preview").toBool();
2511 printComposeResult( job, preview );
2514 void KMComposeWin::printComposeResult(
KJob *job,
bool preview )
2516 Q_ASSERT( dynamic_cast< MessageComposer::Composer* >( job ) );
2517 MessageComposer::Composer* composer =
dynamic_cast< MessageComposer::Composer*
>( job );
2518 Q_ASSERT( mMiscComposers.
contains( composer ) );
2521 if( composer->error() == MessageComposer::Composer::NoError ) {
2523 Q_ASSERT( composer->resultMessages().size() == 1 );
2524 Akonadi::Item printItem;
2525 printItem.setPayload<KMime::Message::Ptr>( composer->resultMessages().first() );
2526 Akonadi::MessageFlags::copyMessageFlags(*(composer->resultMessages().first()), printItem);
2527 const bool isHtml = mComposerBase->editor()->textMode() == KMeditor::Rich;
2528 const MessageViewer::Viewer::DisplayFormatMessage format = isHtml ? MessageViewer::Viewer::Html : MessageViewer::Viewer::Text;
2530 0, format, isHtml );
2534 showErrorMessage(job);
2540 void KMComposeWin::doSend( MessageComposer::MessageSender::SendMethod method,
2541 MessageComposer::MessageSender::SaveIn saveIn )
2544 KMessageBox::sorry(
this, i18np(
"There is %1 file upload in progress.",
2545 "There are %1 file uploads in progress.",
2550 if ( method == MessageComposer::MessageSender::SendImmediate ) {
2551 if( !MessageComposer::Util::sendMailDispatcherIsOnline() ) {
2552 method = MessageComposer::MessageSender::SendLater;
2557 if ( saveIn == MessageComposer::MessageSender::SaveInNone ) {
2558 if ( KPIMUtils::firstEmailAddress( from() ).isEmpty() ) {
2559 if ( !( mShowHeaders &
HDR_FROM ) ) {
2561 rethinkFields(
false );
2563 mEdtFrom->setFocus();
2564 KMessageBox::sorry(
this,
2565 i18n(
"You must enter your email address in the "
2566 "From: field. You should also set your email "
2567 "address for all identities, so that you do "
2568 "not have to enter it for each message.") );
2571 if ( mComposerBase->to().isEmpty() ) {
2572 if ( mComposerBase->cc().isEmpty() && mComposerBase->bcc().isEmpty() ) {
2573 KMessageBox::information(
this,
2574 i18n(
"You must specify at least one receiver, "
2575 "either in the To: field or as CC or as BCC.") );
2579 int rc = KMessageBox::questionYesNo(
this,
2580 i18n(
"To: field is empty. "
2581 "Send message anyway?"),
2582 i18n(
"No To: specified"),
2583 KStandardGuiItem::yes(),
2584 KStandardGuiItem::no(),
2586 if ( rc == KMessageBox::No ) {
2592 if ( subject().isEmpty() ) {
2593 mEdtSubject->setFocus();
2595 KMessageBox::questionYesNo(
this,
2596 i18n(
"You did not specify a subject. "
2597 "Send message anyway?"),
2598 i18n(
"No Subject Specified"),
2599 KGuiItem(i18n(
"S&end as Is")),
2600 KGuiItem(i18n(
"&Specify the Subject")),
2602 if ( rc == KMessageBox::No ) {
2607 const MessageComposer::ComposerViewBase::MissingAttachment forgotAttachment = userForgotAttachment();
2608 if ( (forgotAttachment == MessageComposer::ComposerViewBase::FoundMissingAttachmentAndAddedAttachment) ||
2609 (forgotAttachment == MessageComposer::ComposerViewBase::FoundMissingAttachmentAndCancel) ) {
2614 setEnabled(
false );
2616 const QStringList recipients =
QStringList() << mComposerBase->to().trimmed() << mComposerBase->cc().trimmed() << mComposerBase->bcc().trimmed();
2619 const KPIMIdentities::Identity &ident =
KMKernel::self()->
identityManager()->identityForUoid( mComposerBase->identityCombo()->currentIdentity() );
2621 if ( !ident.isNull() ) {
2622 defaultDomainName = ident.defaultDomainName();
2625 job->setProperty(
"method", static_cast<int>( method ) );
2626 job->setProperty(
"saveIn", static_cast<int>( saveIn ) );
2627 connect( job, SIGNAL(result(
KJob*)), SLOT(slotDoDelayedSend(
KJob*)) );
2632 if( saveIn == MessageComposer::MessageSender::SaveInDrafts && mEncryptAction->isChecked() &&
2634 mComposerBase->to().isEmpty() && mComposerBase->cc().isEmpty() ) {
2636 KMessageBox::information(
this, i18n(
"You must specify at least one receiver "
2637 "in order to be able to encrypt a draft.")
2641 doDelayedSend( method, saveIn );
2645 void KMComposeWin::slotDoDelayedSend(
KJob *job )
2647 if ( job->error() ) {
2648 KMessageBox::error(
this, job->errorText() );
2656 if ( !validateJob->
isValid() ) {
2662 const MessageComposer::MessageSender::SendMethod method =
static_cast<MessageComposer::MessageSender::SendMethod
>( job->property(
"method" ).toInt() );
2663 const MessageComposer::MessageSender::SaveIn saveIn =
static_cast<MessageComposer::MessageSender::SaveIn
>( job->property(
"saveIn" ).toInt() );
2665 doDelayedSend( method, saveIn );
2668 void KMComposeWin::applyComposerSetting( MessageComposer::ComposerViewBase* mComposerBase )
2672 if( !mOriginalPreferredCharset.
isEmpty() ) {
2673 charsets.
insert( 0, mOriginalPreferredCharset );
2675 mComposerBase->setFrom( from() );
2676 mComposerBase->setReplyTo( replyTo() );
2677 mComposerBase->setSubject( subject() );
2678 mComposerBase->setCharsets( charsets );
2679 mComposerBase->setUrgent( mUrgentAction->isChecked() );
2680 mComposerBase->setMDNRequested( mRequestMDNAction->isChecked() );
2684 void KMComposeWin::doDelayedSend( MessageComposer::MessageSender::SendMethod method, MessageComposer::MessageSender::SaveIn saveIn )
2686 #ifndef QT_NO_CURSOR
2687 MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
2689 applyComposerSetting( mComposerBase );
2690 if ( mForceDisableHtml )
2691 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2692 bool sign = mSignAction->isChecked();
2693 bool encrypt = mEncryptAction->isChecked();
2695 mComposerBase->setCryptoOptions( sign, encrypt, cryptoMessageFormat(),
2696 ( ( saveIn != MessageComposer::MessageSender::SaveInNone &&
GlobalSettings::self()->neverEncryptDrafts() )
2697 || mSigningAndEncryptionExplicitlyDisabled ) );
2701 for (
int ix=0; ix<num; ++ix) {
2703 customMimeHeader.readConfig();
2704 customHeader.
insert(customMimeHeader.custHeaderName().toLatin1(), customMimeHeader.custHeaderValue() );
2708 while (extraCustomHeader.hasNext()) {
2709 extraCustomHeader.next();
2710 customHeader.
insert(extraCustomHeader.key(), extraCustomHeader.value() );
2713 mComposerBase->setCustomHeader( customHeader );
2714 mComposerBase->send( method, saveIn,
false );
2718 void KMComposeWin::slotSendLater()
2720 if ( !TransportManager::self()->showTransportCreationDialog(
this, TransportManager::IfNoTransportExists ) )
2722 if ( !checkRecipientNumber() )
2724 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2725 const bool wasRegistered = (SendLater::SendLaterUtil::sentLaterAgentWasRegistered() && SendLater::SendLaterUtil::sentLaterAgentEnabled());
2726 if (wasRegistered) {
2727 SendLater::SendLaterInfo *info = 0;
2731 const SendLater::SendLaterDialog::SendLaterAction action = dlg->action();
2734 case SendLater::SendLaterDialog::Unknown:
2735 kDebug()<<
"Sendlater action \"Unknown\": Need to fix it.";
2737 case SendLater::SendLaterDialog::Canceled:
2740 case SendLater::SendLaterDialog::PutInOutbox:
2741 doSend( MessageComposer::MessageSender::SendLater );
2743 case SendLater::SendLaterDialog::SendDeliveryAtTime:
2745 mComposerBase->setSendLaterInfo(info);
2746 if (info->isRecurrence()) {
2747 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInTemplates );
2749 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInDrafts );
2758 doSend( MessageComposer::MessageSender::SendLater );
2764 void KMComposeWin::slotSaveDraft()
2766 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2767 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInDrafts );
2772 void KMComposeWin::slotSaveTemplate()
2774 if ( mComposerBase->editor()->checkExternalEditorFinished() ) {
2775 doSend( MessageComposer::MessageSender::SendLater, MessageComposer::MessageSender::SaveInTemplates );
2780 void KMComposeWin::slotSendNowVia( MailTransport::Transport *transport )
2783 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
2789 void KMComposeWin::slotSendLaterVia( MailTransport::Transport *transport )
2792 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
2798 void KMComposeWin::sendNow(
bool shortcutUsed)
2800 if ( !mComposerBase->editor()->checkExternalEditorFinished() ) {
2803 if ( !TransportManager::self()->showTransportCreationDialog(
this, TransportManager::IfNoTransportExists ) )
2805 if ( !checkRecipientNumber() )
2807 mSendNowByShortcutUsed = shortcutUsed;
2809 mComposerBase->editor()->forceSpellChecking();
2815 void KMComposeWin::slotSendNowByShortcut()
2825 void KMComposeWin::confirmBeforeSend()
2827 const int rc = KMessageBox::warningYesNoCancel( mMainWidget,
2828 i18n(
"About to send email..."),
2829 i18n(
"Send Confirmation"),
2830 KGuiItem( i18n(
"&Send Now") ),
2831 KGuiItem( i18n(
"Send &Later") ) );
2833 if ( rc == KMessageBox::Yes ) {
2834 doSend( MessageComposer::MessageSender::SendImmediate );
2835 }
else if ( rc == KMessageBox::No ) {
2836 doSend( MessageComposer::MessageSender::SendLater );
2840 void KMComposeWin::slotCheckSendNowStep2()
2843 confirmBeforeSend();
2845 if (mSendNowByShortcutUsed) {
2848 if (!validateShortcut.validate()) {
2853 confirmBeforeSend();
2857 doSend( MessageComposer::MessageSender::SendImmediate );
2861 void KMComposeWin::slotCheckSendNow()
2864 KConfigGroup group( KGlobal::config(),
"PotentialPhishing");
2868 lst << mComposerBase->to();
2869 if (!mComposerBase->cc().isEmpty())
2871 if (!mComposerBase->bcc().isEmpty())
2874 connect(job, SIGNAL(potentialPhishingEmailsFound(
QStringList)),
this, SLOT(slotPotentialPhishingEmailsFound(
QStringList)));
2878 void KMComposeWin::slotPotentialPhishingEmailsFound(
const QStringList &list)
2881 slotCheckSendNowStep2();
2887 bool KMComposeWin::checkRecipientNumber()
const
2890 if (
GlobalSettings::self()->tooManyRecipients() && mComposerBase->recipientsEditor()->recipients().count() > thresHold ) {
2891 if ( KMessageBox::questionYesNo( mMainWidget,
2892 i18n(
"You are trying to send the mail to more than %1 recipients. Send message anyway?", thresHold),
2893 i18n(
"Too many recipients"),
2894 KGuiItem( i18n(
"&Send as Is") ),
2895 KGuiItem( i18n(
"&Edit Recipients") ) ) == KMessageBox::No ) {
2903 void KMComposeWin::slotHelp()
2905 KToolInvocation::invokeHelp();
2909 void KMComposeWin::enableHtml()
2911 if ( mForceDisableHtml ) {
2912 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2916 mComposerBase->editor()->enableRichTextMode();
2917 if ( !toolBar(
QLatin1String(
"htmlToolBar") )->isVisible() ) {
2924 if ( !markupAction->isChecked() )
2925 markupAction->setChecked(
true );
2927 mComposerBase->editor()->updateActionStates();
2928 mComposerBase->editor()->setActionsEnabled(
true );
2934 void KMComposeWin::disableHtml( MessageComposer::ComposerViewBase::Confirmation confirmation )
2936 bool forcePlainTextMarkup =
false;
2937 if ( confirmation == MessageComposer::ComposerViewBase::LetUserConfirm && mComposerBase->editor()->isFormattingUsed() && !mForceDisableHtml ) {
2938 int choice = KMessageBox::warningYesNoCancel(
this, i18n(
"Turning HTML mode off "
2939 "will cause the text to lose the formatting. Are you sure?" ),
2940 i18n(
"Lose the formatting?" ), KGuiItem( i18n(
"Lose Formatting" ) ), KGuiItem( i18n(
"Add Markup Plain Text" ) ) , KStandardGuiItem::cancel(),
2944 case KMessageBox::Cancel:
2947 case KMessageBox::No:
2948 forcePlainTextMarkup =
true;
2950 case KMessageBox::Yes:
2955 mComposerBase->editor()->forcePlainTextMarkup(forcePlainTextMarkup);
2956 mComposerBase->editor()->switchToPlainText();
2957 mComposerBase->editor()->setActionsEnabled(
false );
2960 if ( toolBar(
QLatin1String(
"htmlToolBar") )->isVisible() ) {
2964 if ( markupAction->isChecked() )
2965 markupAction->setChecked(
false );
2977 if ( mode == KMeditor::Plain )
2978 disableHtml( MessageComposer::ComposerViewBase::NoConfirmationNeeded );
2989 disableHtml( MessageComposer::ComposerViewBase::LetUserConfirm );
2993 void KMComposeWin::slotAutoSpellCheckingToggled(
bool on )
2995 mAutoSpellCheckingAction->setChecked( on );
2996 if ( on != mComposerBase->editor()->checkSpellingEnabled() )
2997 mComposerBase->editor()->setCheckSpellingEnabled( on );
2998 if ( on != mEdtSubject->checkSpellingEnabled() )
2999 mEdtSubject->setCheckSpellingEnabled( on );
3003 void KMComposeWin::slotSpellCheckingStatus(
const QString & status)
3005 statusBar()->changeItem( status, 0 );
3011 statusBar()->changeItem(
QString(), 0);
3015 void KMComposeWin::slotIdentityChanged( uint uoid,
bool initalChange )
3018 kDebug() <<
"Trying to change identity but mMsg == 0!";
3022 const KPIMIdentities::Identity &ident =
3024 if ( ident.isNull() ) {
3027 bool wasModified(isModified());
3029 if ( !ident.fullEmailAddr().isNull() ) {
3030 mEdtFrom->setText( ident.fullEmailAddr() );
3034 if ( KPIMUtils::firstEmailAddress( from() ).isEmpty() ) {
3037 if ( mEdtReplyTo ) {
3038 mEdtReplyTo->setText( ident.replyToAddr() );
3042 const KPIMIdentities::Identity &oldIdentity =
3046 if ( ident.organization().isEmpty() ) {
3047 mMsg->organization()->clear();
3049 KMime::Headers::Organization *
const organization
3050 =
new KMime::Headers::Organization( mMsg.get(), ident.organization(),
"utf-8" );
3051 mMsg->setHeader( organization );
3053 if ( !ident.isXFaceEnabled() || ident.xface().isEmpty() ) {
3054 mMsg->removeHeader(
"X-Face" );
3056 QString xface = ident.xface();
3058 int numNL = ( xface.
length() - 1 ) / 70;
3059 for (
int i = numNL; i > 0; --i ) {
3062 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-Face", mMsg.get(), xface,
"utf-8" );
3063 mMsg->setHeader( header );
3068 if ( !mBtnTransport->
isChecked() && !mIgnoreStickyFields ) {
3069 const int transportId = ident.transport().isEmpty() ? -1 : ident.transport().toInt();
3070 const Transport *transport = TransportManager::self()->transportById( transportId,
true );
3072 mMsg->removeHeader(
"X-KMail-Transport" );
3073 mComposerBase->transportComboBox()->setCurrentTransport( TransportManager::self()->defaultTransportId() );
3075 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-Transport", mMsg.get(),
QString::number( transport->id() ),
"utf-8" );
3076 mMsg->setHeader( header );
3077 mComposerBase->transportComboBox()->setCurrentTransport( transport->id() );
3081 const bool fccIsDisabled = ident.disabledFcc();
3082 if (fccIsDisabled) {
3083 KMime::Headers::Generic *header =
new KMime::Headers::Generic(
"X-KMail-FccDisabled", mMsg.get(),
QLatin1String(
"true"),
"utf-8" );
3084 mMsg->setHeader( header );
3086 mMsg->removeHeader(
"X-KMail-FccDisabled" );
3088 mFccFolder->setEnabled(!fccIsDisabled);
3091 if ( !mBtnDictionary->
isChecked() && !mIgnoreStickyFields ) {
3092 mComposerBase->dictionary()->setCurrentByDictionaryName( ident.dictionary() );
3094 slotSpellCheckingLanguage( mComposerBase->dictionary()->currentDictionary() );
3095 if ( !mBtnFcc->
isChecked() && !mPreventFccOverwrite ) {
3100 if ( !wasModified && !( ident.templates().isEmpty() && mCustomTemplate.
isEmpty() ) &&
3102 applyTemplate( uoid, mId );
3104 mComposerBase->identityChanged( ident, oldIdentity,
false );
3105 mEdtSubject->setAutocorrectionLanguage(ident.autocorrectionLanguage());
3111 bool bNewIdentityHasSigningKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
3112 bool bNewIdentityHasEncryptionKey = !ident.pgpSigningKey().isEmpty() || !ident.smimeSigningKey().isEmpty();
3114 if ( !bNewIdentityHasEncryptionKey && mLastIdentityHasEncryptionKey ) {
3115 mLastEncryptActionState = mEncryptAction->isChecked();
3116 setEncryption(
false );
3118 if ( !bNewIdentityHasSigningKey && mLastIdentityHasSigningKey ) {
3119 mLastSignActionState = mSignAction->isChecked();
3120 setSigning(
false );
3123 if ( bNewIdentityHasEncryptionKey && !mLastIdentityHasEncryptionKey ) {
3124 setEncryption( mLastEncryptActionState );
3126 if ( bNewIdentityHasSigningKey && !mLastIdentityHasSigningKey ) {
3127 setSigning( mLastSignActionState );
3130 mCryptoModuleAction->setCurrentItem( format2cb(
3131 Kleo::stringToCryptoMessageFormat( ident.preferredCryptoMessageFormat() ) ) );
3132 slotSelectCryptoModule(
true );
3134 mLastIdentityHasSigningKey = bNewIdentityHasSigningKey;
3135 mLastIdentityHasEncryptionKey = bNewIdentityHasEncryptionKey;
3136 const KPIMIdentities::Signature sig =
const_cast<KPIMIdentities::Identity&
>( ident ).signature();
3137 bool isEnabledSignature = sig.isEnabledSignature();
3138 mAppendSignature->setEnabled(isEnabledSignature);
3139 mPrependSignature->setEnabled(isEnabledSignature);
3140 mInsertSignatureAtCursorPosition->setEnabled(isEnabledSignature);
3143 changeCryptoAction();
3145 rethinkFields(
false );
3150 void KMComposeWin::slotSpellcheckConfig()
3156 void KMComposeWin::slotEditToolbars()
3158 saveMainWindowSettings(
KMKernel::self()->config()->group(
"Composer") );
3159 KEditToolBar dlg( guiFactory(),
this );
3161 connect( &dlg, SIGNAL(newToolBarConfig()),
3162 SLOT(slotUpdateToolbars()) );
3167 void KMComposeWin::slotUpdateToolbars()
3170 applyMainWindowSettings(
KMKernel::self()->config()->group(
"Composer") );
3173 void KMComposeWin::slotEditKeys()
3175 KShortcutsDialog::configure( actionCollection(),
3176 KShortcutsEditor::LetterShortcutsDisallowed );
3183 mComposerBase->editor()->setFocus();
3188 mEdtSubject->setFocus();
3191 void KMComposeWin::slotCompletionModeChanged( KGlobalSettings::Completion mode )
3196 mEdtFrom->setCompletionMode( mode );
3197 mEdtReplyTo->setCompletionMode( mode );
3198 mComposerBase->recipientsEditor()->setCompletionMode( mode );
3201 void KMComposeWin::slotConfigChanged()
3204 mComposerBase->updateAutoSave();
3213 void KMComposeWin::slotFolderRemoved(
const Akonadi::Collection & col )
3215 kDebug() <<
"you killed me.";
3217 if ( ( mFolder.isValid() ) && ( col.id() == mFolder.id() ) ) {
3218 mFolder = CommonKernel->draftsCollectionFolder();
3219 kDebug() <<
"restoring drafts to" << mFolder.id();
3224 void KMComposeWin::slotOverwriteModeChanged()
3226 const bool overwriteMode = mComposerBase->editor()->overwriteMode ();
3227 mComposerBase->editor()->setCursorWidth( overwriteMode ? 5 : 1 );
3228 mStatusBarLabelToggledOverrideMode->
setToggleMode(overwriteMode);
3231 void KMComposeWin::slotCursorPositionChanged()
3236 line = mComposerBase->editor()->linePosition();
3237 col = mComposerBase->editor()->columnNumber();
3238 temp = i18nc(
"Shows the linenumber of the cursor position.",
" Line: %1 ", line + 1 );
3239 statusBar()->changeItem( temp, 1 );
3240 temp = i18n(
" Column: %1 ", col + 1 );
3241 statusBar()->changeItem( temp, 2 );
3244 if ( mComposerBase->editor()->textCursor().charFormat().isAnchor() ) {
3245 const QString text = mComposerBase->editor()->currentLinkText();
3246 const QString url = mComposerBase->editor()->currentLinkUrl();
3247 statusBar()->changeItem( text +
QLatin1String(
" -> ") + url, 0 );
3250 statusBar()->changeItem(
QString(), 0 );
3255 void KMComposeWin::recipientEditorSizeHintChanged()
3260 void KMComposeWin::setMaximumHeaderSize()
3265 void KMComposeWin::updateSignatureAndEncryptionStateIndicators()
3270 void KMComposeWin::slotLanguageChanged(
const QString &language )
3272 mComposerBase->dictionary()->setCurrentByDictionary( language );
3276 void KMComposeWin::slotFccFolderChanged(
const Akonadi::Collection& collection)
3278 mComposerBase->setFcc( collection );
3279 mComposerBase->editor()->document()->setModified(
true);
3282 void KMComposeWin::insertSpecialCharacter()
3284 if(!mSelectSpecialChar) {
3285 mSelectSpecialChar =
new KPIMTextEdit::SelectSpecialChar(
this);
3286 mSelectSpecialChar->setCaption(i18n(
"Insert Special Character"));
3287 mSelectSpecialChar->setOkButtonText(i18n(
"Insert"));
3288 connect(mSelectSpecialChar,SIGNAL(charSelected(
QChar)),
this,SLOT(charSelected(
QChar)));
3290 mSelectSpecialChar->show();
3293 void KMComposeWin::charSelected(
const QChar& c)
3295 mComposerBase->editor()->insertPlainText(c);
3298 void KMComposeWin::slotSaveAsFile()
3302 job->
setHtmlMode(mComposerBase->editor()->textMode() == KMeditor::Rich);
3303 job->
setEditor(mComposerBase->editor());
3308 void KMComposeWin::slotCreateAddressBookContact()
3314 void KMComposeWin::slotAttachMissingFile()
3316 mComposerBase->attachmentController()->showAddAttachmentFileDialog();
3319 void KMComposeWin::slotVerifyMissingAttachmentTimeout()
3322 mAttachmentMissing->animatedShow();
3326 void KMComposeWin::slotExplicitClosedMissingAttachment()
3328 if(m_verifyMissingAttachment) {
3329 m_verifyMissingAttachment->
stop();
3330 delete m_verifyMissingAttachment;
3331 m_verifyMissingAttachment = 0;
3337 mExtraHeaders = headers;
3342 mComposerBase->identityCombo()->setCurrentIdentity( identity );
3345 void KMComposeWin::slotSentenceCase()
3347 QTextCursor textCursor = mComposerBase->editor()->textCursor();
3348 PimCommon::EditorUtil editorUtil;
3349 editorUtil.sentenceCase(textCursor);
3352 void KMComposeWin::slotUpperCase()
3354 PimCommon::EditorUtil editorUtil;
3355 QTextCursor textCursor = mComposerBase->editor()->textCursor();
3356 editorUtil.upperCase(textCursor);
3359 void KMComposeWin::slotLowerCase()
3361 QTextCursor textCursor = mComposerBase->editor()->textCursor();
3362 PimCommon::EditorUtil editorUtil;
3363 editorUtil.lowerCase(textCursor);
3366 void KMComposeWin::slotExternalEditorStarted()
3368 mComposerBase->identityCombo()->setEnabled(
false);
3369 mExternalEditorWarning->show();
3372 void KMComposeWin::slotExternalEditorClosed()
3374 mComposerBase->identityCombo()->setEnabled(
true);
3375 mExternalEditorWarning->hide();
3378 void KMComposeWin::slotInsertShortUrl(
const QString &url)
3380 mComposerBase->editor()->insertLink(url);
3383 void KMComposeWin::slotShareLinkDone(
const QString &link)
3385 mComposerBase->editor()->insertShareLink(link);
3388 void KMComposeWin::slotTransportChanged()
3390 mComposerBase->editor()->document()->setModified(
true);
3393 void KMComposeWin::slotFollowUpMail(
bool toggled)
3398 mComposerBase->setFollowUpDate(dlg->selectedDate());
3399 mComposerBase->setFollowUpCollection(dlg->collection());
3401 mFollowUpToggleAction->setChecked(
false);
3405 mComposerBase->clearFollowUp();
3409 void KMComposeWin::slotSnippetWidgetVisibilityChanged(
bool b)
3412 mSnippetSplitterCollapser->setVisible(b);
3415 void KMComposeWin::slotOverwriteModeWasChanged(
bool state)
3417 mComposerBase->editor()->setCursorWidth( state ? 5 : 1 );
3418 mComposerBase->editor()->setOverwriteMode (state);
void setText(const QString &text)
void setInterval(int msec)
void setFolder(const Akonadi::Collection &aFolder)
If this folder is set, the original message is inserted back after canceling.
void setHeight(int height)
void htmlToolBarVisibilityChanged(bool visible)
void slotSpellcheckDoneClearStatus()
QByteArray data(const QString &mimeType) const
void setSizes(const QList< int > &list)
void setTextSelection(const QString &selection)
Set the text selection the message is a response to.
const QMimeData * mimeData(Mode mode) const
void push_back(const T &value)
void disableWordWrap()
Disables word wrap completely.
void slotWordWrapToggled(bool)
Switch wordWrap on/off.
int numProgressUpdateFile() const
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())
void setEditor(MessageComposer::KMeditor *editor)
virtual void setCaption(const QString &caption)
Reimplement because we have this bug #Bug 163978.
void setSubject(const QString &subject)
Q_SCRIPTABLE void addAttachmentsAndSend(const KUrl::List &urls, const QString &comment, int how)
void setCollectionForNewMessage(const Akonadi::Collection &folder)
void setParentWidget(QWidget *parentWidget)
bool registerObject(const QString &path, QObject *object, QFlags< QDBusConnection::RegisterOption > options)
const KPIMIdentities::Identity & identity() const
bool isComposing() const
Returns true while the message composing is in progress.
void setDefaultDomain(const QString &domainName)
QDBusConnection sessionBus()
void setEmailWhiteList(const QStringList &emails)
QString join(const QString &separator) const
void setPotentialPhisingEmail(const QStringList &lst)
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
void setSpacing(int spacing)
KSharedConfig::Ptr config()
void setBuddy(QWidget *buddy)
void identityChanged(const KPIMIdentities::Identity &identity)
End of D-Bus callable stuff.
void forceDisableHtml()
Disables HTML completely.
QString number(int n, int base)
int count(const T &value) const
QString fromLocal8Bit(const char *str, int size)
static MailList fromMimeData(const QMimeData *md)
void append(const T &value)
void setCurrentReplyTo(const QString &)
void setCustomTemplate(const QString &customTemplate)
Set custom template to be used for the message.
QList< int > sizes() const
QString & insert(int position, QChar ch)
QString messageId() const
void setRowStretch(int row, int stretch)
void setChildrenCollapsible(bool)
Small helper structure which encapsulates the KMMessage created when creating a reply, and.
QString smartQuote(const QString &msg)
void setFollowUpReminderDate(const QDate &date)
void setObjectName(const QString &name)
int removeAll(const T &value)
void setToggleMode(bool state)
void setModified(bool modified)
Set whether the message should be treated as modified or not.
virtual void setCurrentIdentity(uint identity)
void setOpaqueResize(bool opaque)
void setMargin(int margin)
void slotFetchJob(KJob *)
void setFcc(const QString &idString)
Use the given folder as sent-mail folder if the given folder exists.
QByteArray & append(char ch)
void setMessageId(const QString &messageId)
void setEmails(const QStringList &emails)
void slotTextModeChanged(KRichTextEdit::Mode)
bool contains(const T &value) const
Q_SCRIPTABLE void send(int how)
Start of D-Bus callable stuff.
void setCollectionToDo(const Akonadi::Collection &collection)
uint currentIdentity() const
KActionMenu * menuShareLinkServices() const
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 setStateString(const QString &toggled, const QString &untoggled)
void addAttach(KMime::Content *msgPart)
Add an attachment to the list.
QByteArray toLatin1() const
void setPrintPreview(bool preview)
void setFocusToEditor()
Sets the focus to the edit-widget.
void addExtraCustomHeaders(const QMap< QByteArray, QString > &header)
void insert(int i, const T &value)
void setColumnStretch(int column, int stretch)
void setHtmlMode(bool htmlMode)
virtual QSize sizeHint() const
QVariant imageData() const
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
int indexOf(const QRegExp &rx, int from) const
void prepend(const T &value)
KPIMIdentities::IdentityManager * identityManager()
return the pointer to the identity manager
iterator insert(const Key &key, const T &value)
void autoSaveMessage(bool force=false)
void setCollapsible(int index, bool collapse)
void ignoreStickyFields()
Ignore the "sticky" setting of the transport combo box and prefer the X-KMail-Transport header field ...
void setSigningAndEncryptionDisabled(bool v)
Disabled signing and encryption completely for this composer window.
void slotSyncConfig()
Sync the config immediatley.
qlonglong toLongLong(bool *ok, int base) const
void setTo(const QString &to)
QString toUnicode(const QByteArray &a) const
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...
void setSingleShot(bool singleShot)