10 #include "kmreaderwin.h"
12 #include "globalsettings.h"
13 #include "kmversion.h"
14 #include "kmmainwidget.h"
15 #include "kmreadermainwin.h"
16 #include <libtdepim/tdefileio.h>
17 #include "kmfolderindex.h"
18 #include "kmcommands.h"
19 #include "kmmsgpartdlg.h"
20 #include "mailsourceviewer.h"
21 using KMail::MailSourceViewer;
23 #include "kmmsgdict.h"
24 #include "messagesender.h"
25 #include "kcursorsaver.h"
27 #include "vcardviewer.h"
28 using KMail::VCardViewer;
29 #include "objecttreeparser.h"
30 using KMail::ObjectTreeParser;
31 #include "partmetadata.h"
32 using KMail::PartMetaData;
33 #include "attachmentstrategy.h"
34 using KMail::AttachmentStrategy;
35 #include "headerstrategy.h"
36 using KMail::HeaderStrategy;
37 #include "headerstyle.h"
39 #include "tdehtmlparthtmlwriter.h"
41 using KMail::KHtmlPartHtmlWriter;
42 #include "htmlstatusbar.h"
44 #include "folderjob.h"
45 using KMail::FolderJob;
46 #include "csshelper.h"
47 using KMail::CSSHelper;
49 using KMail::ISubject;
50 #include "urlhandlermanager.h"
52 #include "interfaces/observable.h"
54 #include "kmheaders.h"
56 #include "broadcaststatus.h"
58 #include <kmime_mdn.h>
59 using namespace KMime;
60 #ifdef KMAIL_READER_HTML_DEBUG
61 #include "filehtmlwriter.h"
62 using KMail::FileHtmlWriter;
63 #include "teehtmlwriter.h"
67 #include <kasciistringtools.h>
68 #include <kstringhandler.h>
70 #include <mimelib/mimepp.h>
71 #include <mimelib/body.h>
72 #include <mimelib/utility.h>
74 #include <kleo/specialjob.h>
75 #include <kleo/cryptobackend.h>
76 #include <kleo/cryptobackendfactory.h>
79 #include <tdeabc/addressee.h>
80 #include <tdeabc/vcardconverter.h>
83 #include <tdehtml_part.h>
84 #include <tdehtmlview.h>
85 #include <dom/html_element.h>
86 #include <dom/html_block.h>
87 #include <dom/html_document.h>
88 #include <dom/dom_string.h>
89 #include <dom/dom_exception.h>
91 #include <tdeapplication.h>
93 #include <kuserprofile.h>
94 #include <kcharsets.h>
95 #include <tdepopupmenu.h>
96 #include <kstandarddirs.h>
99 #include <tdefiledialog.h>
100 #include <tdelocale.h>
101 #include <tdemessagebox.h>
102 #include <tdeglobalsettings.h>
104 #include <tdetempfile.h>
105 #include <kprocess.h>
107 #include <tdeaction.h>
108 #include <kiconloader.h>
109 #include <kmdcodec.h>
110 #include <kasciistricmp.h>
111 #include <kurldrag.h>
113 #include <tqclipboard.h>
115 #include <tqtextcodec.h>
116 #include <tqpaintdevicemetrics.h>
117 #include <tqlayout.h>
119 #include <tqsplitter.h>
128 #include <sys/stat.h>
138 class NewByteArray :
public TQByteArray
141 NewByteArray &appendNULL();
142 NewByteArray &operator+=(
const char * );
143 NewByteArray &operator+=(
const TQByteArray & );
144 NewByteArray &operator+=(
const TQCString & );
145 TQByteArray& qByteArray();
148 NewByteArray& NewByteArray::appendNULL()
150 TQByteArray::detach();
152 if ( !TQByteArray::resize( len1 + 1 ) )
154 *(data() + len1) =
'\0';
157 NewByteArray& NewByteArray::operator+=(
const char * newData )
161 TQByteArray::detach();
163 uint len2 = tqstrlen( newData );
164 if ( !TQByteArray::resize( len1 + len2 ) )
166 memcpy( data() + len1, newData, len2 );
169 NewByteArray& NewByteArray::operator+=(
const TQByteArray & newData )
171 if ( newData.isNull() )
173 TQByteArray::detach();
175 uint len2 = newData.size();
176 if ( !TQByteArray::resize( len1 + len2 ) )
178 memcpy( data() + len1, newData.data(), len2 );
181 NewByteArray& NewByteArray::operator+=(
const TQCString & newData )
183 if ( newData.isEmpty() )
185 TQByteArray::detach();
187 uint len2 = newData.length();
188 if ( !TQByteArray::resize( len1 + len2 ) )
190 memcpy( data() + len1, newData.data(), len2 );
193 TQByteArray& NewByteArray::qByteArray()
195 return *((TQByteArray*)
this);
202 void KMReaderWin::objectTreeToDecryptedMsg( partNode* node,
203 NewByteArray& resultingData,
205 bool weAreReplacingTheRootNode,
208 kdDebug(5006) << TQString(
"-------------------------------------------------" ) << endl;
209 kdDebug(5006) << TQString(
"KMReaderWin::objectTreeToDecryptedMsg( %1 ) START").arg( recCount ) << endl;
212 kdDebug(5006) << node->typeString() <<
'/' << node->subTypeString() << endl;
214 partNode* curNode = node;
215 partNode* dataNode = curNode;
216 partNode * child = node->firstChild();
217 const bool bIsMultipart = node->type() == DwMime::kTypeMultipart ;
218 bool bKeepPartAsIs =
false;
220 switch( curNode->type() ){
221 case DwMime::kTypeMultipart: {
222 switch( curNode->subType() ){
223 case DwMime::kSubtypeSigned: {
224 bKeepPartAsIs =
true;
227 case DwMime::kSubtypeEncrypted: {
235 case DwMime::kTypeMessage: {
236 switch( curNode->subType() ){
237 case DwMime::kSubtypeRfc822: {
245 case DwMime::kTypeApplication: {
246 switch( curNode->subType() ){
247 case DwMime::kSubtypeOctetStream: {
252 case DwMime::kSubtypePkcs7Signature: {
255 bKeepPartAsIs =
true;
258 case DwMime::kSubtypePkcs7Mime: {
261 if ( child && curNode->encryptionState() != KMMsgNotEncrypted )
271 DwHeaders& rootHeaders( theMessage.
headers() );
272 DwBodyPart * part = dataNode->dwPart() ? dataNode->dwPart() : 0;
274 (part && part->hasHeaders())
276 : ( (weAreReplacingTheRootNode || !dataNode->parentNode())
279 if( dataNode == curNode ) {
280 kdDebug(5006) <<
"dataNode == curNode: Save curNode without replacing it." << endl;
286 if( dataNode->parentNode() && !weAreReplacingTheRootNode ) {
287 kdDebug(5006) <<
"dataNode is NOT replacing the root node: Store the headers." << endl;
288 resultingData += headers->AsString().c_str();
289 }
else if( weAreReplacingTheRootNode && part && part->hasHeaders() ){
290 kdDebug(5006) <<
"dataNode replace the root node: Do NOT store the headers but change" << endl;
291 kdDebug(5006) <<
" the Message's headers accordingly." << endl;
292 kdDebug(5006) <<
" old Content-Type = " << rootHeaders.ContentType().AsString().c_str() << endl;
293 kdDebug(5006) <<
" new Content-Type = " << headers->ContentType( ).AsString().c_str() << endl;
294 rootHeaders.ContentType() = headers->ContentType();
295 theMessage.setContentTransferEncodingStr(
296 headers->HasContentTransferEncoding()
297 ? headers->ContentTransferEncoding().AsString().c_str()
299 rootHeaders.ContentDescription() = headers->ContentDescription();
300 rootHeaders.ContentDisposition() = headers->ContentDisposition();
305 if ( bKeepPartAsIs ) {
306 resultingData += dataNode->encodedBody();
310 if( headers && bIsMultipart && dataNode->firstChild() ) {
311 kdDebug(5006) <<
"is valid Multipart, processing children:" << endl;
312 TQCString boundary = headers->ContentType().Boundary().c_str();
313 curNode = dataNode->firstChild();
316 kdDebug(5006) <<
"--boundary" << endl;
317 if( resultingData.size() &&
318 (
'\n' != resultingData.at( resultingData.size()-1 ) ) )
319 resultingData += TQCString(
"\n" );
320 resultingData += TQCString(
"\n" );
321 resultingData +=
"--";
322 resultingData += boundary;
323 resultingData +=
"\n";
327 objectTreeToDecryptedMsg( curNode,
332 curNode = curNode->nextSibling();
334 kdDebug(5006) <<
"--boundary--" << endl;
335 resultingData +=
"\n--";
336 resultingData += boundary;
337 resultingData +=
"--\n\n";
338 kdDebug(5006) <<
"Multipart processing children - DONE" << endl;
341 kdDebug(5006) <<
"is Simple part or invalid Multipart, storing body data .. DONE" << endl;
342 resultingData += part->Body().AsString().c_str();
346 kdDebug(5006) <<
"dataNode != curNode: Replace curNode by dataNode." << endl;
347 bool rootNodeReplaceFlag = weAreReplacingTheRootNode || !curNode->parentNode();
348 if( rootNodeReplaceFlag ) {
349 kdDebug(5006) <<
" Root node will be replaced." << endl;
351 kdDebug(5006) <<
" Root node will NOT be replaced." << endl;
355 objectTreeToDecryptedMsg( dataNode,
362 kdDebug(5006) << TQString(
"\nKMReaderWin::objectTreeToDecryptedMsg( %1 ) END").arg( recCount ) << endl;
386 void KMReaderWin::createWidgets() {
387 TQVBoxLayout * vlay =
new TQVBoxLayout(
this );
388 mSplitter =
new TQSplitter( Qt::Vertical,
this,
"mSplitter" );
389 vlay->addWidget( mSplitter );
390 mMimePartTree =
new KMMimePartTree(
this, mSplitter,
"mMimePartTree" );
391 mBox =
new TQHBox( mSplitter,
"mBox" );
392 setStyleDependantFrameWidth();
393 mBox->setFrameStyle( mMimePartTree->frameStyle() );
395 mViewer =
new TDEHTMLPart( mBox,
"mViewer" );
396 mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
397 mSplitter->setResizeMode( mMimePartTree, TQSplitter::KeepSize );
400 const int KMReaderWin::delay = 150;
403 KMReaderWin::KMReaderWin(TQWidget *aParent,
404 TQWidget *mainWindow,
405 TDEActionCollection* actionCollection,
408 : TQWidget(aParent, aName, aFlags | TQt::WDestructiveClose),
409 mSerNumOfOriginalMessage( 0 ),
411 mAttachmentStrategy( 0 ),
412 mHeaderStrategy( 0 ),
414 mUpdateReaderWinTimer( 0,
"mUpdateReaderWinTimer" ),
415 mResizeTimer( 0,
"mResizeTimer" ),
416 mDelayedMarkTimer( 0,
"mDelayedMarkTimer" ),
417 mHeaderRefreshTimer( 0,
"mHeaderRefreshTimer" ),
418 mOldGlobalOverrideEncoding(
"---" ),
421 mMainWindow( mainWindow ),
422 mActionCollection( actionCollection ),
423 mMailToComposeAction( 0 ),
424 mMailToReplyAction( 0 ),
425 mMailToForwardAction( 0 ),
426 mAddAddrBookAction( 0 ),
427 mOpenAddrBookAction( 0 ),
431 mUrlSaveAsAction( 0 ),
432 mAddBookmarksAction( 0 ),
433 mStartIMChatAction( 0 ),
434 mSelectAllAction( 0 ),
435 mHeaderOnlyAttachmentsAction( 0 ),
436 mSelectEncodingAction( 0 ),
437 mToggleFixFontAction( 0 ),
438 mToggleMimePartTreeAction( 0 ),
439 mCanStartDrag( false ),
441 mSavedRelativePosition( 0 ),
442 mDecrytMessageOverwrite( false ),
443 mShowSignatureDetails( false ),
444 mShowAttachmentQuicklist( true ),
445 mShowRawToltecMail( false )
447 mExternalWindow = (aParent == mainWindow );
448 mSplitterSizes << 180 << 100;
450 mMimeTreeModeOverride = -1;
451 mMimeTreeAtBottom =
true;
454 mWaitingForSerNum = 0;
458 mShowColorbar =
false;
462 createActions( actionCollection );
466 mHtmlOverride =
false;
467 mHtmlLoadExtDefault =
false;
468 mHtmlLoadExtOverride =
false;
470 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin() - 1;
472 connect( &mUpdateReaderWinTimer, TQT_SIGNAL(timeout()),
473 TQT_TQOBJECT(
this), TQT_SLOT(updateReaderWin()) );
474 connect( &mResizeTimer, TQT_SIGNAL(timeout()),
475 TQT_TQOBJECT(
this), TQT_SLOT(slotDelayedResize()) );
476 connect( &mDelayedMarkTimer, TQT_SIGNAL(timeout()),
477 TQT_TQOBJECT(
this), TQT_SLOT(slotTouchMessage()) );
478 connect( &mHeaderRefreshTimer, TQT_SIGNAL(timeout()),
479 TQT_TQOBJECT(
this), TQT_SLOT(updateHeader()) );
483 void KMReaderWin::createActions( TDEActionCollection * ac ) {
487 TDERadioAction *raction = 0;
490 TDEActionMenu *headerMenu =
491 new TDEActionMenu( i18n(
"View->",
"&Headers"), ac,
"view_headers" );
492 headerMenu->setToolTip( i18n(
"Choose display style of message headers") );
494 connect( headerMenu, TQT_SIGNAL(activated()),
495 TQT_TQOBJECT(
this), TQT_SLOT(slotCycleHeaderStyles()) );
497 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Enterprise Headers"), 0,
498 TQT_TQOBJECT(
this), TQT_SLOT(slotEnterpriseHeaders()),
499 ac,
"view_headers_enterprise" );
500 raction->setToolTip( i18n(
"Show the list of headers in Enterprise style") );
501 raction->setExclusiveGroup(
"view_headers_group" );
502 headerMenu->insert(raction);
504 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Fancy Headers"), 0,
505 TQT_TQOBJECT(
this), TQT_SLOT(slotFancyHeaders()),
506 ac,
"view_headers_fancy" );
507 raction->setToolTip( i18n(
"Show the list of headers in a fancy format") );
508 raction->setExclusiveGroup(
"view_headers_group" );
509 headerMenu->insert( raction );
511 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Brief Headers"), 0,
512 TQT_TQOBJECT(
this), TQT_SLOT(slotBriefHeaders()),
513 ac,
"view_headers_brief" );
514 raction->setToolTip( i18n(
"Show brief list of message headers") );
515 raction->setExclusiveGroup(
"view_headers_group" );
516 headerMenu->insert( raction );
518 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Standard Headers"), 0,
519 TQT_TQOBJECT(
this), TQT_SLOT(slotStandardHeaders()),
520 ac,
"view_headers_standard" );
521 raction->setToolTip( i18n(
"Show standard list of message headers") );
522 raction->setExclusiveGroup(
"view_headers_group" );
523 headerMenu->insert( raction );
525 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Long Headers"), 0,
526 TQT_TQOBJECT(
this), TQT_SLOT(slotLongHeaders()),
527 ac,
"view_headers_long" );
528 raction->setToolTip( i18n(
"Show long list of message headers") );
529 raction->setExclusiveGroup(
"view_headers_group" );
530 headerMenu->insert( raction );
532 raction =
new TDERadioAction( i18n(
"View->headers->",
"&All Headers"), 0,
533 TQT_TQOBJECT(
this), TQT_SLOT(slotAllHeaders()),
534 ac,
"view_headers_all" );
535 raction->setToolTip( i18n(
"Show all message headers") );
536 raction->setExclusiveGroup(
"view_headers_group" );
537 headerMenu->insert( raction );
540 TDEActionMenu *attachmentMenu =
541 new TDEActionMenu( i18n(
"View->",
"&Attachments"), ac,
"view_attachments" );
542 attachmentMenu->setToolTip( i18n(
"Choose display style of attachments") );
543 connect( attachmentMenu, TQT_SIGNAL(activated()),
544 TQT_TQOBJECT(
this), TQT_SLOT(slotCycleAttachmentStrategy()) );
546 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&As Icons"), 0,
547 TQT_TQOBJECT(
this), TQT_SLOT(slotIconicAttachments()),
548 ac,
"view_attachments_as_icons" );
549 raction->setToolTip( i18n(
"Show all attachments as icons. Click to see them.") );
550 raction->setExclusiveGroup(
"view_attachments_group" );
551 attachmentMenu->insert( raction );
553 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Smart"), 0,
554 TQT_TQOBJECT(
this), TQT_SLOT(slotSmartAttachments()),
555 ac,
"view_attachments_smart" );
556 raction->setToolTip( i18n(
"Show attachments as suggested by sender.") );
557 raction->setExclusiveGroup(
"view_attachments_group" );
558 attachmentMenu->insert( raction );
560 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Inline"), 0,
561 TQT_TQOBJECT(
this), TQT_SLOT(slotInlineAttachments()),
562 ac,
"view_attachments_inline" );
563 raction->setToolTip( i18n(
"Show all attachments inline (if possible)") );
564 raction->setExclusiveGroup(
"view_attachments_group" );
565 attachmentMenu->insert( raction );
567 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Hide"), 0,
568 TQT_TQOBJECT(
this), TQT_SLOT(slotHideAttachments()),
569 ac,
"view_attachments_hide" );
570 raction->setToolTip( i18n(
"Do not show attachments in the message viewer") );
571 raction->setExclusiveGroup(
"view_attachments_group" );
572 attachmentMenu->insert( raction );
574 mHeaderOnlyAttachmentsAction =
new TDERadioAction( i18n(
"View->attachments->",
"In Header &Only" ), 0,
575 TQT_TQOBJECT(
this), TQT_SLOT( slotHeaderOnlyAttachments() ),
576 ac,
"view_attachments_headeronly" );
577 mHeaderOnlyAttachmentsAction->setToolTip( i18n(
"Show Attachments only in the header of the mail" ) );
578 mHeaderOnlyAttachmentsAction->setExclusiveGroup(
"view_attachments_group" );
579 attachmentMenu->insert( mHeaderOnlyAttachmentsAction );
582 mSelectEncodingAction =
new TDESelectAction( i18n(
"&Set Encoding" ),
"charset", 0,
583 TQT_TQOBJECT(
this), TQT_SLOT( slotSetEncoding() ),
585 TQStringList encodings = KMMsgBase::supportedEncodings(
false );
586 encodings.prepend( i18n(
"Auto" ) );
587 mSelectEncodingAction->setItems( encodings );
588 mSelectEncodingAction->setCurrentItem( 0 );
590 mMailToComposeAction =
new TDEAction( i18n(
"New Message To..."),
"mail-message-new",
591 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoCompose()), ac,
593 mMailToReplyAction =
new TDEAction( i18n(
"Reply To..."),
"mail-reply-sender",
596 mMailToForwardAction =
new TDEAction( i18n(
"Forward To..."),
"mail-forward",
597 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoForward()), ac,
599 mAddAddrBookAction =
new TDEAction( i18n(
"Add to Address Book"),
600 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoAddAddrBook()),
601 ac,
"add_addr_book" );
602 mOpenAddrBookAction =
new TDEAction( i18n(
"Open in Address Book"),
603 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoOpenAddrBook()),
604 ac,
"openin_addr_book" );
605 mCopyAction = KStdAction::copy( TQT_TQOBJECT(
this), TQT_SLOT(
slotCopySelectedText()), ac,
"kmail_copy");
606 mSelectAllAction =
new TDEAction( i18n(
"Select All Text"), CTRL+SHIFT+Key_A, TQT_TQOBJECT(
this),
607 TQT_SLOT(
selectAll()), ac,
"mark_all_text" );
608 mCopyURLAction =
new TDEAction( i18n(
"Copy Link Address"), 0, TQT_TQOBJECT(
this),
610 mUrlOpenAction =
new TDEAction( i18n(
"Open URL"), 0, TQT_TQOBJECT(
this),
612 mAddBookmarksAction =
new TDEAction( i18n(
"Bookmark This Link"),
614 0, TQT_TQOBJECT(
this), TQT_SLOT(slotAddBookmarks()),
615 ac,
"add_bookmarks" );
616 mUrlSaveAsAction =
new TDEAction( i18n(
"Save Link As..."), 0, TQT_TQOBJECT(
this),
619 mToggleFixFontAction =
new TDEToggleAction( i18n(
"Use Fi&xed Font"),
621 ac,
"toggle_fixedfont" );
623 mToggleMimePartTreeAction =
new TDEToggleAction( i18n(
"Show Message Structure"),
624 0, ac,
"toggle_mimeparttree" );
625 connect(mToggleMimePartTreeAction, TQT_SIGNAL(toggled(
bool)),
628 mStartIMChatAction =
new TDEAction( i18n(
"Chat &With..."), 0, TQT_TQOBJECT(
this),
629 TQT_SLOT(
slotIMChat()), ac,
"start_im_chat" );
633 TDERadioAction *KMReaderWin::actionForHeaderStyle(
const HeaderStyle * style,
const HeaderStrategy * strategy ) {
634 if ( !mActionCollection )
636 const char * actionName = 0;
637 if ( style == HeaderStyle::enterprise() )
638 actionName =
"view_headers_enterprise";
639 if ( style == HeaderStyle::fancy() )
640 actionName =
"view_headers_fancy";
641 else if ( style == HeaderStyle::brief() )
642 actionName =
"view_headers_brief";
643 else if ( style == HeaderStyle::plain() ) {
644 if ( strategy == HeaderStrategy::standard() )
645 actionName =
"view_headers_standard";
646 else if ( strategy == HeaderStrategy::rich() )
647 actionName =
"view_headers_long";
648 else if ( strategy == HeaderStrategy::all() )
649 actionName =
"view_headers_all";
652 return static_cast<TDERadioAction*
>(mActionCollection->action(actionName));
657 TDERadioAction *KMReaderWin::actionForAttachmentStrategy(
const AttachmentStrategy * as ) {
658 if ( !mActionCollection )
660 const char * actionName = 0;
661 if ( as == AttachmentStrategy::iconic() )
662 actionName =
"view_attachments_as_icons";
663 else if ( as == AttachmentStrategy::smart() )
664 actionName =
"view_attachments_smart";
665 else if ( as == AttachmentStrategy::inlined() )
666 actionName =
"view_attachments_inline";
667 else if ( as == AttachmentStrategy::hidden() )
668 actionName =
"view_attachments_hide";
669 else if ( as == AttachmentStrategy::headerOnly() )
670 actionName =
"view_attachments_headeronly";
673 return static_cast<TDERadioAction*
>(mActionCollection->action(actionName));
678 void KMReaderWin::slotEnterpriseHeaders() {
680 HeaderStrategy::rich() );
681 if( !mExternalWindow )
685 void KMReaderWin::slotFancyHeaders() {
687 HeaderStrategy::rich() );
688 if( !mExternalWindow )
692 void KMReaderWin::slotBriefHeaders() {
694 HeaderStrategy::brief() );
695 if( !mExternalWindow )
699 void KMReaderWin::slotStandardHeaders() {
701 HeaderStrategy::standard());
705 void KMReaderWin::slotLongHeaders() {
707 HeaderStrategy::rich() );
708 if( !mExternalWindow )
712 void KMReaderWin::slotAllHeaders() {
714 HeaderStrategy::all() );
715 if( !mExternalWindow )
719 void KMReaderWin::slotLevelQuote(
int l )
726 void KMReaderWin::slotCycleHeaderStyles() {
730 const char * actionName = 0;
731 if ( style == HeaderStyle::enterprise() ) {
733 actionName =
"view_headers_fancy";
735 if ( style == HeaderStyle::fancy() ) {
737 actionName =
"view_headers_brief";
738 }
else if ( style == HeaderStyle::brief() ) {
739 slotStandardHeaders();
740 actionName =
"view_headers_standard";
741 }
else if ( style == HeaderStyle::plain() ) {
742 if ( strategy == HeaderStrategy::standard() ) {
744 actionName =
"view_headers_long";
745 }
else if ( strategy == HeaderStrategy::rich() ) {
747 actionName =
"view_headers_all";
748 }
else if ( strategy == HeaderStrategy::all() ) {
749 slotEnterpriseHeaders();
750 actionName =
"view_headers_enterprise";
755 static_cast<TDERadioAction*
>( mActionCollection->action( actionName ) )->setChecked(
true );
759 void KMReaderWin::slotIconicAttachments() {
760 setAttachmentStrategy( AttachmentStrategy::iconic() );
763 void KMReaderWin::slotSmartAttachments() {
764 setAttachmentStrategy( AttachmentStrategy::smart() );
767 void KMReaderWin::slotInlineAttachments() {
768 setAttachmentStrategy( AttachmentStrategy::inlined() );
771 void KMReaderWin::slotHideAttachments() {
772 setAttachmentStrategy( AttachmentStrategy::hidden() );
775 void KMReaderWin::slotHeaderOnlyAttachments() {
776 setAttachmentStrategy( AttachmentStrategy::headerOnly() );
779 void KMReaderWin::slotCycleAttachmentStrategy() {
783 action->setChecked(
true );
788 KMReaderWin::~KMReaderWin()
793 clearBodyPartMementos();
794 delete mHtmlWriter; mHtmlWriter = 0;
796 if (mAutoDelete)
delete message();
797 delete mRootNode; mRootNode = 0;
803 void KMReaderWin::slotMessageArrived(
KMMessage *msg )
805 if (msg && ((KMMsgBase*)msg)->isMessage()) {
806 if ( msg->getMsgSerNum() == mWaitingForSerNum ) {
832 kdDebug(5006) <<
"KMReaderWin::update - no updated part" << endl;
835 partNode* node = mRootNode->findNodeForDwPart( msg->
lastUpdatedPart() );
837 kdDebug(5006) <<
"KMReaderWin::update - can't find node for part" << endl;
844 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRWXU );
845 TQByteArray data = node->msgPart().bodyDecodedBinary();
846 size_t size = data.size();
847 if ( node->msgPart().type() == DwMime::kTypeText && size) {
850 KPIM::kBytesToFile( data.data(), size, mAtmCurrentName,
false,
false,
false );
851 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRUSR );
859 for (TQStringList::Iterator it = mTempFiles.begin(); it != mTempFiles.end();
865 for (TQStringList::Iterator it = mTempDirs.begin(); it != mTempDirs.end();
868 TQDir(*it).rmdir(*it);
877 if (e->type() == TQEvent::ApplicationPaletteChange)
880 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
886 return TQWidget::event(e);
893 const TDEConfigGroup mdnGroup( KMKernel::config(),
"MDN" );
894 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
897 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
899 mNoMDNsWhenEncrypted = mdnGroup.readBoolEntry(
"not-send-when-encrypted",
true );
901 mUseFixedFont = reader.readBoolEntry(
"useFixedFont",
false );
902 if ( mToggleFixFontAction )
903 mToggleFixFontAction->setChecked( mUseFixedFont );
905 mHtmlMail = reader.readBoolEntry(
"htmlMail",
false );
908 HeaderStrategy::create( reader.readEntry(
"header-set-displayed",
"rich" ) ) );
909 TDERadioAction *raction = actionForHeaderStyle( headerStyle(),
headerStrategy() );
911 raction->setChecked(
true );
913 setAttachmentStrategy( AttachmentStrategy::create( reader.readEntry(
"attachment-strategy",
"smart" ) ) );
916 raction->setChecked(
true );
920 mShowColorbar = reader.readBoolEntry(
"showColorbar", Kpgp::Module::getKpgp()->usePGP() );
924 reader.writeEntry(
"showColorbar", mShowColorbar );
926 mMimeTreeAtBottom = reader.readEntry(
"MimeTreeLocation",
"bottom" ) !=
"top";
927 const TQString s = reader.readEntry(
"MimeTreeMode",
"smart" );
930 else if ( s ==
"always" )
935 const int mimeH = reader.readNumEntry(
"MimePaneHeight", 100 );
936 const int messageH = reader.readNumEntry(
"MessagePaneHeight", 180 );
937 mSplitterSizes.clear();
938 if ( mMimeTreeAtBottom )
939 mSplitterSizes << messageH << mimeH;
941 mSplitterSizes << mimeH << messageH;
945 readGlobalOverrideCodec();
953 void KMReaderWin::adjustLayout() {
954 if ( mMimeTreeAtBottom )
955 mSplitter->moveToLast( mMimePartTree );
957 mSplitter->moveToFirst( mMimePartTree );
958 mSplitter->setSizes( mSplitterSizes );
960 if ( mMimeTreeMode == 2 && mMsgDisplay )
961 mMimePartTree->show();
963 mMimePartTree->hide();
965 if ( mShowColorbar && mMsgDisplay )
972 void KMReaderWin::saveSplitterSizes( TDEConfigBase & c )
const {
973 if ( !mSplitter || !mMimePartTree )
975 if ( mMimePartTree->isHidden() )
978 c.writeEntry(
"MimePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 1 : 0 ] );
979 c.writeEntry(
"MessagePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 0 : 1 ] );
984 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
986 reader.writeEntry(
"useFixedFont", mUseFixedFont );
988 reader.writeEntry(
"header-style", headerStyle()->name() );
990 reader.writeEntry(
"header-set-displayed",
headerStrategy()->name() );
994 saveSplitterSizes( reader );
997 kmkernel->slotRequestConfigSync();
1003 mViewer->widget()->setFocusPolicy(TQWidget::WheelFocus);
1005 mViewer->setPluginsEnabled(
false);
1006 mViewer->setJScriptEnabled(
false);
1007 mViewer->setJavaEnabled(
false);
1008 mViewer->setMetaRefreshEnabled(
false);
1009 mViewer->setURLCursor(KCursor::handCursor());
1011 mViewer->view()->setLineWidth(0);
1013 mViewer->view()->viewport()->installEventFilter(
this );
1016 #ifdef KMAIL_READER_HTML_DEBUG
1017 mHtmlWriter =
new TeeHtmlWriter(
new FileHtmlWriter( TQString() ),
1018 new KHtmlPartHtmlWriter( mViewer, 0 ) );
1020 mHtmlWriter =
new KHtmlPartHtmlWriter( mViewer, 0 );
1023 connect(mViewer->browserExtension(),
1024 TQT_SIGNAL(openURLRequest(
const KURL &,
const KParts::URLArgs &)),
this,
1026 connect(mViewer->browserExtension(),
1027 TQT_SIGNAL(createNewWindow(
const KURL &,
const KParts::URLArgs &)),
this,
1029 connect(mViewer,TQT_SIGNAL(
popupMenu(
const TQString &,
const TQPoint &)),
1030 TQT_SLOT(
slotUrlPopup(
const TQString &,
const TQPoint &)));
1031 connect( kmkernel->imProxy(), TQT_SIGNAL( sigContactPresenceChanged(
const TQString & ) ),
1032 TQT_TQOBJECT(
this), TQT_SLOT( contactStatusChanged(
const TQString & ) ) );
1033 connect( kmkernel->imProxy(), TQT_SIGNAL( sigPresenceInfoExpired() ),
1037 void KMReaderWin::contactStatusChanged(
const TQString &uid)
1041 DOM::NodeList presenceNodes = mViewer->htmlDocument()
1042 .getElementsByName( DOM::DOMString( TQString::fromLatin1(
"presence-") + uid ) );
1043 for (
unsigned int i = 0; i < presenceNodes.length(); ++i ) {
1044 DOM::Node n = presenceNodes.item( i );
1045 kdDebug( 5006 ) <<
"name is " << n.nodeName().string() << endl;
1046 kdDebug( 5006 ) <<
"value of content was " << n.firstChild().nodeValue().string() << endl;
1047 TQString newPresence = kmkernel->imProxy()->presenceString( uid );
1048 if ( newPresence.isNull() )
1049 newPresence = TQString::fromLatin1(
"ENOIMRUNNING" );
1050 n.firstChild().setNodeValue( newPresence );
1056 void KMReaderWin::setAttachmentStrategy(
const AttachmentStrategy * strategy ) {
1057 mAttachmentStrategy = strategy ? strategy : AttachmentStrategy::smart();
1062 const HeaderStrategy * strategy ) {
1063 mHeaderStyle = style ? style : HeaderStyle::fancy();
1064 mHeaderStrategy = strategy ? strategy : HeaderStrategy::rich();
1065 if ( mHeaderOnlyAttachmentsAction ) {
1066 const bool styleHasAttachmentQuickList = mHeaderStyle == HeaderStyle::fancy() ||
1067 mHeaderStyle == HeaderStyle::enterprise();
1068 mHeaderOnlyAttachmentsAction->setEnabled( styleHasAttachmentQuickList );
1069 if ( !styleHasAttachmentQuickList && mAttachmentStrategy == AttachmentStrategy::headerOnly() ) {
1072 setAttachmentStrategy( AttachmentStrategy::smart() );
1081 if ( encoding == mOverrideEncoding )
1084 mOverrideEncoding = encoding;
1085 if ( mSelectEncodingAction ) {
1086 if ( encoding.isEmpty() ) {
1087 mSelectEncodingAction->setCurrentItem( 0 );
1090 TQStringList encodings = mSelectEncodingAction->items();
1092 for ( TQStringList::const_iterator it = encodings.begin(), end = encodings.end(); it != end; ++it, ++i ) {
1093 if ( TDEGlobal::charsets()->encodingForName( *it ) == encoding ) {
1094 mSelectEncodingAction->setCurrentItem( i );
1098 if ( i == encodings.size() ) {
1100 kdWarning(5006) <<
"Unknown override character encoding \"" << encoding
1101 <<
"\". Using Auto instead." << endl;
1102 mSelectEncodingAction->setCurrentItem( 0 );
1103 mOverrideEncoding = TQString();
1111 void KMReaderWin::setPrintFont(
const TQFont& font )
1114 mCSSHelper->setPrintFont( font );
1120 if ( mOverrideEncoding.isEmpty() || mOverrideEncoding ==
"Auto" )
1123 return KMMsgBase::codecForName( mOverrideEncoding.latin1() );
1127 void KMReaderWin::slotSetEncoding()
1129 if ( mSelectEncodingAction->currentItem() == 0 )
1130 mOverrideEncoding = TQString();
1132 mOverrideEncoding = TDEGlobal::charsets()->encodingForName( mSelectEncodingAction->currentText() );
1137 void KMReaderWin::readGlobalOverrideCodec()
1140 if ( GlobalSettings::self()->overrideCharacterEncoding() == mOldGlobalOverrideEncoding )
1144 mOldGlobalOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
1150 mSerNumOfOriginalMessage = serNumOfOriginalMessage;
1151 mNodeIdOffset = nodeIdOffset;
1158 kdDebug(5006) <<
"(" << aMsg->getMsgSerNum() <<
", last " << mLastSerNum <<
") " << aMsg->
subject() <<
" "
1159 << aMsg->fromStrip() <<
", readyToShow " << (aMsg->
readyToShow()) << endl;
1163 if ( aMsg && aMsg->getMsgSerNum() != mLastSerNum && !updateOnly ){
1164 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin()-1;
1165 mShowRawToltecMail = !GlobalSettings::self()->showToltecReplacementText();
1166 clearBodyPartMementos();
1171 bool complete =
true;
1174 (aMsg->getMsgSerNum() != mLastSerNum) &&
1179 if (!force && aMsg && mLastSerNum != 0 && aMsg->getMsgSerNum() == mLastSerNum)
1186 aMsg->attach(
this );
1189 mDelayedMarkTimer.stop();
1193 mWaitingForSerNum = 0;
1196 mLastSerNum = aMsg->getMsgSerNum();
1213 mViewer->setDNDEnabled(
false );
1215 mViewer->setDNDEnabled(
true );
1225 mUpdateReaderWinTimer.stop();
1228 else if (mUpdateReaderWinTimer.isActive())
1229 mUpdateReaderWinTimer.changeInterval( delay );
1231 mUpdateReaderWinTimer.start( 0,
true );
1234 if ( aMsg && (aMsg->isUnread() || aMsg->isNew()) && GlobalSettings::self()->delayedMarkAsRead() ) {
1235 if ( GlobalSettings::self()->delayedMarkTime() != 0 )
1236 mDelayedMarkTimer.start( GlobalSettings::self()->delayedMarkTime() * 1000,
true );
1241 mHeaderRefreshTimer.start( 1000,
false );
1247 mUpdateReaderWinTimer.stop();
1249 mDelayedMarkTimer.stop();
1251 mWaitingForSerNum = 0;
1256 static const char *
const kmailChanges[] = {
1259 static const int numKMailChanges =
1260 sizeof kmailChanges /
sizeof *kmailChanges;
1266 static const char *
const kmailNewFeatures[] = {
1267 I18N_NOOP(
"Full namespace support for IMAP"),
1268 I18N_NOOP(
"Offline mode"),
1269 I18N_NOOP(
"Sieve script management and editing"),
1270 I18N_NOOP(
"Account specific filtering"),
1271 I18N_NOOP(
"Filtering of incoming mail for online IMAP accounts"),
1272 I18N_NOOP(
"Online IMAP folders can be used when filtering into folders"),
1273 I18N_NOOP(
"Automatically delete older mails on POP servers")
1275 static const int numKMailNewFeatures =
1276 sizeof kmailNewFeatures /
sizeof *kmailNewFeatures;
1284 for (
int i = 0 ; i < numKMailChanges ; ++i )
1285 str += kmailChanges[i];
1286 for (
int i = 0 ; i < numKMailNewFeatures ; ++i )
1287 str += kmailNewFeatures[i];
1289 return md5.base64Digest();
1295 mMsgDisplay =
false;
1298 TQString location = locate(
"data",
"kmail/about/main.html");
1299 TQString content = KPIM::kFileToString(location);
1300 content = content.arg( locate(
"data",
"libtdepim/about/kde_infopage.css" ) );
1301 if ( kapp->reverseLayout() )
1302 content = content.arg(
"@import \"%1\";" ).arg( locate(
"data",
"libtdepim/about/kde_infopage_rtl.css" ) );
1304 content = content.arg(
"" );
1306 mViewer->begin(KURL( location ));
1308 TQString fontSize = TQString::number(
pointsToPixel( mCSSHelper->bodyFont().pointSize() ) );
1309 TQString appTitle = i18n(
"KMail");
1310 TQString catchPhrase =
"";
1311 TQString quickDescription = i18n(
"The email client for the Trinity Desktop Environment.");
1312 mViewer->write(content.arg(fontSize).arg(appTitle).arg(catchPhrase).arg(quickDescription).arg(info));
1319 i18n(
"<h2 style='margin-top: 0px;'>Retrieving Folder Contents</h2><p>Please wait . . .</p> " );
1327 i18n(
"<h2 style='margin-top: 0px;'>Offline</h2><p>KMail is currently in offline mode. "
1328 "Click <a href=\"kmail:goOnline\">here</a> to go online . . .</p> " );
1338 i18n(
"%1: KMail version; %2: help:// URL; %3: homepage URL; "
1339 "%4: prior KMail version; %5: prior TDE version; "
1340 "%6: generated list of new features; "
1341 "%7: First-time user text (only shown on first start); "
1342 "%8: generated list of important changes; "
1343 "--- end of comment ---",
1344 "<h2 style='margin-top: 0px;'>Welcome to KMail %1</h2><p>KMail is the email client for the Trinity "
1345 "Desktop Environment. It is designed to be fully compatible with "
1346 "Internet mailing standards including MIME, SMTP, POP3 and IMAP."
1348 "<ul><li>KMail has many powerful features which are described in the "
1349 "<a href=\"%2\">documentation</a></li>\n"
1350 "<li>The <a href=\"%3\">KMail (TDE) homepage</A> offers information about "
1351 "new versions of KMail</li></ul>\n"
1353 "<p>Some of the new features in this release of KMail include "
1354 "(compared to KMail %4, which is part of TDE %5):</p>\n"
1357 "<p>We hope that you will enjoy KMail.</p>\n"
1358 "<p>Thank you,</p>\n"
1359 "<p style='margin-bottom: 0px'> The KMail Team</p>")
1361 .arg(
"help:/kmail/index.html")
1362 .arg(
"http://www.trinitydesktop.org")
1363 .arg(
"1.8").arg(
"3.4");
1365 TQString featureItems;
1366 for (
int i = 0 ; i < numKMailNewFeatures ; i++ )
1367 featureItems += i18n(
"<li>%1</li>\n").arg( i18n( kmailNewFeatures[i] ) );
1369 info = info.arg( featureItems );
1371 if( kmkernel->firstStart() ) {
1372 info = info.arg( i18n(
"<p>Please take a moment to fill in the KMail "
1373 "configuration panel at Settings->Configure "
1375 "You need to create at least a default identity and "
1376 "an incoming as well as outgoing mail account."
1379 info = info.arg( TQString() );
1382 if ( ( numKMailChanges > 1 ) || ( numKMailChanges == 1 && strlen(kmailChanges[0]) > 0 ) ) {
1383 TQString changesText =
1384 i18n(
"<p><span style='font-size:125%; font-weight:bold;'>"
1385 "Important changes</span> (compared to KMail %1):</p>\n")
1387 changesText +=
"<ul>\n";
1388 for (
int i = 0 ; i < numKMailChanges ; i++ )
1389 changesText += i18n(
"<li>%1</li>\n").arg( i18n( kmailChanges[i] ) );
1390 changesText +=
"</ul>\n";
1391 info = info.arg( changesText );
1394 info = info.arg(
"");
1409 if (!mMsgDisplay)
return;
1416 if ( mShowColorbar )
1425 mMimePartTree->hide();
1426 mMimePartTree->clear();
1427 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1428 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) +
"</body></html>" );
1432 if (mSavedRelativePosition)
1434 TQScrollView * scrollview =
static_cast<TQScrollView *
>(mViewer->widget());
1435 scrollview->setContentsPos( 0,
1436 tqRound( scrollview->contentsHeight() * mSavedRelativePosition ) );
1437 mSavedRelativePosition = 0;
1444 const TQPaintDeviceMetrics pdm(mViewer->view());
1446 return (pointSize * pdm.logicalDpiY() + 36) / 72;
1451 if ( mMimeTreeModeOverride == 2 ||
1452 ( mMimeTreeModeOverride != 0 && (mMimeTreeMode == 2 ||
1453 ( mMimeTreeMode == 1 && !isPlainTextTopLevel ) ) ) ) {
1454 mMimePartTree->show();
1458 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
1459 saveSplitterSizes( reader );
1460 mMimePartTree->hide();
1463 if ( mToggleMimePartTreeAction && mToggleMimePartTreeAction->isChecked() != mMimePartTree->isVisible() ) {
1464 mToggleMimePartTreeAction->setChecked( mMimePartTree->isVisible() );
1471 mMimePartTree->clear();
1472 mMimeTreeModeOverride = -1;
1474 ( msg->type() == DwMime::kTypeText
1475 && msg->subtype() == DwMime::kSubtypePlain ) );
1482 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1483 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
1494 if( mColorBar->isNeutral() )
1500 TQTimer::singleShot( 1, TQT_TQOBJECT(
this), TQT_SLOT(injectAttachments()) );
1503 static bool message_was_saved_decrypted_before(
const KMMessage * msg ) {
1507 return msg->
msgId().stripWhiteSpace().startsWith(
"<DecryptedMsg." );
1513 KMMessagePart msgPart;
1514 TQCString subtype, contDisp;
1519 aMsg->setIsBeingParsed(
true );
1521 if ( mRootNode && !mRootNode->processed() )
1523 kdWarning() <<
"The root node is not yet processed! Danger!\n";
1527 mRootNode = partNode::fromMessage( aMsg,
this );
1528 const TQCString mainCntTypeStr = mRootNode->typeString() +
'/' + mRootNode->subTypeString();
1530 TQString cntDesc = aMsg->
subject();
1531 if( cntDesc.isEmpty() )
1532 cntDesc = i18n(
"( body part )");
1533 TDEIO::filesize_t cntSize = aMsg->
msgSize();
1541 mRootNode->fillMimePartTree( 0,
1548 partNode* vCardNode = mRootNode->findType( DwMime::kTypeText, DwMime::kSubtypeXVCard );
1549 bool hasVCard =
false;
1553 TDEABC::VCardConverter t;
1554 #if defined(KABC_VCARD_ENCODING_FIX)
1555 const TQByteArray vcard = vCardNode->msgPart().bodyDecodedBinary();
1556 if ( !t.parseVCardsRaw( vcard.data() ).empty() ) {
1558 const TQString vcard = vCardNode->msgPart().bodyToUnicode(
overrideCodec() );
1559 if ( !t.parseVCards( vcard ).empty() ) {
1566 if ( !mRootNode || !mRootNode->isToltecMessage() || mShowRawToltecMail ) {
1571 ObjectTreeParser otp(
this );
1572 otp.setAllowAsync(
true );
1573 otp.setShowRawToltecMail( mShowRawToltecMail );
1574 otp.parseObjectTree( mRootNode );
1578 KMMsgEncryptionState encryptionState = mRootNode->overallEncryptionState();
1579 KMMsgSignatureState signatureState = mRootNode->overallSignatureState();
1589 if ( signatureState != KMMsgNotSigned ||
1594 bool emitReplaceMsgByUnencryptedVersion =
false;
1595 const TDEConfigGroup reader( KMKernel::config(),
"Reader" );
1596 if ( reader.readBoolEntry(
"store-displayed-messages-unencrypted",
false ) ) {
1611 kdDebug(5006) <<
"\n\n\nKMReaderWin::parseMsg() - special post-encryption handling:\n1." << endl;
1612 kdDebug(5006) <<
"(aMsg == msg) = " << (aMsg ==
message()) << endl;
1613 kdDebug(5006) <<
"aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() = " << (aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder()) << endl;
1614 kdDebug(5006) <<
"message_was_saved_decrypted_before( aMsg ) = " << message_was_saved_decrypted_before( aMsg ) << endl;
1615 kdDebug(5006) <<
"this->decryptMessage() = " <<
decryptMessage() << endl;
1616 kdDebug(5006) <<
"otp.hasPendingAsyncJobs() = " << otp.hasPendingAsyncJobs() << endl;
1617 kdDebug(5006) <<
" (KMMsgFullyEncrypted == encryptionState) = " << (KMMsgFullyEncrypted == encryptionState) << endl;
1618 kdDebug(5006) <<
"|| (KMMsgPartiallyEncrypted == encryptionState) = " << (KMMsgPartiallyEncrypted == encryptionState) << endl;
1623 && ( aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() )
1625 && !message_was_saved_decrypted_before( aMsg )
1629 && !otp.hasPendingAsyncJobs()
1631 && ( (KMMsgFullyEncrypted == encryptionState)
1632 || (KMMsgPartiallyEncrypted == encryptionState) ) ) {
1634 kdDebug(5006) <<
"KMReaderWin - calling objectTreeToDecryptedMsg()" << endl;
1636 NewByteArray decryptedData;
1638 objectTreeToDecryptedMsg( mRootNode, decryptedData, *aMsg );
1640 decryptedData.appendNULL();
1641 TQCString resultString( decryptedData.data() );
1642 kdDebug(5006) <<
"KMReaderWin - resulting data:" << resultString << endl;
1644 if( !resultString.isEmpty() ) {
1645 kdDebug(5006) <<
"KMReaderWin - composing unencrypted message" << endl;
1647 aMsg->
setBody( resultString );
1649 unencryptedMessage->setParent( 0 );
1658 kdDebug(5006) <<
"KMReaderWin - attach unencrypted message to aMsg" << endl;
1660 emitReplaceMsgByUnencryptedVersion =
true;
1666 const int rootNodeCntType = mRootNode ? mRootNode->type() : DwMime::kTypeText;
1667 const int rootNodeCntSubtype = mRootNode ? mRootNode->subType() : DwMime::kSubtypePlain;
1672 if( emitReplaceMsgByUnencryptedVersion ) {
1673 kdDebug(5006) <<
"KMReaderWin - invoce saving in decrypted form:" << endl;
1676 kdDebug(5006) <<
"KMReaderWin - finished parsing and displaying of message." << endl;
1678 rootNodeCntSubtype == DwMime::kSubtypePlain );
1681 aMsg->setIsBeingParsed(
false );
1686 void KMReaderWin::updateHeader()
1698 if (currentMessage &&
1699 mHeaderStyle == HeaderStyle::fancy() &&
1700 currentMessage->parent())
1704 DOM::NodeList divs(mViewer->document().documentElement().getElementsByTagName(
"div"));
1705 DOM::NodeList headerDivs(
static_cast<DOM::HTMLDivElement
>(divs.item(0)).getElementsByTagName(
"div"));
1706 for (i=0; i<((int)headerDivs.length()); i++) {
1707 if (
static_cast<DOM::HTMLDivElement
>(headerDivs.item(i)).
id().string() ==
"sendersCurrentTime") {
1713 if (divNumber >= 0) {
1714 DOM::HTMLDivElement elem =
static_cast<DOM::HTMLDivElement
>(headerDivs.item(i));
1718 TQString latestHeader = headerStyle()->format( currentMessage,
headerStrategy(),
"", mPrinting,
false );
1719 int startPos = latestHeader.find(
"<div id=\"sendersCurrentTime\" style=\"");
1720 if (startPos >= 0) {
1721 latestHeader = latestHeader.mid(startPos);
1722 int endPos = latestHeader.find(
"</div>");
1724 endPos = endPos + 6;
1725 latestHeader.truncate(endPos);
1727 TQString divText = latestHeader;
1728 TQString divStyle = latestHeader;
1730 divText = divText.mid(divText.find(
">")+1);
1731 divText.truncate(divText.find(
"</div>"));
1733 divStyle = divStyle.mid(TQString(
"<div id=\"sendersCurrentTime\" style=\"").length());
1734 divStyle.truncate(divStyle.find(
"\""));
1736 elem.setInnerHTML(divText);
1737 elem.setAttribute(
"style", divStyle);
1738 elem.applyChanges();
1748 kdFatal( !headerStyle(), 5006 )
1749 <<
"trying to writeMsgHeader() without a header style set!" << endl;
1751 <<
"trying to writeMsgHeader() without a header strategy set!" << endl;
1754 href = vCardNode->asHREF(
"body" );
1756 return headerStyle()->format( aMsg,
headerStrategy(), href, mPrinting, topLevel );
1765 TQString fileName = aMsgPart->fileName();
1766 if( fileName.isEmpty() )
1767 fileName = aMsgPart->name();
1770 TQString fname =
createTempDir( TQString::number( aPartNum ) );
1771 if ( fname.isEmpty() )
1775 int slashPos = fileName.findRev(
'/' );
1776 if( -1 != slashPos )
1777 fileName = fileName.mid( slashPos + 1 );
1778 if( fileName.isEmpty() )
1779 fileName =
"unnamed";
1780 fname +=
"/" + fileName;
1782 TQByteArray data = aMsgPart->bodyDecodedBinary();
1783 size_t size = data.size();
1784 if ( aMsgPart->type() == DwMime::kTypeText && size) {
1788 if( !KPIM::kBytesToFile( data.data(), size, fname,
false,
false,
false ) )
1791 mTempFiles.append( fname );
1794 ::chmod( TQFile::encodeName( fname ), S_IRUSR );
1801 KTempFile *tempFile =
new KTempFile( TQString(),
"." + param );
1802 tempFile->setAutoDelete(
true );
1803 TQString fname = tempFile->name();
1806 if( ::access( TQFile::encodeName( fname ), W_OK ) != 0 )
1808 if( ::mkdir( TQFile::encodeName( fname ), 0 ) != 0
1809 || ::chmod( TQFile::encodeName( fname ), S_IRWXU ) != 0 )
1812 assert( !fname.isNull() );
1814 mTempDirs.append( fname );
1821 #if defined(KABC_VCARD_ENCODING_FIX)
1822 const TQByteArray vCard = msgPart->bodyDecodedBinary();
1824 const TQString vCard = msgPart->bodyToUnicode(
overrideCodec() );
1826 VCardViewer *vcv =
new VCardViewer(
this, vCard,
"vCardDialog" );
1834 mViewer->view()->print();
1841 if (aUrl.isEmpty())
return -1;
1842 if (!aUrl.isLocalFile())
return -1;
1844 TQString path = aUrl.path();
1845 uint right = path.findRev(
'/');
1846 uint left = path.findRev(
'.', right);
1849 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
1850 return (ok) ? res : -1;
1855 void KMReaderWin::resizeEvent(TQResizeEvent *)
1857 if( !mResizeTimer.isActive() )
1863 mResizeTimer.start( 100,
true );
1869 void KMReaderWin::slotDelayedResize()
1871 mSplitter->setGeometry(0, 0, width(), height());
1876 void KMReaderWin::slotTouchMessage()
1885 serNums.append(
message()->getMsgSerNum() );
1886 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
1890 if ( mNoMDNsWhenEncrypted &&
1891 message()->encryptionState() != KMMsgNotEncrypted &&
1892 message()->encryptionState() != KMMsgEncryptionStateUnknown )
1904 if ( !kmkernel->msgSender()->send( receipt ) )
1905 KMessageBox::error(
this, i18n(
"Could not send MDN.") );
1912 TQWidget::closeEvent(e);
1917 bool foundSMIMEData(
const TQString aUrl,
1918 TQString& displayName,
1922 static TQString showCertMan(
"showCertificate#");
1926 int i1 = aUrl.find( showCertMan );
1928 i1 += showCertMan.length();
1929 int i2 = aUrl.find(
" ### ", i1);
1932 displayName = aUrl.mid( i1, i2-i1 );
1934 i2 = aUrl.find(
" ### ", i1);
1937 libName = aUrl.mid( i1, i2-i1 );
1940 keyId = aUrl.mid( i2 );
1956 return !keyId.isEmpty();
1963 const KURL url(aUrl);
1965 if ( url.protocol() ==
"kmail" || url.protocol() ==
"x-kmail" || url.protocol() ==
"attachment"
1966 || (url.protocol().isEmpty() && url.path().isEmpty()) ) {
1967 mViewer->setDNDEnabled(
false );
1969 mViewer->setDNDEnabled(
true );
1972 if ( aUrl.stripWhiteSpace().isEmpty() ) {
1973 KPIM::BroadcastStatus::instance()->reset();
1974 mHoveredUrl = KURL();
1975 mLastClickImagePath = TQString();
1981 const TQString msg = URLHandlerManager::instance()->statusBarMessage( url,
this );
1983 kdWarning( msg.isEmpty(), 5006 ) <<
"KMReaderWin::slotUrlOn(): Unhandled URL hover!" << endl;
1984 KPIM::BroadcastStatus::instance()->setTransienStatusMsg( msg );
1993 if ( URLHandlerManager::instance()->handleClick( aUrl,
this ) )
1996 kdWarning( 5006 ) <<
"KMReaderWin::slotOpenUrl(): Unhandled URL click!" << endl;
2003 const KURL url( aUrl );
2006 if ( url.protocol() ==
"mailto" ) {
2007 mCopyURLAction->setText( i18n(
"Copy Email Address" ) );
2009 mCopyURLAction->setText( i18n(
"Copy Link Address" ) );
2012 if ( URLHandlerManager::instance()->handleContextMenuRequest( url, aPos,
this ) )
2016 kdWarning( 5006 ) <<
"KMReaderWin::slotUrlPopup(): Unhandled URL right-click!" << endl;
2017 emitPopupMenu( url, aPos );
2023 static bool hasParentDivWithId(
const DOM::Node &start,
const TQString &
id )
2025 if ( start.isNull() )
2028 if ( start.nodeName().string() ==
"div" ) {
2029 for (
unsigned int i = 0; i < start.attributes().length(); i++ ) {
2030 if ( start.attributes().item( i ).nodeName().string() ==
"id" &&
2031 start.attributes().item( i ).nodeValue().string() ==
id )
2036 if ( !start.parentNode().isNull() )
2037 return hasParentDivWithId( start.parentNode(),
id );
2042 void KMReaderWin::showAttachmentPopup(
int id,
const TQString & name,
const TQPoint & p )
2045 mAtmCurrentName = name;
2046 TDEPopupMenu *menu =
new TDEPopupMenu();
2047 menu->insertItem(SmallIcon(
"document-open"),i18n(
"to open",
"Open"), 1);
2048 menu->insertItem(i18n(
"Open With..."), 2);
2049 menu->insertItem(i18n(
"to view something",
"View"), 3);
2050 menu->insertItem(SmallIcon(
"document-save-as"),i18n(
"Save As..."), 4);
2051 menu->insertItem(SmallIcon(
"edit-copy"), i18n(
"Copy"), 9 );
2052 const bool canChange =
message()->parent() ? !
message()->parent()->isReadOnly() :
false;
2053 if ( GlobalSettings::self()->allowAttachmentEditing() && canChange )
2054 menu->insertItem(SmallIcon(
"edit"), i18n(
"Edit Attachment"), 8 );
2055 if ( GlobalSettings::self()->allowAttachmentDeletion() && canChange )
2056 menu->insertItem(SmallIcon(
"edit-delete"), i18n(
"Delete Attachment"), 7 );
2057 if ( name.endsWith(
".xia",
false ) &&
2058 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) )
2059 menu->insertItem( i18n(
"Decrypt With Chiasmus..." ), 6 );
2060 menu->insertItem(i18n(
"Properties"), 5);
2062 const bool attachmentInHeader = hasParentDivWithId( mViewer->nodeUnderMouse(),
"attachmentInjectionPoint" );
2063 const bool hasScrollbar = mViewer->view()->verticalScrollBar()->isVisible();
2064 if ( attachmentInHeader && hasScrollbar ) {
2065 menu->insertItem( i18n(
"Scroll To"), 10 );
2068 connect(menu, TQT_SIGNAL(activated(
int)), TQT_TQOBJECT(
this), TQT_SLOT(slotHandleAttachment(
int)));
2080 if( style().isA(
"KeramikStyle") )
2081 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
2083 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
2084 if ( frameWidth < 0 )
2086 if ( frameWidth != mBox->lineWidth() )
2087 mBox->setLineWidth( frameWidth );
2094 TQWidget::styleChange( oldStyle );
2098 void KMReaderWin::slotHandleAttachment(
int choice )
2101 partNode* node = mRootNode ? mRootNode->findId( mAtmCurrent ) : 0;
2102 if ( mAtmCurrentName.isEmpty() && node )
2103 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2105 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand(
2106 node,
message(), mAtmCurrent, mAtmCurrentName,
2107 KMHandleAttachmentCommand::AttachmentAction( choice ), 0,
this );
2108 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2109 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2111 }
else if ( choice == 7 ) {
2112 slotDeleteAttachment( node );
2113 }
else if ( choice == 8 ) {
2114 slotEditAttachment( node );
2115 }
else if ( choice == 9 ) {
2116 if ( !node )
return;
2118 KURL url = tempFileUrlFromPartNode( node );
2119 if (!url.isValid() )
return;
2121 KURLDrag* drag =
new KURLDrag( urls,
this );
2122 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
2123 }
else if ( choice == 10 ) {
2131 mViewer->findText();
2137 mViewer->findTextNext();
2143 mUseFixedFont = !mUseFixedFont;
2152 if ( mToggleMimePartTreeAction->isChecked() ) {
2153 mMimeTreeModeOverride = 2;
2155 mMimeTreeModeOverride = 0;
2163 kapp->clipboard()->setText( mViewer->selectedText() );
2170 assert(aMsgPart!=0);
2172 msg->fromString(aMsgPart->bodyDecoded());
2176 msg->setParent(
message()->parent() );
2177 msg->setUID(
message()->UID());
2179 KMReaderMainWin *win =
new KMReaderMainWin();
2188 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2189 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2192 ObjectTreeParser otp(
this, 0,
true );
2193 otp.parseObjectTree( node );
2202 const TQString& aFileName,
const TQString& pname )
2205 if (kasciistricmp(aMsgPart->typeStr(),
"message")==0) {
2208 assert(aMsgPart!=0);
2209 msg->fromString(aMsgPart->bodyDecoded());
2210 mMainWindow->setCaption(msg->
subject());
2212 setAutoDelete(
true);
2213 }
else if (kasciistricmp(aMsgPart->typeStr(),
"text")==0) {
2214 if (kasciistricmp(aMsgPart->subtypeStr(),
"x-vcard") == 0) {
2218 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2219 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2221 if (aHTML && (kasciistricmp(aMsgPart->subtypeStr(),
"html")==0)) {
2226 const TQCString str = aMsgPart->bodyDecoded();
2227 ObjectTreeParser otp(
this );
2228 otp.writeBodyStr( str,
2234 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2235 }
else if (kasciistricmp(aMsgPart->typeStr(),
"image")==0 ||
2236 (kasciistricmp(aMsgPart->typeStr(),
"application")==0 &&
2237 kasciistricmp(aMsgPart->subtypeStr(),
"postscript")==0))
2239 if (aFileName.isEmpty())
return;
2241 TQImageIO *iio =
new TQImageIO();
2242 iio->setFileName(aFileName);
2244 TQImage img = iio->image();
2245 TQRect desk = TDEGlobalSettings::desktopGeometry(mMainWindow);
2248 if( img.width() < 50 )
2250 else if( img.width()+20 < desk.width() )
2251 width = img.width()+20;
2253 width = desk.width();
2254 if( img.height() < 50 )
2256 else if( img.height()+20 < desk.height() )
2257 height = img.height()+20;
2259 height = desk.height();
2260 mMainWindow->resize( width, height );
2263 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2264 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2266 KURL::encode_string( aFileName ) +
2267 "\" border=\"0\">\n"
2268 "</body></html>\n" );
2270 setCaption( i18n(
"View Attachment: %1").arg( pname ) );
2274 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2275 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2278 TQString str = aMsgPart->bodyDecoded();
2281 if( str.length() < (
unsigned) aMsgPart->decodedSize() ) {
2282 str.prepend( i18n(
"[KMail: Attachment contains binary data. Trying to show first character.]",
2283 "[KMail: Attachment contains binary data. Trying to show first %n characters.]",
2284 str.length()) + TQChar(
'\n') );
2286 htmlWriter()->queue( TQStyleSheet::escape( str ) );
2290 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2299 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2302 mAtmCurrentName = name;
2303 if ( mAtmCurrentName.isEmpty() )
2304 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2306 KMMessagePart& msgPart = node->msgPart();
2307 TQString pname = msgPart.fileName();
2308 if (pname.isEmpty()) pname=msgPart.name();
2309 if (pname.isEmpty()) pname=msgPart.contentDescription();
2310 if (pname.isEmpty()) pname=
"unnamed";
2312 if (kasciistricmp(msgPart.typeStr(),
"message")==0) {
2314 }
else if ((kasciistricmp(msgPart.typeStr(),
"text")==0) &&
2315 (kasciistricmp(msgPart.subtypeStr(),
"x-vcard")==0)) {
2318 KMReaderMainWin *win =
new KMReaderMainWin(&msgPart,
htmlMail(),
2326 void KMReaderWin::openAttachment(
int id,
const TQString & name )
2328 mAtmCurrentName = name;
2331 TQString str, pname, cmd, fileName;
2333 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2335 kdWarning(5006) <<
"KMReaderWin::openAttachment - could not find node " <<
id << endl;
2338 if ( mAtmCurrentName.isEmpty() )
2339 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2341 KMMessagePart& msgPart = node->msgPart();
2342 if (kasciistricmp(msgPart.typeStr(),
"message")==0)
2348 TQCString contentTypeStr( msgPart.typeStr() +
'/' + msgPart.subtypeStr() );
2349 KPIM::kAsciiToLower( contentTypeStr.data() );
2351 if ( qstrcmp( contentTypeStr,
"text/x-vcard" ) == 0 ) {
2357 KMimeType::Ptr mimetype;
2359 mimetype = KMimeType::mimeType( TQString::fromLatin1( contentTypeStr ) );
2360 if ( mimetype->name() ==
"application/octet-stream" ) {
2362 mimetype = KMimeType::findByPath( name, 0,
true );
2364 if ( ( mimetype->name() ==
"application/octet-stream" )
2365 && msgPart.isComplete() ) {
2368 mimetype = KMimeType::findByFileContent( name );
2371 KService::Ptr offer =
2372 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
2375 TQString filenameText = msgPart.fileName();
2376 if ( filenameText.isEmpty() )
2377 filenameText = msgPart.name();
2379 open_text = i18n(
"&Open with '%1'").arg( offer->name() );
2381 open_text = i18n(
"&Open With...");
2383 const TQString text = i18n(
"Open attachment '%1'?\n"
2384 "Note that opening an attachment may compromise "
2385 "your system's security.")
2386 .arg( filenameText );
2387 const int choice = KMessageBox::questionYesNoCancel(
this, text,
2388 i18n(
"Open Attachment?"), KStdGuiItem::saveAs(), open_text,
2389 TQString::fromLatin1(
"askSave") + mimetype->name() );
2391 if( choice == KMessageBox::Yes ) {
2393 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2394 message(), mAtmCurrent, mAtmCurrentName, KMHandleAttachmentCommand::Save,
2396 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2397 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2400 else if( choice == KMessageBox::No ) {
2401 KMHandleAttachmentCommand::AttachmentAction action = ( offer ?
2402 KMHandleAttachmentCommand::Open : KMHandleAttachmentCommand::OpenWith );
2404 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2405 message(), mAtmCurrent, mAtmCurrentName, action, offer,
this );
2406 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2407 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2410 kdDebug(5006) <<
"Canceled opening attachment" << endl;
2417 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -10);
2422 void KMReaderWin::slotScrollDown()
2424 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, 10);
2427 bool KMReaderWin::atBottom()
const
2429 const TQScrollView *view =
static_cast<const TQScrollView *
>(mViewer->widget());
2430 return view->contentsY() + view->visibleHeight() >= view->contentsHeight();
2434 void KMReaderWin::slotJumpDown()
2436 TQScrollView *view =
static_cast<TQScrollView *
>(mViewer->widget());
2437 int offs = (view->clipper()->height() < 30) ? view->clipper()->height() : 30;
2438 view->scrollBy( 0, view->clipper()->height() - offs );
2442 void KMReaderWin::slotScrollPrior()
2444 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -(
int)(height()*0.8));
2449 void KMReaderWin::slotScrollNext()
2451 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, (
int)(height()*0.8));
2455 void KMReaderWin::slotDocumentChanged()
2462 void KMReaderWin::slotTextSelected(
bool)
2464 TQString temp = mViewer->selectedText();
2465 kapp->clipboard()->setText(temp);
2471 mViewer->selectAll();
2477 TQString temp = mViewer->selectedText();
2483 void KMReaderWin::slotDocumentDone()
2490 void KMReaderWin::setHtmlOverride(
bool override)
2492 mHtmlOverride =
override;
2501 mHtmlLoadExtDefault = loadExtDefault;
2506 mHtmlLoadExtOverride = loadExtOverride;
2513 return ((mHtmlMail && !mHtmlOverride) || (!mHtmlMail && mHtmlOverride));
2522 return mHtmlLoadExtOverride;
2526 if (mRootNode->overallEncryptionState() != KMMsgNotEncrypted)
2528 return mHtmlLoadExtOverride;
2531 return ((mHtmlLoadExtDefault && !mHtmlLoadExtOverride) ||
2532 (!mHtmlLoadExtDefault && mHtmlLoadExtOverride));
2539 const TQScrollView * scrollview =
static_cast<TQScrollView *
>( mViewer->widget() );
2540 mSavedRelativePosition =
2541 static_cast<float>( scrollview->contentsY() ) / scrollview->contentsHeight();
2550 setMsg( msg, force,
true );
2558 KMFolder*& folder = aFolder ? *aFolder : tmpFolder;
2569 kdWarning(5006) <<
"Attempt to reference invalid serial number " << mLastSerNum <<
"\n" << endl;
2578 void KMReaderWin::slotUrlClicked()
2580 KMMainWidget *mainWidget =
dynamic_cast<KMMainWidget*
>(mMainWindow);
2583 identity =
message()->parent()->identity();
2586 KMCommand *command =
new KMUrlClickedCommand( mClickedUrl, identity,
this,
2587 false, mainWidget );
2592 void KMReaderWin::slotMailtoCompose()
2594 KMCommand *command =
new KMMailtoComposeCommand( mClickedUrl,
message() );
2599 void KMReaderWin::slotMailtoForward()
2601 KMCommand *command =
new KMMailtoForwardCommand( mMainWindow, mClickedUrl,
2607 void KMReaderWin::slotMailtoAddAddrBook()
2609 KMCommand *command =
new KMMailtoAddAddrBookCommand( mClickedUrl,
2615 void KMReaderWin::slotMailtoOpenAddrBook()
2617 KMCommand *command =
new KMMailtoOpenAddrBookCommand( mClickedUrl,
2627 KMCommand *command =
2628 new KMUrlCopyCommand( mClickedUrl,
2629 dynamic_cast<KMMainWidget*
>( mMainWindow ) );
2636 if ( !url.isEmpty() )
2638 KMCommand *command =
new KMUrlOpenCommand( mClickedUrl,
this );
2643 void KMReaderWin::slotAddBookmarks()
2645 KMCommand *command =
new KMAddBookmarksCommand( mClickedUrl,
this );
2652 KMCommand *command =
new KMUrlSaveCommand( mClickedUrl, mMainWindow );
2659 KMCommand *command =
new KMMailtoReplyCommand( mMainWindow, mClickedUrl,
2666 return mRootNode ? mRootNode->findId(
msgPartFromUrl( url ) ) : 0 ;
2669 partNode * KMReaderWin::partNodeForId(
int id ) {
2670 return mRootNode ? mRootNode->findId(
id ) : 0 ;
2674 KURL KMReaderWin::tempFileUrlFromPartNode(
const partNode * node )
2676 if (!node)
return KURL();
2677 TQStringList::const_iterator it = mTempFiles.begin();
2678 TQStringList::const_iterator end = mTempFiles.end();
2680 while ( it != end ) {
2681 TQString path = *it;
2683 uint right = path.findRev(
'/');
2684 uint left = path.findRev(
'.', right);
2687 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
2688 if ( res == node->nodeId() )
2689 return KURL( path );
2695 void KMReaderWin::slotSaveAttachments()
2698 KMSaveAttachmentsCommand *saveCommand =
new KMSaveAttachmentsCommand( mMainWindow,
2700 saveCommand->start();
2704 void KMReaderWin::saveAttachment(
const KURL &tempFileName )
2707 mAtmCurrentName = mClickedUrl.path();
2708 slotHandleAttachment( KMHandleAttachmentCommand::Save );
2712 void KMReaderWin::slotSaveMsg()
2714 KMSaveMsgCommand *saveCommand =
new KMSaveMsgCommand( mMainWindow,
message() );
2716 if (saveCommand->url().isEmpty())
2719 saveCommand->start();
2724 KMCommand *command =
new KMIMChatCommand( mClickedUrl,
message() );
2729 static TQString linkForNode(
const DOM::Node &node )
2732 if ( node.isNull() )
2735 const DOM::NamedNodeMap attributes = node.attributes();
2736 if ( !attributes.isNull() ) {
2737 const DOM::Node href = attributes.getNamedItem( DOM::DOMString(
"href" ) );
2738 if ( !href.isNull() ) {
2739 return href.nodeValue().string();
2742 if ( !node.parentNode().isNull() ) {
2743 return linkForNode( node.parentNode() );
2747 }
catch ( DOM::DOMException &e ) {
2748 kdWarning(5006) <<
"Got an exception when trying to determine link under cursor!" << endl;
2756 if ( e->type() == TQEvent::MouseButtonPress ) {
2757 TQMouseEvent* me = TQT_TQMOUSEEVENT(e);
2758 if ( me->button() == Qt::LeftButton && ( me->state() & ShiftButton ) ) {
2760 URLHandlerManager::instance()->handleShiftClick( mHoveredUrl,
this );
2764 if ( me->button() == Qt::LeftButton ) {
2767 const DOM::Node nodeUnderMouse = mViewer->nodeUnderMouse();
2768 if ( !nodeUnderMouse.isNull() ) {
2769 const DOM::NamedNodeMap attributes = nodeUnderMouse.attributes();
2770 if ( !attributes.isNull() ) {
2771 const DOM::Node src = attributes.getNamedItem( DOM::DOMString(
"src" ) );
2772 if ( !src.isNull() ) {
2773 imagePath = src.nodeValue().string();
2778 mCanStartDrag = URLHandlerManager::instance()->willHandleDrag( mHoveredUrl, imagePath,
this );
2779 mLastClickPosition = me->pos();
2780 mLastClickImagePath = imagePath;
2784 if ( e->type() == TQEvent::MouseButtonRelease ) {
2785 mCanStartDrag =
false;
2788 if ( e->type() == TQEvent::MouseMove ) {
2789 TQMouseEvent* me = TQT_TQMOUSEEVENT( e );
2793 slotUrlOn( linkForNode( mViewer->nodeUnderMouse() ) );
2795 if ( ( mLastClickPosition - me->pos() ).manhattanLength() > TDEGlobalSettings::dndEventDelay() ) {
2796 if ( mCanStartDrag && ( !( mHoveredUrl.isEmpty() && mLastClickImagePath.isEmpty() ) ) ) {
2797 if ( URLHandlerManager::instance()->handleDrag( mHoveredUrl, mLastClickImagePath,
this ) ) {
2798 mCanStartDrag =
false;
2804 TQMouseEvent mouseEvent( TQEvent::MouseButtonRelease, me->pos(), Qt::NoButton, Qt::NoButton );
2805 TQT_TQOBJECT( mViewer->view() )->eventFilter( mViewer->view()->viewport(),
2819 Q_ASSERT( msg && nodeId );
2821 if ( mSerNumOfOriginalMessage != 0 ) {
2825 if ( folder && index != -1 )
2826 *msg = folder->
getMsg( index );
2829 kdWarning( 5006 ) <<
"Unable to find the original message, aborting attachment deletion!" << endl;
2833 *nodeId = node->nodeId() + mNodeIdOffset;
2836 *nodeId = node->nodeId();
2841 void KMReaderWin::slotDeleteAttachment(partNode * node)
2843 if ( KMessageBox::warningContinueCancel(
this,
2844 i18n(
"Deleting an attachment might invalidate any digital signature on this message."),
2845 i18n(
"Delete Attachment"), KStdGuiItem::del(),
"DeleteAttachmentSignatureWarning" )
2846 != KMessageBox::Continue ) {
2853 if ( msg && nodeId != -1 ) {
2854 KMDeleteAttachmentCommand* command =
new KMDeleteAttachmentCommand( nodeId, msg,
this );
2856 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
2858 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
2867 connect( headers, TQT_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2868 TQT_TQOBJECT(
this), TQT_SLOT( msgAdded( TQListViewItem* ) ) );
2872 if ( mSerNumOfOriginalMessage != 0 &&
message() ) {
2878 void KMReaderWin::msgAdded( TQListViewItem *item )
2885 headers->setCurrentItem( item );
2886 headers->clearSelection();
2893 disconnect( headers, TQT_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2894 TQT_TQOBJECT(
this), TQT_SLOT( msgAdded( TQListViewItem* ) ) );
2897 void KMReaderWin::slotEditAttachment(partNode * node)
2899 if ( KMessageBox::warningContinueCancel(
this,
2900 i18n(
"Modifying an attachment might invalidate any digital signature on this message."),
2901 i18n(
"Edit Attachment"), KGuiItem( i18n(
"Edit"),
"edit" ),
"EditAttachmentSignatureWarning" )
2902 != KMessageBox::Continue ) {
2909 if ( msg && nodeId != -1 ) {
2910 KMEditAttachmentCommand* command =
new KMEditAttachmentCommand( nodeId, msg,
this );
2917 KMail::CSSHelper* KMReaderWin::cssHelper()
2924 if ( !GlobalSettings::self()->alwaysDecrypt() )
2925 return mDecrytMessageOverwrite;
2931 DOM::Document doc = mViewer->htmlDocument();
2934 mViewer->gotoAnchor( TQString::fromLatin1(
"att%1" ).arg( node->nodeId() ) );
2937 const partNode *root = node->topLevelParent();
2938 for (
int i = 0; i <= root->totalChildCount() + 1; i++ ) {
2939 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( i + 1 ) );
2940 if ( !attachmentDiv.isNull() )
2941 attachmentDiv.removeAttribute(
"style" );
2945 if ( node->isDisplayedHidden() )
2951 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( node->nodeId() ) );
2952 if ( attachmentDiv.isNull() ) {
2953 kdWarning( 5006 ) <<
"Could not find attachment div for attachment " << node->nodeId() << endl;
2957 attachmentDiv.setAttribute(
"style", TQString(
"border:2px solid %1" )
2958 .arg( cssHelper()->pgpWarnColor().name() ) );
2962 doc.updateRendering();
2965 void KMReaderWin::injectAttachments()
2969 DOM::Document doc = mViewer->htmlDocument();
2970 DOM::Element injectionPoint = doc.getElementById(
"attachmentInjectionPoint" );
2971 if ( injectionPoint.isNull() )
2974 TQString imgpath( locate(
"data",
"kmail/pics/") );
2975 TQString visibility;
2978 if( !showAttachmentQuicklist() ) {
2979 urlHandle.append(
"kmail:showAttachmentQuicklist" );
2980 imgSrc.append(
"attachmentQuicklistClosed.png" );
2982 urlHandle.append(
"kmail:hideAttachmentQuicklist" );
2983 imgSrc.append(
"attachmentQuicklistOpened.png" );
2986 TQString html = renderAttachments( mRootNode, TQApplication::palette().active().background() );
2987 if ( html.isEmpty() )
2991 if ( headerStyle() == HeaderStyle::fancy() ) {
2992 link +=
"<div style=\"text-align: left;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2993 imgpath + imgSrc +
"\"/></a></div>";
2994 html.prepend( link );
2995 html.prepend( TQString::fromLatin1(
"<div style=\"float:left;\">%1 </div>" ).
2996 arg( i18n(
"Attachments:" ) ) );
2998 link +=
"<div style=\"text-align: right;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2999 imgpath + imgSrc +
"\"/></a></div>";
3000 html.prepend( link );
3003 assert( injectionPoint.tagName() ==
"div" );
3004 static_cast<DOM::HTMLElement
>( injectionPoint ).setInnerHTML( html );
3007 static TQColor nextColor(
const TQColor & c )
3010 c.hsv( &h, &s, &v );
3011 return TQColor( (h + 50) % 360, TQMAX(s, 64), v, TQColor::Hsv );
3014 TQString KMReaderWin::renderAttachments(partNode * node,
const TQColor &bgColor )
3020 if ( node->firstChild() ) {
3021 TQString subHtml = renderAttachments( node->firstChild(), nextColor( bgColor ) );
3022 if ( !subHtml.isEmpty() ) {
3024 TQString visibility;
3025 if ( !showAttachmentQuicklist() ) {
3026 visibility.append(
"display:none;" );
3030 if ( node != mRootNode || headerStyle() != HeaderStyle::enterprise() )
3031 margin =
"padding:2px; margin:2px; ";
3032 TQString align =
"left";
3033 if ( headerStyle() == HeaderStyle::enterprise() )
3035 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3036 html += TQString::fromLatin1(
"<div style=\"background:%1; %2"
3037 "vertical-align:middle; float:%3; %4\">").arg( bgColor.name() ).arg( margin )
3038 .arg( align ).arg( visibility );
3040 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3044 partNode::AttachmentDisplayInfo info = node->attachmentDisplayInfo();
3045 if ( info.displayInHeader ) {
3046 html +=
"<div style=\"float:left;\">";
3047 html += TQString::fromLatin1(
"<span style=\"white-space:nowrap; border-width: 0px; border-left-width: 5px; border-color: %1; 2px; border-left-style: solid;\">" ).arg( bgColor.name() );
3049 TQString href = node->asHREF(
"header" );
3050 html += TQString::fromLatin1(
"<a href=\"" ) + href +
3051 TQString::fromLatin1(
"\">" );
3052 html +=
"<img style=\"vertical-align:middle;\" src=\"" + info.icon +
"\"/> ";
3053 if ( headerStyle() == HeaderStyle::enterprise() ) {
3054 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3055 TQFontMetrics fm( bodyFont );
3056 html += KStringHandler::rPixelSqueeze( info.label, fm, 140 );
3057 }
else if ( headerStyle() == HeaderStyle::fancy() ) {
3058 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3059 TQFontMetrics fm( bodyFont );
3060 html += KStringHandler::rPixelSqueeze( info.label, fm, 640 );
3064 html +=
"</a></span></div> ";
3068 html += renderAttachments( node->nextSibling(), nextColor ( bgColor ) );
3074 void KMReaderWin::setBodyPartMemento(
const partNode * node,
const TQCString & which,
BodyPartMemento * memento )
3076 const TQCString index = node->path() +
':' + which.lower();
3078 const std::map<TQCString,BodyPartMemento*>::iterator it = mBodyPartMementoMap.lower_bound( index );
3079 if ( it != mBodyPartMementoMap.end() && it->first == index ) {
3081 if ( memento && memento == it->second )
3087 it->second = memento;
3090 mBodyPartMementoMap.erase( it );
3095 mBodyPartMementoMap.insert( it, std::make_pair( index, memento ) );
3103 BodyPartMemento * KMReaderWin::bodyPartMemento(
const partNode * node,
const TQCString & which )
const
3105 const TQCString index = node->path() +
':' + which.lower();
3106 const std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.find( index );
3107 if ( it == mBodyPartMementoMap.end() ) {
3121 void KMReaderWin::clearBodyPartMementos()
3123 for ( std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.begin(), end = mBodyPartMementoMap.end() ; it != end ; ++it )
3128 detach_and_delete( it->second,
this );
3130 mBodyPartMementoMap.clear();
3133 #include "kmreaderwin.moc"
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
bool isTrash()
Returns true if this folder is configured as a trash folder, locally or for one of the accounts.
bool isDrafts()
Returns true if this folder is the drafts box of the local account, or is configured to be the drafts...
bool isTemplates()
Returns true if this folder is the templates folder of the local account, or is configured to be the ...
bool isSent()
Returns true if this folder is the sent-mail box of the local account, or is configured to be the sen...
bool isOutbox()
Returns true only if this is the outbox for outgoing mail.
KMMessage * getMsg(int idx)
Read message at given index.
static KMKernel * self()
normal control stuff
KMMainWidget * getKMMainWidget()
Get first mainwidget.
void setBody(const TQCString &aStr)
Set the message body.
void setReadyToShow(bool v)
Set if the message is ready to be shown.
TQString msgId() const
Get or set the 'Message-Id' header field.
bool readyToShow() const
Return if the message is ready to be shown.
static void readConfig()
Reads config settings from group "KMMessage" and sets all internal variables (e.g.
void setOverrideCodec(const TQTextCodec *codec)
Set the charset the user selected for the message to display.
void setNeedsAssembly()
tell the message that internal data were changed (must be called after directly modifying message str...
void setUnencryptedMsg(KMMessage *unencrypted)
Specifies an unencrypted copy of this message to be stored in a separate member variable to allow sav...
void setDecodeHTML(bool aDecodeHTML)
Allow decoding of HTML for quoting.
bool deleteBodyPart(int partIndex)
Delete a body part with the specified part index.
TQString subject() const
Get or set the 'Subject' header field.
void setSignatureState(const KMMsgSignatureState, int idx=-1)
Set signature status of the message.
void setMsgSerNum(unsigned long newMsgSerNum=0)
Sets the message serial number.
size_t msgSize() const
Get/set size of message in the folder including the whole header in bytes.
TQCString contentTransferEncodingStr() const
Get or set the 'Content-Transfer-Encoding' header field The member functions that involve enumerated ...
void setEncryptionState(const KMMsgEncryptionState, int idx=-1)
Set encryption status of the message.
DwHeaders & headers() const
get the DwHeaders (make sure to call setNeedsAssembly() function after directly modyfying internal da...
bool isComplete() const
Return true if the complete message is available without referring to the backing store.
KMMsgSignatureState signatureState() const
Signature status of the message.
DwBodyPart * lastUpdatedPart()
Returns the last DwBodyPart that was updated.
void getLocation(unsigned long key, KMFolder **retFolder, int *retIndex) const
Returns the folder the message represented by the serial number key is in and the index in that folde...
static const KMMsgDict * instance()
Access the globally unique MessageDict.
This class implements a "reader window", that is a window used for reading or viewing messages.
const KMail::HeaderStrategy * headerStrategy() const
Getthe message header strategy.
void urlClicked(const KURL &url, int button)
The user has clicked onto an URL that is no attachment.
bool eventFilter(TQObject *obj, TQEvent *ev)
Event filter.
void setOriginalMsg(unsigned long serNumOfOriginalMessage, int nodeIdOffset)
This should be called when setting a message that was constructed from another message,...
void displayAboutPage()
Display the about page instead of a message.
void slotFindNext()
The user selected "Find Next" from the menu.
TQString writeMsgHeader(KMMessage *aMsg, partNode *vCardNode=0, bool topLevel=false)
Creates a nice mail header depending on the current selected header style.
KMail::HtmlWriter * htmlWriter()
Return the HtmlWriter connected to the TDEHTMLPart we use.
void replaceMsgByUnencryptedVersion()
Emitted after parsing of a message to have it stored in unencrypted state in it's folder.
TQString overrideEncoding() const
Get selected override character encoding.
void slotUrlCopy()
Copy URL in mUrlCurrent to clipboard.
void setMsgPart(KMMessagePart *aMsgPart, bool aHTML, const TQString &aFileName, const TQString &pname)
Instead of settings a message to be shown sets a message part to be shown.
void slotUrlOpen(const KURL &url, const KParts::URLArgs &args)
An URL has been activate with a click.
void setHeaderStyleAndStrategy(const KMail::HeaderStyle *style, const KMail::HeaderStrategy *strategy)
Set the header style and strategy.
virtual void closeEvent(TQCloseEvent *)
Some necessary event handling.
TQString createTempDir(const TQString ¶m=TQString())
Creates a temporary dir for saving attachments, etc.
bool decryptMessage() const
Returns wether the message should be decryted.
void fillCommandInfo(partNode *node, KMMessage **msg, int *nodeId)
Find the node ID and the message of the attachment that should be edited or deleted.
virtual void printMsg(void)
Print current message.
void slotCopySelectedText()
Copy the selected text to the clipboard.
virtual void parseMsg(KMMessage *msg)
Parse given message and add it's contents to the reader window.
const TQTextCodec * overrideCodec() const
Get codec corresponding to the currently selected override character encoding.
bool htmlMail()
Is html mail to be supported? Takes into account override.
void slotMailtoReply()
Operations on mailto: URLs.
static TQString newFeaturesMD5()
Returns the MD5 hash for the list of new features.
void setIdOfLastViewedMessage(const TQString &msgId)
Store message id of last viewed message, normally no need to call this function directly,...
int pointsToPixel(int pointSize) const
Calculate the pixel size.
void styleChange(TQStyle &oldStyle)
reimplemented in order to update the frame width in case of a changed GUI style
void displaySplashPage(const TQString &info)
Display a generic HTML splash page instead of a message.
KMMessage * message(KMFolder **folder=0) const
Returns the current message or 0 if none.
void displayBusyPage()
Display the 'please wait' page instead of a message.
virtual bool event(TQEvent *e)
Watch for palette changes.
void scrollToAttachment(const partNode *node)
Scrolls to the given attachment and marks it with a yellow border.
partNode * partNodeFromUrl(const KURL &url)
Returns message part from given URL or null if invalid.
void disconnectMsgAdded()
Helper functions used to change message selection in the message list after deleting an attachment,...
void updateReaderWin()
Refresh the reader window.
void popupMenu(KMMessage &msg, const KURL &url, const TQPoint &mousePos)
The user presses the right mouse button.
TQString writeMessagePartToTempFile(KMMessagePart *msgPart, int partNumber)
Writes the given message part to a temporary file and returns the name of this file or TQString() if ...
bool htmlLoadExternal()
Is loading ext.
void clear(bool force=false)
Clear the reader and discard the current message.
void displayOfflinePage()
Display the 'we are currently in offline mode' page instead of a message.
void displayMessage()
Feeds the HTML viewer with the contents of the given message.
void slotUrlSave()
Save the page to a file.
static int msgPartFromUrl(const KURL &url)
Returns id of message part from given URL or -1 if invalid.
void slotFind()
The user selected "Find" from the menu.
void enableMsgDisplay()
Enable the displaying of messages again after an URL was displayed.
virtual void setMsg(KMMessage *msg, bool force=false, bool updateOnly=false)
Set the message that shall be shown.
void readConfig()
Read settings from app's config file.
TQString copyText()
Return selected text.
void slotUrlPopup(const TQString &, const TQPoint &mousePos)
The user presses the right mouse button on an URL.
void slotToggleFixedFont()
The user toggled the "Fixed Font" flag from the view menu.
void slotScrollUp()
HTML Widget scrollbar and layout handling.
void setOverrideEncoding(const TQString &encoding)
Set the override character encoding.
void slotIMChat()
start IM Chat with addressee
virtual void removeTempFiles()
Cleanup the attachment temp files.
void setHtmlLoadExtDefault(bool loadExtDefault)
Default behavior for loading external references.
void selectAll()
Select message body.
void showHideMimeTree(bool isPlainTextTopLevel)
Show or hide the Mime Tree Viewer if configuration is set to smart mode.
const KMail::AttachmentStrategy * attachmentStrategy() const
Get/set the message attachment strategy.
void atmViewMsg(KMMessagePart *msgPart, int nodeId)
View message part of type message/RFC822 in extra viewer window.
void setHtmlLoadExtOverride(bool loadExtOverride)
Override default load external references setting.
void showVCard(KMMessagePart *msgPart)
show window containing infos about a vCard.
void writeConfig(bool withSync=true) const
Write settings to app's config file.
void slotToggleMimePartTree()
Show or hide the Mime Tree Viewer.
void clearCache()
Force update even if message is the same.
void slotAtmView(int id, const TQString &name)
Some attachment operations.
virtual void initHtmlWidget(void)
HTML initialization.
void saveRelativePosition()
Saves the relative position of the scroll view.
void setStyleDependantFrameWidth()
Set the width of the frame to a reasonable value for the current GUI style.
void slotUrlOn(const TQString &url)
The mouse has moved on or off an URL.
void update(KMail::Interface::Observable *)
The HTML statusbar widget for use with the reader.
void setNeutralMode()
Switch to "neutral" mode (currently == normal mode).
void setHtmlMode()
Switch to "html mode".
void setNormalMode()
Switch to "normal mode".
An interface to HTML sinks.
virtual void reset()=0
Stop all possibly pending processing in order to be able to call #begin() again.
virtual void flush()=0
(Start) flushing internal buffers, if any.
interface of classes that implement status for BodyPartFormatters.
virtual Observable * asObservable()=0
If your BodyPartMemento implementation also implements the KMail::Observable interface,...
A HtmlWriter that dispatches all calls to a list of other HtmlWriters.
Singleton to manage the list of URLHandlers.
An interface for HTML sinks.
size_t crlf2lf(char *str, const size_t strLen)
Convert all sequences of "\r\n" (carriage return followed by a line feed) to a single "\n" (line feed...