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( TQt::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, TQ_SIGNAL(timeout()),
473 this, TQ_SLOT(updateReaderWin()) );
474 connect( &mResizeTimer, TQ_SIGNAL(timeout()),
475 this, TQ_SLOT(slotDelayedResize()) );
476 connect( &mDelayedMarkTimer, TQ_SIGNAL(timeout()),
477 this, TQ_SLOT(slotTouchMessage()) );
478 connect( &mHeaderRefreshTimer, TQ_SIGNAL(timeout()),
479 this, TQ_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, TQ_SIGNAL(activated()),
495 this, TQ_SLOT(slotCycleHeaderStyles()) );
497 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Enterprise Headers"), 0,
498 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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, TQ_SIGNAL(activated()),
544 this, TQ_SLOT(slotCycleAttachmentStrategy()) );
546 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&As Icons"), 0,
547 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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 this, TQ_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,
this, TQ_SLOT(slotMailtoCompose()), ac,
593 mMailToReplyAction =
new TDEAction( i18n(
"Reply To..."),
"mail-reply-sender",
596 mMailToForwardAction =
new TDEAction( i18n(
"Forward To..."),
"mail-forward",
597 0,
this, TQ_SLOT(slotMailtoForward()), ac,
599 mAddAddrBookAction =
new TDEAction( i18n(
"Add to Address Book"),
600 0,
this, TQ_SLOT(slotMailtoAddAddrBook()),
601 ac,
"add_addr_book" );
602 mOpenAddrBookAction =
new TDEAction( i18n(
"Open in Address Book"),
603 0,
this, TQ_SLOT(slotMailtoOpenAddrBook()),
604 ac,
"openin_addr_book" );
606 mSelectAllAction =
new TDEAction( i18n(
"Select All Text"), CTRL+SHIFT+Key_A,
this,
607 TQ_SLOT(
selectAll()), ac,
"mark_all_text" );
608 mCopyURLAction =
new TDEAction( i18n(
"Copy Link Address"), 0,
this,
610 mUrlOpenAction =
new TDEAction( i18n(
"Open URL"), 0,
this,
612 mAddBookmarksAction =
new TDEAction( i18n(
"Bookmark This Link"),
614 0,
this, TQ_SLOT(slotAddBookmarks()),
615 ac,
"add_bookmarks" );
616 mUrlSaveAsAction =
new TDEAction( i18n(
"Save Link As..."), 0,
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, TQ_SIGNAL(toggled(
bool)),
628 mStartIMChatAction =
new TDEAction( i18n(
"Chat &With..."), 0,
this,
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 TQ_SIGNAL(openURLRequest(
const KURL &,
const KParts::URLArgs &)),
this,
1026 connect(mViewer->browserExtension(),
1027 TQ_SIGNAL(createNewWindow(
const KURL &,
const KParts::URLArgs &)),
this,
1029 connect(mViewer,TQ_SIGNAL(
popupMenu(
const TQString &,
const TQPoint &)),
1030 TQ_SLOT(
slotUrlPopup(
const TQString &,
const TQPoint &)));
1031 connect( kmkernel->imProxy(), TQ_SIGNAL( sigContactPresenceChanged(
const TQString & ) ),
1032 this, TQ_SLOT( contactStatusChanged(
const TQString & ) ) );
1033 connect( kmkernel->imProxy(), TQ_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,
this, TQ_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";
1781 if ( aMsgPart->subtype() == DwMime::kSubtypeHtml )
1782 fileName +=
".html";
1784 fname +=
"/" + fileName;
1786 TQByteArray data = aMsgPart->bodyDecodedBinary();
1787 size_t size = data.size();
1788 if ( aMsgPart->type() == DwMime::kTypeText && size) {
1792 if( !KPIM::kBytesToFile( data.data(), size, fname,
false,
false,
false ) )
1795 mTempFiles.append( fname );
1798 ::chmod( TQFile::encodeName( fname ), S_IRUSR );
1805 KTempFile *tempFile =
new KTempFile( TQString(),
"." + param );
1806 tempFile->setAutoDelete(
true );
1807 TQString fname = tempFile->name();
1810 if( ::access( TQFile::encodeName( fname ), W_OK ) != 0 )
1812 if( ::mkdir( TQFile::encodeName( fname ), 0 ) != 0
1813 || ::chmod( TQFile::encodeName( fname ), S_IRWXU ) != 0 )
1816 assert( !fname.isNull() );
1818 mTempDirs.append( fname );
1825 #if defined(KABC_VCARD_ENCODING_FIX)
1826 const TQByteArray vCard = msgPart->bodyDecodedBinary();
1828 const TQString vCard = msgPart->bodyToUnicode(
overrideCodec() );
1830 VCardViewer *vcv =
new VCardViewer(
this, vCard,
"vCardDialog" );
1838 mViewer->view()->print();
1845 if (aUrl.isEmpty())
return -1;
1846 if (!aUrl.isLocalFile())
return -1;
1848 TQString path = aUrl.path();
1849 uint right = path.findRev(
'/');
1850 uint left = path.findRev(
'.', right);
1853 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
1854 return (ok) ? res : -1;
1859 void KMReaderWin::resizeEvent(TQResizeEvent *)
1861 if( !mResizeTimer.isActive() )
1867 mResizeTimer.start( 100,
true );
1873 void KMReaderWin::slotDelayedResize()
1875 mSplitter->setGeometry(0, 0, width(), height());
1880 void KMReaderWin::slotTouchMessage()
1889 serNums.append(
message()->getMsgSerNum() );
1890 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
1894 if ( mNoMDNsWhenEncrypted &&
1895 message()->encryptionState() != KMMsgNotEncrypted &&
1896 message()->encryptionState() != KMMsgEncryptionStateUnknown )
1908 if ( !kmkernel->msgSender()->send( receipt ) )
1909 KMessageBox::error(
this, i18n(
"Could not send MDN.") );
1916 TQWidget::closeEvent(e);
1921 bool foundSMIMEData(
const TQString aUrl,
1922 TQString& displayName,
1926 static TQString showCertMan(
"showCertificate#");
1930 int i1 = aUrl.find( showCertMan );
1932 i1 += showCertMan.length();
1933 int i2 = aUrl.find(
" ### ", i1);
1936 displayName = aUrl.mid( i1, i2-i1 );
1938 i2 = aUrl.find(
" ### ", i1);
1941 libName = aUrl.mid( i1, i2-i1 );
1944 keyId = aUrl.mid( i2 );
1960 return !keyId.isEmpty();
1967 const KURL url(aUrl);
1969 if ( url.protocol() ==
"kmail" || url.protocol() ==
"x-kmail" || url.protocol() ==
"attachment"
1970 || (url.protocol().isEmpty() && url.path().isEmpty()) ) {
1971 mViewer->setDNDEnabled(
false );
1973 mViewer->setDNDEnabled(
true );
1976 if ( aUrl.stripWhiteSpace().isEmpty() ) {
1977 KPIM::BroadcastStatus::instance()->reset();
1978 mHoveredUrl = KURL();
1979 mLastClickImagePath = TQString();
1985 const TQString msg = URLHandlerManager::instance()->statusBarMessage( url,
this );
1987 kdWarning( msg.isEmpty(), 5006 ) <<
"KMReaderWin::slotUrlOn(): Unhandled URL hover!" << endl;
1988 KPIM::BroadcastStatus::instance()->setTransienStatusMsg( msg );
1997 if ( URLHandlerManager::instance()->handleClick( aUrl,
this ) )
2000 kdWarning( 5006 ) <<
"KMReaderWin::slotOpenUrl(): Unhandled URL click!" << endl;
2007 const KURL url( aUrl );
2010 if ( url.protocol() ==
"mailto" ) {
2011 mCopyURLAction->setText( i18n(
"Copy Email Address" ) );
2013 mCopyURLAction->setText( i18n(
"Copy Link Address" ) );
2016 if ( URLHandlerManager::instance()->handleContextMenuRequest( url, aPos,
this ) )
2020 kdWarning( 5006 ) <<
"KMReaderWin::slotUrlPopup(): Unhandled URL right-click!" << endl;
2021 emitPopupMenu( url, aPos );
2027 static bool hasParentDivWithId(
const DOM::Node &start,
const TQString &
id )
2029 if ( start.isNull() )
2032 if ( start.nodeName().string() ==
"div" ) {
2033 for (
unsigned int i = 0; i < start.attributes().length(); i++ ) {
2034 if ( start.attributes().item( i ).nodeName().string() ==
"id" &&
2035 start.attributes().item( i ).nodeValue().string() ==
id )
2040 if ( !start.parentNode().isNull() )
2041 return hasParentDivWithId( start.parentNode(),
id );
2046 void KMReaderWin::showAttachmentPopup(
int id,
const TQString & name,
const TQPoint & p )
2049 mAtmCurrentName = name;
2050 TDEPopupMenu *menu =
new TDEPopupMenu();
2051 menu->insertItem(SmallIcon(
"document-open"),i18n(
"to open",
"Open"), 1);
2052 menu->insertItem(i18n(
"Open With..."), 2);
2053 menu->insertItem(i18n(
"to view something",
"View"), 3);
2054 menu->insertItem(SmallIcon(
"document-save-as"),i18n(
"Save As..."), 4);
2055 menu->insertItem(SmallIcon(
"edit-copy"), i18n(
"Copy"), 9 );
2056 const bool canChange =
message()->parent() ? !
message()->parent()->isReadOnly() :
false;
2057 if ( GlobalSettings::self()->allowAttachmentEditing() && canChange )
2058 menu->insertItem(SmallIcon(
"edit"), i18n(
"Edit Attachment"), 8 );
2059 if ( GlobalSettings::self()->allowAttachmentDeletion() && canChange )
2060 menu->insertItem(SmallIcon(
"edit-delete"), i18n(
"Delete Attachment"), 7 );
2061 if ( name.endsWith(
".xia",
false ) &&
2062 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) )
2063 menu->insertItem( i18n(
"Decrypt With Chiasmus..." ), 6 );
2064 menu->insertItem(i18n(
"Properties"), 5);
2066 const bool attachmentInHeader = hasParentDivWithId( mViewer->nodeUnderMouse(),
"attachmentInjectionPoint" );
2067 const bool hasScrollbar = mViewer->view()->verticalScrollBar()->isVisible();
2068 if ( attachmentInHeader && hasScrollbar ) {
2069 menu->insertItem( i18n(
"Scroll To"), 10 );
2072 connect(menu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotHandleAttachment(
int)));
2084 if( style().isA(
"KeramikStyle") )
2085 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
2087 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
2088 if ( frameWidth < 0 )
2090 if ( frameWidth != mBox->lineWidth() )
2091 mBox->setLineWidth( frameWidth );
2098 TQWidget::styleChange( oldStyle );
2102 void KMReaderWin::slotHandleAttachment(
int choice )
2105 partNode* node = mRootNode ? mRootNode->findId( mAtmCurrent ) : 0;
2106 if ( mAtmCurrentName.isEmpty() && node )
2107 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2109 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand(
2110 node,
message(), mAtmCurrent, mAtmCurrentName,
2111 KMHandleAttachmentCommand::AttachmentAction( choice ), 0,
this );
2112 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2113 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2115 }
else if ( choice == 7 ) {
2116 slotDeleteAttachment( node );
2117 }
else if ( choice == 8 ) {
2118 slotEditAttachment( node );
2119 }
else if ( choice == 9 ) {
2120 if ( !node )
return;
2122 KURL url = tempFileUrlFromPartNode( node );
2123 if (!url.isValid() )
return;
2125 KURLDrag* drag =
new KURLDrag( urls,
this );
2126 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
2127 }
else if ( choice == 10 ) {
2135 mViewer->findText();
2141 mViewer->findTextNext();
2147 mUseFixedFont = !mUseFixedFont;
2156 if ( mToggleMimePartTreeAction->isChecked() ) {
2157 mMimeTreeModeOverride = 2;
2159 mMimeTreeModeOverride = 0;
2167 kapp->clipboard()->setText( mViewer->selectedText() );
2174 assert(aMsgPart!=0);
2176 msg->fromString(aMsgPart->bodyDecoded());
2180 msg->setParent(
message()->parent() );
2181 msg->setUID(
message()->UID());
2183 KMReaderMainWin *win =
new KMReaderMainWin();
2192 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2193 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2196 ObjectTreeParser otp(
this, 0,
true );
2197 otp.parseObjectTree( node );
2206 const TQString& aFileName,
const TQString& pname )
2209 if (kasciistricmp(aMsgPart->typeStr(),
"message")==0) {
2212 assert(aMsgPart!=0);
2213 msg->fromString(aMsgPart->bodyDecoded());
2214 mMainWindow->setCaption(msg->
subject());
2216 setAutoDelete(
true);
2217 }
else if (kasciistricmp(aMsgPart->typeStr(),
"text")==0) {
2218 if (kasciistricmp(aMsgPart->subtypeStr(),
"x-vcard") == 0) {
2222 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2223 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2225 if (aHTML && (kasciistricmp(aMsgPart->subtypeStr(),
"html")==0)) {
2230 const TQCString str = aMsgPart->bodyDecoded();
2231 ObjectTreeParser otp(
this );
2232 otp.writeBodyStr( str,
2238 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2239 }
else if (kasciistricmp(aMsgPart->typeStr(),
"image")==0 ||
2240 (kasciistricmp(aMsgPart->typeStr(),
"application")==0 &&
2241 kasciistricmp(aMsgPart->subtypeStr(),
"postscript")==0))
2243 if (aFileName.isEmpty())
return;
2245 TQImageIO *iio =
new TQImageIO();
2246 iio->setFileName(aFileName);
2248 TQImage img = iio->image();
2249 TQRect desk = TDEGlobalSettings::desktopGeometry(mMainWindow);
2252 if( img.width() < 50 )
2254 else if( img.width()+20 < desk.width() )
2255 width = img.width()+20;
2257 width = desk.width();
2258 if( img.height() < 50 )
2260 else if( img.height()+20 < desk.height() )
2261 height = img.height()+20;
2263 height = desk.height();
2264 mMainWindow->resize( width, height );
2267 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2268 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2270 KURL::encode_string( aFileName ) +
2271 "\" border=\"0\">\n"
2272 "</body></html>\n" );
2274 setCaption( i18n(
"View Attachment: %1").arg( pname ) );
2278 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2279 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2282 TQString str = aMsgPart->bodyDecoded();
2285 if( str.length() < (
unsigned) aMsgPart->decodedSize() ) {
2286 str.prepend( i18n(
"[KMail: Attachment contains binary data. Trying to show first character.]",
2287 "[KMail: Attachment contains binary data. Trying to show first %n characters.]",
2288 str.length()) + TQChar(
'\n') );
2290 htmlWriter()->queue( TQStyleSheet::escape( str ) );
2294 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2303 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2306 mAtmCurrentName = name;
2307 if ( mAtmCurrentName.isEmpty() )
2308 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2310 KMMessagePart& msgPart = node->msgPart();
2311 TQString pname = msgPart.fileName();
2312 if (pname.isEmpty()) pname=msgPart.name();
2313 if (pname.isEmpty()) pname=msgPart.contentDescription();
2314 if (pname.isEmpty()) pname=
"unnamed";
2316 if (kasciistricmp(msgPart.typeStr(),
"message")==0) {
2318 }
else if ((kasciistricmp(msgPart.typeStr(),
"text")==0) &&
2319 (kasciistricmp(msgPart.subtypeStr(),
"x-vcard")==0)) {
2322 KMReaderMainWin *win =
new KMReaderMainWin(&msgPart,
htmlMail(),
2330 void KMReaderWin::openAttachment(
int id,
const TQString & name )
2332 mAtmCurrentName = name;
2335 TQString str, pname, cmd, fileName;
2337 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2339 kdWarning(5006) <<
"KMReaderWin::openAttachment - could not find node " <<
id << endl;
2342 if ( mAtmCurrentName.isEmpty() )
2343 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2345 KMMessagePart& msgPart = node->msgPart();
2346 if (kasciistricmp(msgPart.typeStr(),
"message")==0)
2352 TQCString contentTypeStr( msgPart.typeStr() +
'/' + msgPart.subtypeStr() );
2353 KPIM::kAsciiToLower( contentTypeStr.data() );
2355 if ( qstrcmp( contentTypeStr,
"text/x-vcard" ) == 0 ) {
2361 KMimeType::Ptr mimetype;
2363 mimetype = KMimeType::mimeType( TQString::fromLatin1( contentTypeStr ) );
2364 if ( mimetype->name() ==
"application/octet-stream" ) {
2366 mimetype = KMimeType::findByPath( name, 0,
true );
2368 if ( ( mimetype->name() ==
"application/octet-stream" )
2369 && msgPart.isComplete() ) {
2372 mimetype = KMimeType::findByFileContent( name );
2375 KService::Ptr offer =
2376 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
2379 TQString filenameText = msgPart.fileName();
2380 if ( filenameText.isEmpty() )
2381 filenameText = msgPart.name();
2383 open_text = i18n(
"&Open with '%1'").arg( offer->name() );
2385 open_text = i18n(
"&Open With...");
2387 const TQString text = i18n(
"Open attachment '%1'?\n"
2388 "Note that opening an attachment may compromise "
2389 "your system's security.")
2390 .arg( filenameText );
2391 const int choice = KMessageBox::questionYesNoCancel(
this, text,
2392 i18n(
"Open Attachment?"), KStdGuiItem::saveAs(), open_text,
2393 TQString::fromLatin1(
"askSave") + mimetype->name() );
2395 if( choice == KMessageBox::Yes ) {
2397 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2398 message(), mAtmCurrent, mAtmCurrentName, KMHandleAttachmentCommand::Save,
2400 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2401 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2404 else if( choice == KMessageBox::No ) {
2405 KMHandleAttachmentCommand::AttachmentAction action = ( offer ?
2406 KMHandleAttachmentCommand::Open : KMHandleAttachmentCommand::OpenWith );
2408 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2409 message(), mAtmCurrent, mAtmCurrentName, action, offer,
this );
2410 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2411 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2414 kdDebug(5006) <<
"Canceled opening attachment" << endl;
2421 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -10);
2426 void KMReaderWin::slotScrollDown()
2428 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, 10);
2431 bool KMReaderWin::atBottom()
const
2433 const TQScrollView *view =
static_cast<const TQScrollView *
>(mViewer->widget());
2434 return view->contentsY() + view->visibleHeight() >= view->contentsHeight();
2438 void KMReaderWin::slotJumpDown()
2440 TQScrollView *view =
static_cast<TQScrollView *
>(mViewer->widget());
2441 int offs = (view->clipper()->height() < 30) ? view->clipper()->height() : 30;
2442 view->scrollBy( 0, view->clipper()->height() - offs );
2446 void KMReaderWin::slotScrollPrior()
2448 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -(
int)(height()*0.8));
2453 void KMReaderWin::slotScrollNext()
2455 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, (
int)(height()*0.8));
2459 void KMReaderWin::slotDocumentChanged()
2466 void KMReaderWin::slotTextSelected(
bool)
2468 TQString temp = mViewer->selectedText();
2469 kapp->clipboard()->setText(temp);
2475 mViewer->selectAll();
2481 TQString temp = mViewer->selectedText();
2487 void KMReaderWin::slotDocumentDone()
2494 void KMReaderWin::setHtmlOverride(
bool override)
2496 mHtmlOverride =
override;
2505 mHtmlLoadExtDefault = loadExtDefault;
2510 mHtmlLoadExtOverride = loadExtOverride;
2517 return ((mHtmlMail && !mHtmlOverride) || (!mHtmlMail && mHtmlOverride));
2526 return mHtmlLoadExtOverride;
2530 if (mRootNode->overallEncryptionState() != KMMsgNotEncrypted)
2532 return mHtmlLoadExtOverride;
2535 return ((mHtmlLoadExtDefault && !mHtmlLoadExtOverride) ||
2536 (!mHtmlLoadExtDefault && mHtmlLoadExtOverride));
2543 const TQScrollView * scrollview =
static_cast<TQScrollView *
>( mViewer->widget() );
2544 mSavedRelativePosition =
2545 static_cast<float>( scrollview->contentsY() ) / scrollview->contentsHeight();
2554 setMsg( msg, force,
true );
2562 KMFolder*& folder = aFolder ? *aFolder : tmpFolder;
2573 kdWarning(5006) <<
"Attempt to reference invalid serial number " << mLastSerNum <<
"\n" << endl;
2582 void KMReaderWin::slotUrlClicked()
2584 KMMainWidget *mainWidget =
dynamic_cast<KMMainWidget*
>(mMainWindow);
2587 identity =
message()->parent()->identity();
2590 KMCommand *command =
new KMUrlClickedCommand( mClickedUrl, identity,
this,
2591 false, mainWidget );
2596 void KMReaderWin::slotMailtoCompose()
2598 KMCommand *command =
new KMMailtoComposeCommand( mClickedUrl,
message() );
2603 void KMReaderWin::slotMailtoForward()
2605 KMCommand *command =
new KMMailtoForwardCommand( mMainWindow, mClickedUrl,
2611 void KMReaderWin::slotMailtoAddAddrBook()
2613 KMCommand *command =
new KMMailtoAddAddrBookCommand( mClickedUrl,
2619 void KMReaderWin::slotMailtoOpenAddrBook()
2621 KMCommand *command =
new KMMailtoOpenAddrBookCommand( mClickedUrl,
2631 KMCommand *command =
2632 new KMUrlCopyCommand( mClickedUrl,
2633 dynamic_cast<KMMainWidget*
>( mMainWindow ) );
2640 if ( !url.isEmpty() )
2642 KMCommand *command =
new KMUrlOpenCommand( mClickedUrl,
this );
2647 void KMReaderWin::slotAddBookmarks()
2649 KMCommand *command =
new KMAddBookmarksCommand( mClickedUrl,
this );
2656 KMCommand *command =
new KMUrlSaveCommand( mClickedUrl, mMainWindow );
2663 KMCommand *command =
new KMMailtoReplyCommand( mMainWindow, mClickedUrl,
2670 return mRootNode ? mRootNode->findId(
msgPartFromUrl( url ) ) : 0 ;
2673 partNode * KMReaderWin::partNodeForId(
int id ) {
2674 return mRootNode ? mRootNode->findId(
id ) : 0 ;
2678 KURL KMReaderWin::tempFileUrlFromPartNode(
const partNode * node )
2680 if (!node)
return KURL();
2681 TQStringList::const_iterator it = mTempFiles.begin();
2682 TQStringList::const_iterator end = mTempFiles.end();
2684 while ( it != end ) {
2685 TQString path = *it;
2687 uint right = path.findRev(
'/');
2688 uint left = path.findRev(
'.', right);
2691 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
2692 if ( res == node->nodeId() )
2693 return KURL( path );
2699 void KMReaderWin::slotSaveAttachments()
2702 KMSaveAttachmentsCommand *saveCommand =
new KMSaveAttachmentsCommand( mMainWindow,
2704 saveCommand->start();
2708 void KMReaderWin::saveAttachment(
const KURL &tempFileName )
2711 mAtmCurrentName = mClickedUrl.path();
2712 slotHandleAttachment( KMHandleAttachmentCommand::Save );
2716 void KMReaderWin::slotSaveMsg()
2718 KMSaveMsgCommand *saveCommand =
new KMSaveMsgCommand( mMainWindow,
message() );
2720 if (saveCommand->url().isEmpty())
2723 saveCommand->start();
2728 KMCommand *command =
new KMIMChatCommand( mClickedUrl,
message() );
2733 static TQString linkForNode(
const DOM::Node &node )
2736 if ( node.isNull() )
2739 const DOM::NamedNodeMap attributes = node.attributes();
2740 if ( !attributes.isNull() ) {
2741 const DOM::Node href = attributes.getNamedItem( DOM::DOMString(
"href" ) );
2742 if ( !href.isNull() ) {
2743 return href.nodeValue().string();
2746 if ( !node.parentNode().isNull() ) {
2747 return linkForNode( node.parentNode() );
2751 }
catch ( DOM::DOMException &e ) {
2752 kdWarning(5006) <<
"Got an exception when trying to determine link under cursor!" << endl;
2760 if ( e->type() == TQEvent::MouseButtonPress ) {
2761 TQMouseEvent* me =
static_cast<TQMouseEvent*
>(e);
2762 if ( me->button() == TQt::LeftButton && ( me->state() & ShiftButton ) ) {
2764 URLHandlerManager::instance()->handleShiftClick( mHoveredUrl,
this );
2768 if ( me->button() == TQt::LeftButton ) {
2771 const DOM::Node nodeUnderMouse = mViewer->nodeUnderMouse();
2772 if ( !nodeUnderMouse.isNull() ) {
2773 const DOM::NamedNodeMap attributes = nodeUnderMouse.attributes();
2774 if ( !attributes.isNull() ) {
2775 const DOM::Node src = attributes.getNamedItem( DOM::DOMString(
"src" ) );
2776 if ( !src.isNull() ) {
2777 imagePath = src.nodeValue().string();
2782 mCanStartDrag = URLHandlerManager::instance()->willHandleDrag( mHoveredUrl, imagePath,
this );
2783 mLastClickPosition = me->pos();
2784 mLastClickImagePath = imagePath;
2788 if ( e->type() == TQEvent::MouseButtonRelease ) {
2789 mCanStartDrag =
false;
2792 if ( e->type() == TQEvent::MouseMove ) {
2793 TQMouseEvent* me =
static_cast<TQMouseEvent*
>( e );
2797 slotUrlOn( linkForNode( mViewer->nodeUnderMouse() ) );
2799 if ( ( mLastClickPosition - me->pos() ).manhattanLength() > TDEGlobalSettings::dndEventDelay() ) {
2800 if ( mCanStartDrag && ( !( mHoveredUrl.isEmpty() && mLastClickImagePath.isEmpty() ) ) ) {
2801 if ( URLHandlerManager::instance()->handleDrag( mHoveredUrl, mLastClickImagePath,
this ) ) {
2802 mCanStartDrag =
false;
2808 TQMouseEvent mouseEvent( TQEvent::MouseButtonRelease, me->pos(), TQt::NoButton, TQt::NoButton );
2809 static_cast<TQObject*
>(mViewer->view())->
eventFilter( mViewer->view()->viewport(),
2823 Q_ASSERT( msg && nodeId );
2825 if ( mSerNumOfOriginalMessage != 0 ) {
2829 if ( folder && index != -1 )
2830 *msg = folder->
getMsg( index );
2833 kdWarning( 5006 ) <<
"Unable to find the original message, aborting attachment deletion!" << endl;
2837 *nodeId = node->nodeId() + mNodeIdOffset;
2840 *nodeId = node->nodeId();
2845 void KMReaderWin::slotDeleteAttachment(partNode * node)
2847 if ( KMessageBox::warningContinueCancel(
this,
2848 i18n(
"Deleting an attachment might invalidate any digital signature on this message."),
2849 i18n(
"Delete Attachment"), KStdGuiItem::del(),
"DeleteAttachmentSignatureWarning" )
2850 != KMessageBox::Continue ) {
2857 if ( msg && nodeId != -1 ) {
2858 KMDeleteAttachmentCommand* command =
new KMDeleteAttachmentCommand( nodeId, msg,
this );
2860 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
2862 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
2871 connect( headers, TQ_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2872 this, TQ_SLOT( msgAdded( TQListViewItem* ) ) );
2876 if ( mSerNumOfOriginalMessage != 0 &&
message() ) {
2882 void KMReaderWin::msgAdded( TQListViewItem *item )
2889 headers->setCurrentItem( item );
2890 headers->clearSelection();
2897 disconnect( headers, TQ_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2898 this, TQ_SLOT( msgAdded( TQListViewItem* ) ) );
2901 void KMReaderWin::slotEditAttachment(partNode * node)
2903 if ( KMessageBox::warningContinueCancel(
this,
2904 i18n(
"Modifying an attachment might invalidate any digital signature on this message."),
2905 i18n(
"Edit Attachment"), KGuiItem( i18n(
"Edit"),
"edit" ),
"EditAttachmentSignatureWarning" )
2906 != KMessageBox::Continue ) {
2913 if ( msg && nodeId != -1 ) {
2914 KMEditAttachmentCommand* command =
new KMEditAttachmentCommand( nodeId, msg,
this );
2921 KMail::CSSHelper* KMReaderWin::cssHelper()
2928 if ( !GlobalSettings::self()->alwaysDecrypt() )
2929 return mDecrytMessageOverwrite;
2935 DOM::Document doc = mViewer->htmlDocument();
2938 mViewer->gotoAnchor( TQString::fromLatin1(
"att%1" ).arg( node->nodeId() ) );
2941 const partNode *root = node->topLevelParent();
2942 for (
int i = 0; i <= root->totalChildCount() + 1; i++ ) {
2943 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( i + 1 ) );
2944 if ( !attachmentDiv.isNull() )
2945 attachmentDiv.removeAttribute(
"style" );
2949 if ( node->isDisplayedHidden() )
2955 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( node->nodeId() ) );
2956 if ( attachmentDiv.isNull() ) {
2957 kdWarning( 5006 ) <<
"Could not find attachment div for attachment " << node->nodeId() << endl;
2961 attachmentDiv.setAttribute(
"style", TQString(
"border:2px solid %1" )
2962 .arg( cssHelper()->pgpWarnColor().name() ) );
2966 doc.updateRendering();
2969 void KMReaderWin::injectAttachments()
2973 DOM::Document doc = mViewer->htmlDocument();
2974 DOM::Element injectionPoint = doc.getElementById(
"attachmentInjectionPoint" );
2975 if ( injectionPoint.isNull() )
2978 TQString imgpath( locate(
"data",
"kmail/pics/") );
2979 TQString visibility;
2982 if( !showAttachmentQuicklist() ) {
2983 urlHandle.append(
"kmail:showAttachmentQuicklist" );
2984 imgSrc.append(
"attachmentQuicklistClosed.png" );
2986 urlHandle.append(
"kmail:hideAttachmentQuicklist" );
2987 imgSrc.append(
"attachmentQuicklistOpened.png" );
2990 TQString html = renderAttachments( mRootNode, TQApplication::palette().active().background() );
2991 if ( html.isEmpty() )
2995 if ( headerStyle() == HeaderStyle::fancy() ) {
2996 link +=
"<div style=\"text-align: left;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2997 imgpath + imgSrc +
"\"/></a></div>";
2998 html.prepend( link );
2999 html.prepend( TQString::fromLatin1(
"<div style=\"float:left;\">%1 </div>" ).
3000 arg( i18n(
"Attachments:" ) ) );
3002 link +=
"<div style=\"text-align: right;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
3003 imgpath + imgSrc +
"\"/></a></div>";
3004 html.prepend( link );
3007 assert( injectionPoint.tagName() ==
"div" );
3008 static_cast<DOM::HTMLElement
>( injectionPoint ).setInnerHTML( html );
3011 static TQColor nextColor(
const TQColor & c )
3014 c.hsv( &h, &s, &v );
3015 return TQColor( (h + 50) % 360, TQMAX(s, 64), v, TQColor::Hsv );
3018 TQString KMReaderWin::renderAttachments(partNode * node,
const TQColor &bgColor )
3024 if ( node->firstChild() ) {
3025 TQString subHtml = renderAttachments( node->firstChild(), nextColor( bgColor ) );
3026 if ( !subHtml.isEmpty() ) {
3028 TQString visibility;
3029 if ( !showAttachmentQuicklist() ) {
3030 visibility.append(
"display:none;" );
3034 if ( node != mRootNode || headerStyle() != HeaderStyle::enterprise() )
3035 margin =
"padding:2px; margin:2px; ";
3036 TQString align =
"left";
3037 if ( headerStyle() == HeaderStyle::enterprise() )
3039 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3040 html += TQString::fromLatin1(
"<div style=\"background:%1; %2"
3041 "vertical-align:middle; float:%3; %4\">").arg( bgColor.name() ).arg( margin )
3042 .arg( align ).arg( visibility );
3044 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3048 partNode::AttachmentDisplayInfo info = node->attachmentDisplayInfo();
3051 bool writePartToDisk = info.displayInHeader || node->msgPart().subtype() == DwMime::kSubtypeHtml;
3052 if ( writePartToDisk )
3055 if ( info.displayInHeader ) {
3056 html +=
"<div style=\"float:left;\">";
3057 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() );
3058 TQString href = node->asHREF(
"header" );
3059 html += TQString::fromLatin1(
"<a href=\"" ) + href +
3060 TQString::fromLatin1(
"\">" );
3061 html +=
"<img style=\"vertical-align:middle;\" src=\"" + info.icon +
"\"/> ";
3062 if ( headerStyle() == HeaderStyle::enterprise() ) {
3063 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3064 TQFontMetrics fm( bodyFont );
3065 html += KStringHandler::rPixelSqueeze( info.label, fm, 140 );
3066 }
else if ( headerStyle() == HeaderStyle::fancy() ) {
3067 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3068 TQFontMetrics fm( bodyFont );
3069 html += KStringHandler::rPixelSqueeze( info.label, fm, 640 );
3073 html +=
"</a></span></div> ";
3077 html += renderAttachments( node->nextSibling(), nextColor ( bgColor ) );
3083 void KMReaderWin::setBodyPartMemento(
const partNode * node,
const TQCString & which,
BodyPartMemento * memento )
3085 const TQCString index = node->path() +
':' + which.lower();
3087 const std::map<TQCString,BodyPartMemento*>::iterator it = mBodyPartMementoMap.lower_bound( index );
3088 if ( it != mBodyPartMementoMap.end() && it->first == index ) {
3090 if ( memento && memento == it->second )
3096 it->second = memento;
3099 mBodyPartMementoMap.erase( it );
3104 mBodyPartMementoMap.insert( it, std::make_pair( index, memento ) );
3112 BodyPartMemento * KMReaderWin::bodyPartMemento(
const partNode * node,
const TQCString & which )
const
3114 const TQCString index = node->path() +
':' + which.lower();
3115 const std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.find( index );
3116 if ( it == mBodyPartMementoMap.end() ) {
3130 void KMReaderWin::clearBodyPartMementos()
3132 for ( std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.begin(), end = mBodyPartMementoMap.end() ; it != end ; ++it )
3137 detach_and_delete( it->second,
this );
3139 mBodyPartMementoMap.clear();
3142 #include "kmreaderwin.moc"