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 <kstringhandler.h>
69 #include <mimelib/mimepp.h>
70 #include <mimelib/body.h>
71 #include <mimelib/utility.h>
73 #include <kleo/specialjob.h>
74 #include <kleo/cryptobackend.h>
75 #include <kleo/cryptobackendfactory.h>
78 #include <tdeabc/addressee.h>
79 #include <tdeabc/vcardconverter.h>
82 #include <tdehtml_part.h>
83 #include <tdehtmlview.h>
84 #include <dom/html_element.h>
85 #include <dom/html_block.h>
86 #include <dom/html_document.h>
87 #include <dom/dom_string.h>
88 #include <dom/dom_exception.h>
90 #include <tdeapplication.h>
92 #include <kuserprofile.h>
93 #include <kcharsets.h>
94 #include <tdepopupmenu.h>
95 #include <kstandarddirs.h>
98 #include <tdefiledialog.h>
99 #include <tdelocale.h>
100 #include <tdemessagebox.h>
101 #include <tdeglobal.h>
102 #include <tdeglobalsettings.h>
104 #include <tdetempfile.h>
105 #include <tdeprocess.h>
107 #include <tdeaction.h>
108 #include <kiconloader.h>
109 #include <kmdcodec.h>
110 #include <kurldrag.h>
112 #include <tqclipboard.h>
114 #include <tqtextcodec.h>
115 #include <tqpaintdevicemetrics.h>
116 #include <tqlayout.h>
118 #include <tqsplitter.h>
127 #include <sys/stat.h>
137 class NewByteArray :
public TQByteArray
140 NewByteArray &appendNULL();
141 NewByteArray &operator+=(
const char * );
142 NewByteArray &operator+=(
const TQByteArray & );
143 NewByteArray &operator+=(
const TQCString & );
144 TQByteArray& qByteArray();
147 NewByteArray& NewByteArray::appendNULL()
149 TQByteArray::detach();
151 if ( !TQByteArray::resize( len1 + 1 ) )
153 *(data() + len1) =
'\0';
156 NewByteArray& NewByteArray::operator+=(
const char * newData )
160 TQByteArray::detach();
162 uint len2 = tqstrlen( newData );
163 if ( !TQByteArray::resize( len1 + len2 ) )
165 memcpy( data() + len1, newData, len2 );
168 NewByteArray& NewByteArray::operator+=(
const TQByteArray & newData )
170 if ( newData.isNull() )
172 TQByteArray::detach();
174 uint len2 = newData.size();
175 if ( !TQByteArray::resize( len1 + len2 ) )
177 memcpy( data() + len1, newData.data(), len2 );
180 NewByteArray& NewByteArray::operator+=(
const TQCString & newData )
182 if ( newData.isEmpty() )
184 TQByteArray::detach();
186 uint len2 = newData.length();
187 if ( !TQByteArray::resize( len1 + len2 ) )
189 memcpy( data() + len1, newData.data(), len2 );
192 TQByteArray& NewByteArray::qByteArray()
194 return *((TQByteArray*)
this);
201 void KMReaderWin::objectTreeToDecryptedMsg( partNode* node,
202 NewByteArray& resultingData,
204 bool weAreReplacingTheRootNode,
207 kdDebug(5006) << TQString(
"-------------------------------------------------" ) << endl;
208 kdDebug(5006) << TQString(
"KMReaderWin::objectTreeToDecryptedMsg( %1 ) START").arg( recCount ) << endl;
211 kdDebug(5006) << node->typeString() <<
'/' << node->subTypeString() << endl;
213 partNode* curNode = node;
214 partNode* dataNode = curNode;
215 partNode * child = node->firstChild();
216 const bool bIsMultipart = node->type() == DwMime::kTypeMultipart ;
217 bool bKeepPartAsIs =
false;
219 switch( curNode->type() ){
220 case DwMime::kTypeMultipart: {
221 switch( curNode->subType() ){
222 case DwMime::kSubtypeSigned: {
223 bKeepPartAsIs =
true;
226 case DwMime::kSubtypeEncrypted: {
234 case DwMime::kTypeMessage: {
235 switch( curNode->subType() ){
236 case DwMime::kSubtypeRfc822: {
244 case DwMime::kTypeApplication: {
245 switch( curNode->subType() ){
246 case DwMime::kSubtypeOctetStream: {
251 case DwMime::kSubtypePkcs7Signature: {
254 bKeepPartAsIs =
true;
257 case DwMime::kSubtypePkcs7Mime: {
260 if ( child && curNode->encryptionState() != KMMsgNotEncrypted )
270 DwHeaders& rootHeaders( theMessage.
headers() );
271 DwBodyPart * part = dataNode->dwPart() ? dataNode->dwPart() : 0;
273 (part && part->hasHeaders())
275 : ( (weAreReplacingTheRootNode || !dataNode->parentNode())
278 if( dataNode == curNode ) {
279 kdDebug(5006) <<
"dataNode == curNode: Save curNode without replacing it." << endl;
285 if( dataNode->parentNode() && !weAreReplacingTheRootNode ) {
286 kdDebug(5006) <<
"dataNode is NOT replacing the root node: Store the headers." << endl;
287 resultingData += headers->AsString().c_str();
288 }
else if( weAreReplacingTheRootNode && part && part->hasHeaders() ){
289 kdDebug(5006) <<
"dataNode replace the root node: Do NOT store the headers but change" << endl;
290 kdDebug(5006) <<
" the Message's headers accordingly." << endl;
291 kdDebug(5006) <<
" old Content-Type = " << rootHeaders.ContentType().AsString().c_str() << endl;
292 kdDebug(5006) <<
" new Content-Type = " << headers->ContentType( ).AsString().c_str() << endl;
293 rootHeaders.ContentType() = headers->ContentType();
294 theMessage.setContentTransferEncodingStr(
295 headers->HasContentTransferEncoding()
296 ? headers->ContentTransferEncoding().AsString().c_str()
298 rootHeaders.ContentDescription() = headers->ContentDescription();
299 rootHeaders.ContentDisposition() = headers->ContentDisposition();
304 if ( bKeepPartAsIs ) {
305 resultingData += dataNode->encodedBody();
309 if( headers && bIsMultipart && dataNode->firstChild() ) {
310 kdDebug(5006) <<
"is valid Multipart, processing children:" << endl;
311 TQCString boundary = headers->ContentType().Boundary().c_str();
312 curNode = dataNode->firstChild();
315 kdDebug(5006) <<
"--boundary" << endl;
316 if( resultingData.size() &&
317 (
'\n' != resultingData.at( resultingData.size()-1 ) ) )
318 resultingData += TQCString(
"\n" );
319 resultingData += TQCString(
"\n" );
320 resultingData +=
"--";
321 resultingData += boundary;
322 resultingData +=
"\n";
326 objectTreeToDecryptedMsg( curNode,
331 curNode = curNode->nextSibling();
333 kdDebug(5006) <<
"--boundary--" << endl;
334 resultingData +=
"\n--";
335 resultingData += boundary;
336 resultingData +=
"--\n\n";
337 kdDebug(5006) <<
"Multipart processing children - DONE" << endl;
340 kdDebug(5006) <<
"is Simple part or invalid Multipart, storing body data .. DONE" << endl;
341 resultingData += part->Body().AsString().c_str();
345 kdDebug(5006) <<
"dataNode != curNode: Replace curNode by dataNode." << endl;
346 bool rootNodeReplaceFlag = weAreReplacingTheRootNode || !curNode->parentNode();
347 if( rootNodeReplaceFlag ) {
348 kdDebug(5006) <<
" Root node will be replaced." << endl;
350 kdDebug(5006) <<
" Root node will NOT be replaced." << endl;
354 objectTreeToDecryptedMsg( dataNode,
361 kdDebug(5006) << TQString(
"\nKMReaderWin::objectTreeToDecryptedMsg( %1 ) END").arg( recCount ) << endl;
385 void KMReaderWin::createWidgets() {
386 TQVBoxLayout * vlay =
new TQVBoxLayout(
this );
387 mSplitter =
new TQSplitter( TQt::Vertical,
this,
"mSplitter" );
388 vlay->addWidget( mSplitter );
389 mMimePartTree =
new KMMimePartTree(
this, mSplitter,
"mMimePartTree" );
390 mBox =
new TQHBox( mSplitter,
"mBox" );
391 setStyleDependantFrameWidth();
392 mBox->setFrameStyle( mMimePartTree->frameStyle() );
394 mViewer =
new TDEHTMLPart( mBox,
"mViewer" );
395 mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
396 mSplitter->setResizeMode( mMimePartTree, TQSplitter::KeepSize );
399 const int KMReaderWin::delay = 150;
402 KMReaderWin::KMReaderWin(TQWidget *aParent,
403 TQWidget *mainWindow,
404 TDEActionCollection* actionCollection,
407 : TQWidget(aParent, aName, aFlags | TQt::WDestructiveClose),
408 mSerNumOfOriginalMessage( 0 ),
410 mAttachmentStrategy( 0 ),
411 mHeaderStrategy( 0 ),
413 mUpdateReaderWinTimer( 0,
"mUpdateReaderWinTimer" ),
414 mResizeTimer( 0,
"mResizeTimer" ),
415 mDelayedMarkTimer( 0,
"mDelayedMarkTimer" ),
416 mHeaderRefreshTimer( 0,
"mHeaderRefreshTimer" ),
417 mOldGlobalOverrideEncoding(
"---" ),
420 mMainWindow( mainWindow ),
421 mActionCollection( actionCollection ),
422 mMailToComposeAction( 0 ),
423 mMailToReplyAction( 0 ),
424 mMailToForwardAction( 0 ),
425 mAddAddrBookAction( 0 ),
426 mOpenAddrBookAction( 0 ),
430 mUrlSaveAsAction( 0 ),
431 mAddBookmarksAction( 0 ),
432 mStartIMChatAction( 0 ),
433 mSelectAllAction( 0 ),
434 mHeaderOnlyAttachmentsAction( 0 ),
435 mSelectEncodingAction( 0 ),
436 mToggleFixFontAction( 0 ),
437 mToggleMimePartTreeAction( 0 ),
438 mCanStartDrag( false ),
440 mSavedRelativePosition( 0 ),
441 mDecrytMessageOverwrite( false ),
442 mShowSignatureDetails( false ),
443 mShowAttachmentQuicklist( true ),
444 mShowRawToltecMail( false )
446 mExternalWindow = (aParent == mainWindow );
447 mSplitterSizes << 180 << 100;
449 mMimeTreeModeOverride = -1;
450 mMimeTreeAtBottom =
true;
453 mWaitingForSerNum = 0;
457 mShowColorbar =
false;
461 createActions( actionCollection );
465 mHtmlOverride =
false;
466 mHtmlLoadExtDefault =
false;
467 mHtmlLoadExtOverride =
false;
469 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin() - 1;
471 connect( &mUpdateReaderWinTimer, TQ_SIGNAL(timeout()),
472 this, TQ_SLOT(updateReaderWin()) );
473 connect( &mResizeTimer, TQ_SIGNAL(timeout()),
474 this, TQ_SLOT(slotDelayedResize()) );
475 connect( &mDelayedMarkTimer, TQ_SIGNAL(timeout()),
476 this, TQ_SLOT(slotTouchMessage()) );
477 connect( &mHeaderRefreshTimer, TQ_SIGNAL(timeout()),
478 this, TQ_SLOT(updateHeader()) );
482 void KMReaderWin::createActions( TDEActionCollection * ac ) {
486 TDERadioAction *raction = 0;
489 TDEActionMenu *headerMenu =
490 new TDEActionMenu( i18n(
"View->",
"&Headers"), ac,
"view_headers" );
491 headerMenu->setToolTip( i18n(
"Choose display style of message headers") );
493 connect( headerMenu, TQ_SIGNAL(activated()),
494 this, TQ_SLOT(slotCycleHeaderStyles()) );
496 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Enterprise Headers"), 0,
497 this, TQ_SLOT(slotEnterpriseHeaders()),
498 ac,
"view_headers_enterprise" );
499 raction->setToolTip( i18n(
"Show the list of headers in Enterprise style") );
500 raction->setExclusiveGroup(
"view_headers_group" );
501 headerMenu->insert(raction);
503 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Fancy Headers"), 0,
504 this, TQ_SLOT(slotFancyHeaders()),
505 ac,
"view_headers_fancy" );
506 raction->setToolTip( i18n(
"Show the list of headers in a fancy format") );
507 raction->setExclusiveGroup(
"view_headers_group" );
508 headerMenu->insert( raction );
510 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Brief Headers"), 0,
511 this, TQ_SLOT(slotBriefHeaders()),
512 ac,
"view_headers_brief" );
513 raction->setToolTip( i18n(
"Show brief list of message headers") );
514 raction->setExclusiveGroup(
"view_headers_group" );
515 headerMenu->insert( raction );
517 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Standard Headers"), 0,
518 this, TQ_SLOT(slotStandardHeaders()),
519 ac,
"view_headers_standard" );
520 raction->setToolTip( i18n(
"Show standard list of message headers") );
521 raction->setExclusiveGroup(
"view_headers_group" );
522 headerMenu->insert( raction );
524 raction =
new TDERadioAction( i18n(
"View->headers->",
"&Long Headers"), 0,
525 this, TQ_SLOT(slotLongHeaders()),
526 ac,
"view_headers_long" );
527 raction->setToolTip( i18n(
"Show long list of message headers") );
528 raction->setExclusiveGroup(
"view_headers_group" );
529 headerMenu->insert( raction );
531 raction =
new TDERadioAction( i18n(
"View->headers->",
"&All Headers"), 0,
532 this, TQ_SLOT(slotAllHeaders()),
533 ac,
"view_headers_all" );
534 raction->setToolTip( i18n(
"Show all message headers") );
535 raction->setExclusiveGroup(
"view_headers_group" );
536 headerMenu->insert( raction );
539 TDEActionMenu *attachmentMenu =
540 new TDEActionMenu( i18n(
"View->",
"&Attachments"), ac,
"view_attachments" );
541 attachmentMenu->setToolTip( i18n(
"Choose display style of attachments") );
542 connect( attachmentMenu, TQ_SIGNAL(activated()),
543 this, TQ_SLOT(slotCycleAttachmentStrategy()) );
545 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&As Icons"), 0,
546 this, TQ_SLOT(slotIconicAttachments()),
547 ac,
"view_attachments_as_icons" );
548 raction->setToolTip( i18n(
"Show all attachments as icons. Click to see them.") );
549 raction->setExclusiveGroup(
"view_attachments_group" );
550 attachmentMenu->insert( raction );
552 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Smart"), 0,
553 this, TQ_SLOT(slotSmartAttachments()),
554 ac,
"view_attachments_smart" );
555 raction->setToolTip( i18n(
"Show attachments as suggested by sender.") );
556 raction->setExclusiveGroup(
"view_attachments_group" );
557 attachmentMenu->insert( raction );
559 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Inline"), 0,
560 this, TQ_SLOT(slotInlineAttachments()),
561 ac,
"view_attachments_inline" );
562 raction->setToolTip( i18n(
"Show all attachments inline (if possible)") );
563 raction->setExclusiveGroup(
"view_attachments_group" );
564 attachmentMenu->insert( raction );
566 raction =
new TDERadioAction( i18n(
"View->attachments->",
"&Hide"), 0,
567 this, TQ_SLOT(slotHideAttachments()),
568 ac,
"view_attachments_hide" );
569 raction->setToolTip( i18n(
"Do not show attachments in the message viewer") );
570 raction->setExclusiveGroup(
"view_attachments_group" );
571 attachmentMenu->insert( raction );
573 mHeaderOnlyAttachmentsAction =
new TDERadioAction( i18n(
"View->attachments->",
"In Header &Only" ), 0,
574 this, TQ_SLOT( slotHeaderOnlyAttachments() ),
575 ac,
"view_attachments_headeronly" );
576 mHeaderOnlyAttachmentsAction->setToolTip( i18n(
"Show Attachments only in the header of the mail" ) );
577 mHeaderOnlyAttachmentsAction->setExclusiveGroup(
"view_attachments_group" );
578 attachmentMenu->insert( mHeaderOnlyAttachmentsAction );
581 mSelectEncodingAction =
new TDESelectAction( i18n(
"&Set Encoding" ),
"charset", 0,
582 this, TQ_SLOT( slotSetEncoding() ),
584 TQStringList encodings = KMMsgBase::supportedEncodings(
false );
585 encodings.prepend( i18n(
"Auto" ) );
586 mSelectEncodingAction->setItems( encodings );
587 mSelectEncodingAction->setCurrentItem( 0 );
589 mMailToComposeAction =
new TDEAction( i18n(
"New Message To..."),
"mail-message-new",
590 0,
this, TQ_SLOT(slotMailtoCompose()), ac,
592 mMailToReplyAction =
new TDEAction( i18n(
"Reply To..."),
"mail-reply-sender",
595 mMailToForwardAction =
new TDEAction( i18n(
"Forward To..."),
"mail-forward",
596 0,
this, TQ_SLOT(slotMailtoForward()), ac,
598 mAddAddrBookAction =
new TDEAction( i18n(
"Add to Address Book"),
599 0,
this, TQ_SLOT(slotMailtoAddAddrBook()),
600 ac,
"add_addr_book" );
601 mOpenAddrBookAction =
new TDEAction( i18n(
"Open in Address Book"),
602 0,
this, TQ_SLOT(slotMailtoOpenAddrBook()),
603 ac,
"openin_addr_book" );
605 mSelectAllAction =
new TDEAction( i18n(
"Select All Text"), CTRL+SHIFT+Key_A,
this,
606 TQ_SLOT(
selectAll()), ac,
"mark_all_text" );
607 mCopyURLAction =
new TDEAction( i18n(
"Copy Link Address"), 0,
this,
609 mUrlOpenAction =
new TDEAction( i18n(
"Open URL"), 0,
this,
611 mAddBookmarksAction =
new TDEAction( i18n(
"Bookmark This Link"),
613 0,
this, TQ_SLOT(slotAddBookmarks()),
614 ac,
"add_bookmarks" );
615 mUrlSaveAsAction =
new TDEAction( i18n(
"Save Link As..."), 0,
this,
618 mToggleFixFontAction =
new TDEToggleAction( i18n(
"Use Fi&xed Font"),
620 ac,
"toggle_fixedfont" );
622 mToggleMimePartTreeAction =
new TDEToggleAction( i18n(
"Show Message Structure"),
623 0, ac,
"toggle_mimeparttree" );
624 connect(mToggleMimePartTreeAction, TQ_SIGNAL(toggled(
bool)),
627 mStartIMChatAction =
new TDEAction( i18n(
"Chat &With..."), 0,
this,
632 TDERadioAction *KMReaderWin::actionForHeaderStyle(
const HeaderStyle * style,
const HeaderStrategy * strategy ) {
633 if ( !mActionCollection )
635 const char * actionName = 0;
636 if ( style == HeaderStyle::enterprise() )
637 actionName =
"view_headers_enterprise";
638 if ( style == HeaderStyle::fancy() )
639 actionName =
"view_headers_fancy";
640 else if ( style == HeaderStyle::brief() )
641 actionName =
"view_headers_brief";
642 else if ( style == HeaderStyle::plain() ) {
643 if ( strategy == HeaderStrategy::standard() )
644 actionName =
"view_headers_standard";
645 else if ( strategy == HeaderStrategy::rich() )
646 actionName =
"view_headers_long";
647 else if ( strategy == HeaderStrategy::all() )
648 actionName =
"view_headers_all";
651 return static_cast<TDERadioAction*
>(mActionCollection->action(actionName));
656 TDERadioAction *KMReaderWin::actionForAttachmentStrategy(
const AttachmentStrategy * as ) {
657 if ( !mActionCollection )
659 const char * actionName = 0;
660 if ( as == AttachmentStrategy::iconic() )
661 actionName =
"view_attachments_as_icons";
662 else if ( as == AttachmentStrategy::smart() )
663 actionName =
"view_attachments_smart";
664 else if ( as == AttachmentStrategy::inlined() )
665 actionName =
"view_attachments_inline";
666 else if ( as == AttachmentStrategy::hidden() )
667 actionName =
"view_attachments_hide";
668 else if ( as == AttachmentStrategy::headerOnly() )
669 actionName =
"view_attachments_headeronly";
672 return static_cast<TDERadioAction*
>(mActionCollection->action(actionName));
677 void KMReaderWin::slotEnterpriseHeaders() {
679 HeaderStrategy::rich() );
680 if( !mExternalWindow )
684 void KMReaderWin::slotFancyHeaders() {
686 HeaderStrategy::rich() );
687 if( !mExternalWindow )
691 void KMReaderWin::slotBriefHeaders() {
693 HeaderStrategy::brief() );
694 if( !mExternalWindow )
698 void KMReaderWin::slotStandardHeaders() {
700 HeaderStrategy::standard());
704 void KMReaderWin::slotLongHeaders() {
706 HeaderStrategy::rich() );
707 if( !mExternalWindow )
711 void KMReaderWin::slotAllHeaders() {
713 HeaderStrategy::all() );
714 if( !mExternalWindow )
718 void KMReaderWin::slotLevelQuote(
int l )
725 void KMReaderWin::slotCycleHeaderStyles() {
729 const char * actionName = 0;
730 if ( style == HeaderStyle::enterprise() ) {
732 actionName =
"view_headers_fancy";
734 if ( style == HeaderStyle::fancy() ) {
736 actionName =
"view_headers_brief";
737 }
else if ( style == HeaderStyle::brief() ) {
738 slotStandardHeaders();
739 actionName =
"view_headers_standard";
740 }
else if ( style == HeaderStyle::plain() ) {
741 if ( strategy == HeaderStrategy::standard() ) {
743 actionName =
"view_headers_long";
744 }
else if ( strategy == HeaderStrategy::rich() ) {
746 actionName =
"view_headers_all";
747 }
else if ( strategy == HeaderStrategy::all() ) {
748 slotEnterpriseHeaders();
749 actionName =
"view_headers_enterprise";
754 static_cast<TDERadioAction*
>( mActionCollection->action( actionName ) )->setChecked(
true );
758 void KMReaderWin::slotIconicAttachments() {
759 setAttachmentStrategy( AttachmentStrategy::iconic() );
762 void KMReaderWin::slotSmartAttachments() {
763 setAttachmentStrategy( AttachmentStrategy::smart() );
766 void KMReaderWin::slotInlineAttachments() {
767 setAttachmentStrategy( AttachmentStrategy::inlined() );
770 void KMReaderWin::slotHideAttachments() {
771 setAttachmentStrategy( AttachmentStrategy::hidden() );
774 void KMReaderWin::slotHeaderOnlyAttachments() {
775 setAttachmentStrategy( AttachmentStrategy::headerOnly() );
778 void KMReaderWin::slotCycleAttachmentStrategy() {
782 action->setChecked(
true );
787 KMReaderWin::~KMReaderWin()
792 clearBodyPartMementos();
793 delete mHtmlWriter; mHtmlWriter = 0;
795 if (mAutoDelete)
delete message();
796 delete mRootNode; mRootNode = 0;
802 void KMReaderWin::slotMessageArrived(
KMMessage *msg )
804 if (msg && ((KMMsgBase*)msg)->isMessage()) {
805 if ( msg->getMsgSerNum() == mWaitingForSerNum ) {
831 kdDebug(5006) <<
"KMReaderWin::update - no updated part" << endl;
834 partNode* node = mRootNode->findNodeForDwPart( msg->
lastUpdatedPart() );
836 kdDebug(5006) <<
"KMReaderWin::update - can't find node for part" << endl;
843 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRWXU );
844 TQByteArray data = node->msgPart().bodyDecodedBinary();
845 size_t size = data.size();
846 if ( node->msgPart().type() == DwMime::kTypeText && size) {
849 KPIM::kBytesToFile( data.data(), size, mAtmCurrentName,
false,
false,
false );
850 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRUSR );
858 for (TQStringList::Iterator it = mTempFiles.begin(); it != mTempFiles.end();
864 for (TQStringList::Iterator it = mTempDirs.begin(); it != mTempDirs.end();
867 TQDir(*it).rmdir(*it);
876 if (e->type() == TQEvent::ApplicationPaletteChange)
879 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
885 return TQWidget::event(e);
892 const TDEConfigGroup mdnGroup( KMKernel::config(),
"MDN" );
893 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
896 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
898 mNoMDNsWhenEncrypted = mdnGroup.readBoolEntry(
"not-send-when-encrypted",
true );
900 mUseFixedFont = reader.readBoolEntry(
"useFixedFont",
false );
901 if ( mToggleFixFontAction )
902 mToggleFixFontAction->setChecked( mUseFixedFont );
904 mHtmlMail = reader.readBoolEntry(
"htmlMail",
false );
907 HeaderStrategy::create( reader.readEntry(
"header-set-displayed",
"rich" ) ) );
908 TDERadioAction *raction = actionForHeaderStyle( headerStyle(),
headerStrategy() );
910 raction->setChecked(
true );
912 setAttachmentStrategy( AttachmentStrategy::create( reader.readEntry(
"attachment-strategy",
"smart" ) ) );
915 raction->setChecked(
true );
919 mShowColorbar = reader.readBoolEntry(
"showColorbar", Kpgp::Module::getKpgp()->usePGP() );
923 reader.writeEntry(
"showColorbar", mShowColorbar );
925 mMimeTreeAtBottom = reader.readEntry(
"MimeTreeLocation",
"bottom" ) !=
"top";
926 const TQString s = reader.readEntry(
"MimeTreeMode",
"smart" );
929 else if ( s ==
"always" )
934 const int mimeH = reader.readNumEntry(
"MimePaneHeight", 100 );
935 const int messageH = reader.readNumEntry(
"MessagePaneHeight", 180 );
936 mSplitterSizes.clear();
937 if ( mMimeTreeAtBottom )
938 mSplitterSizes << messageH << mimeH;
940 mSplitterSizes << mimeH << messageH;
944 readGlobalOverrideCodec();
952 void KMReaderWin::adjustLayout() {
953 if ( mMimeTreeAtBottom )
954 mSplitter->moveToLast( mMimePartTree );
956 mSplitter->moveToFirst( mMimePartTree );
957 mSplitter->setSizes( mSplitterSizes );
959 if ( mMimeTreeMode == 2 && mMsgDisplay )
960 mMimePartTree->show();
962 mMimePartTree->hide();
964 if ( mShowColorbar && mMsgDisplay )
971 void KMReaderWin::saveSplitterSizes( TDEConfigBase & c )
const {
972 if ( !mSplitter || !mMimePartTree )
974 if ( mMimePartTree->isHidden() )
977 c.writeEntry(
"MimePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 1 : 0 ] );
978 c.writeEntry(
"MessagePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 0 : 1 ] );
983 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
985 reader.writeEntry(
"useFixedFont", mUseFixedFont );
987 reader.writeEntry(
"header-style", headerStyle()->name() );
989 reader.writeEntry(
"header-set-displayed",
headerStrategy()->name() );
993 saveSplitterSizes( reader );
996 kmkernel->slotRequestConfigSync();
1002 mViewer->widget()->setFocusPolicy(TQWidget::WheelFocus);
1004 mViewer->setPluginsEnabled(
false);
1005 mViewer->setJScriptEnabled(
false);
1006 mViewer->setJavaEnabled(
false);
1007 mViewer->setMetaRefreshEnabled(
false);
1008 mViewer->setURLCursor(KCursor::handCursor());
1010 mViewer->view()->setLineWidth(0);
1012 mViewer->view()->viewport()->installEventFilter(
this );
1015 #ifdef KMAIL_READER_HTML_DEBUG
1016 mHtmlWriter =
new TeeHtmlWriter(
new FileHtmlWriter( TQString() ),
1017 new KHtmlPartHtmlWriter( mViewer, 0 ) );
1019 mHtmlWriter =
new KHtmlPartHtmlWriter( mViewer, 0 );
1022 connect(mViewer->browserExtension(),
1023 TQ_SIGNAL(openURLRequest(
const KURL &,
const KParts::URLArgs &)),
this,
1025 connect(mViewer->browserExtension(),
1026 TQ_SIGNAL(createNewWindow(
const KURL &,
const KParts::URLArgs &)),
this,
1028 connect(mViewer,TQ_SIGNAL(
popupMenu(
const TQString &,
const TQPoint &)),
1029 TQ_SLOT(
slotUrlPopup(
const TQString &,
const TQPoint &)));
1030 connect( kmkernel->imProxy(), TQ_SIGNAL( sigContactPresenceChanged(
const TQString & ) ),
1031 this, TQ_SLOT( contactStatusChanged(
const TQString & ) ) );
1032 connect( kmkernel->imProxy(), TQ_SIGNAL( sigPresenceInfoExpired() ),
1036 void KMReaderWin::contactStatusChanged(
const TQString &uid)
1040 DOM::NodeList presenceNodes = mViewer->htmlDocument()
1041 .getElementsByName( DOM::DOMString( TQString::fromLatin1(
"presence-") + uid ) );
1042 for (
unsigned int i = 0; i < presenceNodes.length(); ++i ) {
1043 DOM::Node n = presenceNodes.item( i );
1044 kdDebug( 5006 ) <<
"name is " << n.nodeName().string() << endl;
1045 kdDebug( 5006 ) <<
"value of content was " << n.firstChild().nodeValue().string() << endl;
1046 TQString newPresence = kmkernel->imProxy()->presenceString( uid );
1047 if ( newPresence.isNull() )
1048 newPresence = TQString::fromLatin1(
"ENOIMRUNNING" );
1049 n.firstChild().setNodeValue( newPresence );
1055 void KMReaderWin::setAttachmentStrategy(
const AttachmentStrategy * strategy ) {
1056 mAttachmentStrategy = strategy ? strategy : AttachmentStrategy::smart();
1061 const HeaderStrategy * strategy ) {
1062 mHeaderStyle = style ? style : HeaderStyle::fancy();
1063 mHeaderStrategy = strategy ? strategy : HeaderStrategy::rich();
1064 if ( mHeaderOnlyAttachmentsAction ) {
1065 const bool styleHasAttachmentQuickList = mHeaderStyle == HeaderStyle::fancy() ||
1066 mHeaderStyle == HeaderStyle::enterprise();
1067 mHeaderOnlyAttachmentsAction->setEnabled( styleHasAttachmentQuickList );
1068 if ( !styleHasAttachmentQuickList && mAttachmentStrategy == AttachmentStrategy::headerOnly() ) {
1071 setAttachmentStrategy( AttachmentStrategy::smart() );
1080 if ( encoding == mOverrideEncoding )
1083 mOverrideEncoding = encoding;
1084 if ( mSelectEncodingAction ) {
1085 if ( encoding.isEmpty() ) {
1086 mSelectEncodingAction->setCurrentItem( 0 );
1089 TQStringList encodings = mSelectEncodingAction->items();
1091 for ( TQStringList::const_iterator it = encodings.begin(), end = encodings.end(); it != end; ++it, ++i ) {
1092 if ( TDEGlobal::charsets()->encodingForName( *it ) == encoding ) {
1093 mSelectEncodingAction->setCurrentItem( i );
1097 if ( i == encodings.size() ) {
1099 kdWarning(5006) <<
"Unknown override character encoding \"" << encoding
1100 <<
"\". Using Auto instead." << endl;
1101 mSelectEncodingAction->setCurrentItem( 0 );
1102 mOverrideEncoding = TQString();
1110 void KMReaderWin::setPrintFont(
const TQFont& font )
1113 mCSSHelper->setPrintFont( font );
1119 if ( mOverrideEncoding.isEmpty() || mOverrideEncoding ==
"Auto" )
1122 return KMMsgBase::codecForName( mOverrideEncoding.latin1() );
1126 void KMReaderWin::slotSetEncoding()
1128 if ( mSelectEncodingAction->currentItem() == 0 )
1129 mOverrideEncoding = TQString();
1131 mOverrideEncoding = TDEGlobal::charsets()->encodingForName( mSelectEncodingAction->currentText() );
1136 void KMReaderWin::readGlobalOverrideCodec()
1139 if ( GlobalSettings::self()->overrideCharacterEncoding() == mOldGlobalOverrideEncoding )
1143 mOldGlobalOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
1149 mSerNumOfOriginalMessage = serNumOfOriginalMessage;
1150 mNodeIdOffset = nodeIdOffset;
1157 kdDebug(5006) <<
"(" << aMsg->getMsgSerNum() <<
", last " << mLastSerNum <<
") " << aMsg->
subject() <<
" "
1158 << aMsg->fromStrip() <<
", readyToShow " << (aMsg->
readyToShow()) << endl;
1162 if ( aMsg && aMsg->getMsgSerNum() != mLastSerNum && !updateOnly ){
1163 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin()-1;
1164 mShowRawToltecMail = !GlobalSettings::self()->showToltecReplacementText();
1165 clearBodyPartMementos();
1170 bool complete =
true;
1173 (aMsg->getMsgSerNum() != mLastSerNum) &&
1178 if (!force && aMsg && mLastSerNum != 0 && aMsg->getMsgSerNum() == mLastSerNum)
1185 aMsg->attach(
this );
1188 mDelayedMarkTimer.stop();
1192 mWaitingForSerNum = 0;
1195 mLastSerNum = aMsg->getMsgSerNum();
1212 mViewer->setDNDEnabled(
false );
1214 mViewer->setDNDEnabled(
true );
1224 mUpdateReaderWinTimer.stop();
1227 else if (mUpdateReaderWinTimer.isActive())
1228 mUpdateReaderWinTimer.changeInterval( delay );
1230 mUpdateReaderWinTimer.start( 0,
true );
1233 if ( aMsg && (aMsg->isUnread() || aMsg->isNew()) && GlobalSettings::self()->delayedMarkAsRead() ) {
1234 if ( GlobalSettings::self()->delayedMarkTime() != 0 )
1235 mDelayedMarkTimer.start( GlobalSettings::self()->delayedMarkTime() * 1000,
true );
1240 mHeaderRefreshTimer.start( 1000,
false );
1246 mUpdateReaderWinTimer.stop();
1248 mDelayedMarkTimer.stop();
1250 mWaitingForSerNum = 0;
1255 static const char *
const kmailChanges[] = {
1258 static const int numKMailChanges =
1259 sizeof kmailChanges /
sizeof *kmailChanges;
1265 static const char *
const kmailNewFeatures[] = {
1266 I18N_NOOP(
"Full namespace support for IMAP"),
1267 I18N_NOOP(
"Offline mode"),
1268 I18N_NOOP(
"Sieve script management and editing"),
1269 I18N_NOOP(
"Account specific filtering"),
1270 I18N_NOOP(
"Filtering of incoming mail for online IMAP accounts"),
1271 I18N_NOOP(
"Online IMAP folders can be used when filtering into folders"),
1272 I18N_NOOP(
"Automatically delete older mails on POP servers")
1274 static const int numKMailNewFeatures =
1275 sizeof kmailNewFeatures /
sizeof *kmailNewFeatures;
1283 for (
int i = 0 ; i < numKMailChanges ; ++i )
1284 str += kmailChanges[i];
1285 for (
int i = 0 ; i < numKMailNewFeatures ; ++i )
1286 str += kmailNewFeatures[i];
1288 return md5.base64Digest();
1294 mMsgDisplay =
false;
1297 TQString location = locate(
"data",
"kmail/about/main.html");
1298 TQString content = KPIM::kFileToString(location);
1299 content = content.arg( locate(
"data",
"libtdepim/about/kde_infopage.css" ) );
1300 if ( kapp->reverseLayout() )
1301 content = content.arg(
"@import \"%1\";" ).arg( locate(
"data",
"libtdepim/about/kde_infopage_rtl.css" ) );
1303 content = content.arg(
"" );
1305 mViewer->begin(KURL( location ));
1307 TQString fontSize = TQString::number(
pointsToPixel( mCSSHelper->bodyFont().pointSize() ) );
1308 TQString appTitle = i18n(
"KMail");
1309 TQString catchPhrase =
"";
1310 TQString quickDescription = i18n(
"The email client for the Trinity Desktop Environment.");
1311 mViewer->write(content.arg(fontSize).arg(appTitle).arg(catchPhrase).arg(quickDescription).arg(info));
1318 i18n(
"<h2 style='margin-top: 0px;'>Retrieving Folder Contents</h2><p>Please wait . . .</p> " );
1326 i18n(
"<h2 style='margin-top: 0px;'>Offline</h2><p>KMail is currently in offline mode. "
1327 "Click <a href=\"kmail:goOnline\">here</a> to go online . . .</p> " );
1337 i18n(
"%1: KMail version; %2: help:// URL; %3: homepage URL; "
1338 "%4: prior KMail version; %5: prior TDE version; "
1339 "%6: generated list of new features; "
1340 "%7: First-time user text (only shown on first start); "
1341 "%8: generated list of important changes; "
1342 "--- end of comment ---",
1343 "<h2 style='margin-top: 0px;'>Welcome to KMail %1</h2><p>KMail is the email client for the Trinity "
1344 "Desktop Environment. It is designed to be fully compatible with "
1345 "Internet mailing standards including MIME, SMTP, POP3 and IMAP."
1347 "<ul><li>KMail has many powerful features which are described in the "
1348 "<a href=\"%2\">documentation</a></li>\n"
1349 "<li>The <a href=\"%3\">KMail (TDE) homepage</A> offers information about "
1350 "new versions of KMail</li></ul>\n"
1352 "<p>Some of the new features in this release of KMail include "
1353 "(compared to KMail %4, which is part of TDE %5):</p>\n"
1356 "<p>We hope that you will enjoy KMail.</p>\n"
1357 "<p>Thank you,</p>\n"
1358 "<p style='margin-bottom: 0px'> The KMail Team</p>")
1360 .arg(
"help:/kmail/index.html")
1361 .arg(
"http://www.trinitydesktop.org")
1362 .arg(
"1.8").arg(
"3.4");
1364 TQString featureItems;
1365 for (
int i = 0 ; i < numKMailNewFeatures ; i++ )
1366 featureItems += i18n(
"<li>%1</li>\n").arg( i18n( kmailNewFeatures[i] ) );
1368 info = info.arg( featureItems );
1370 if( kmkernel->firstStart() ) {
1371 info = info.arg( i18n(
"<p>Please take a moment to fill in the KMail "
1372 "configuration panel at Settings->Configure "
1374 "You need to create at least a default identity and "
1375 "an incoming as well as outgoing mail account."
1378 info = info.arg( TQString() );
1381 if ( ( numKMailChanges > 1 ) || ( numKMailChanges == 1 && strlen(kmailChanges[0]) > 0 ) ) {
1382 TQString changesText =
1383 i18n(
"<p><span style='font-size:125%; font-weight:bold;'>"
1384 "Important changes</span> (compared to KMail %1):</p>\n")
1386 changesText +=
"<ul>\n";
1387 for (
int i = 0 ; i < numKMailChanges ; i++ )
1388 changesText += i18n(
"<li>%1</li>\n").arg( i18n( kmailChanges[i] ) );
1389 changesText +=
"</ul>\n";
1390 info = info.arg( changesText );
1393 info = info.arg(
"");
1408 if (!mMsgDisplay)
return;
1415 if ( mShowColorbar )
1424 mMimePartTree->hide();
1425 mMimePartTree->clear();
1426 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1427 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) +
"</body></html>" );
1431 if (mSavedRelativePosition)
1433 TQScrollView * scrollview =
static_cast<TQScrollView *
>(mViewer->widget());
1434 scrollview->setContentsPos( 0,
1435 tqRound( scrollview->contentsHeight() * mSavedRelativePosition ) );
1436 mSavedRelativePosition = 0;
1443 const TQPaintDeviceMetrics pdm(mViewer->view());
1445 return (pointSize * pdm.logicalDpiY() + 36) / 72;
1450 if ( mMimeTreeModeOverride == 2 ||
1451 ( mMimeTreeModeOverride != 0 && (mMimeTreeMode == 2 ||
1452 ( mMimeTreeMode == 1 && !isPlainTextTopLevel ) ) ) ) {
1453 mMimePartTree->show();
1457 TDEConfigGroup reader( KMKernel::config(),
"Reader" );
1458 saveSplitterSizes( reader );
1459 mMimePartTree->hide();
1462 if ( mToggleMimePartTreeAction && mToggleMimePartTreeAction->isChecked() != mMimePartTree->isVisible() ) {
1463 mToggleMimePartTreeAction->setChecked( mMimePartTree->isVisible() );
1470 mMimePartTree->clear();
1471 mMimeTreeModeOverride = -1;
1473 ( msg->type() == DwMime::kTypeText
1474 && msg->subtype() == DwMime::kSubtypePlain ) );
1481 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1482 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
1493 if( mColorBar->isNeutral() )
1499 TQTimer::singleShot( 1,
this, TQ_SLOT(injectAttachments()) );
1502 static bool message_was_saved_decrypted_before(
const KMMessage * msg ) {
1506 return msg->
msgId().stripWhiteSpace().startsWith(
"<DecryptedMsg." );
1512 KMMessagePart msgPart;
1513 TQCString subtype, contDisp;
1518 aMsg->setIsBeingParsed(
true );
1520 if ( mRootNode && !mRootNode->processed() )
1522 kdWarning() <<
"The root node is not yet processed! Danger!\n";
1526 mRootNode = partNode::fromMessage( aMsg,
this );
1527 const TQCString mainCntTypeStr = mRootNode->typeString() +
'/' + mRootNode->subTypeString();
1529 TQString cntDesc = aMsg->
subject();
1530 if( cntDesc.isEmpty() )
1531 cntDesc = i18n(
"( body part )");
1532 TDEIO::filesize_t cntSize = aMsg->
msgSize();
1540 mRootNode->fillMimePartTree( 0,
1547 partNode* vCardNode = mRootNode->findType( DwMime::kTypeText, DwMime::kSubtypeXVCard );
1548 bool hasVCard =
false;
1552 TDEABC::VCardConverter t;
1553 #if defined(KABC_VCARD_ENCODING_FIX)
1554 const TQByteArray vcard = vCardNode->msgPart().bodyDecodedBinary();
1555 if ( !t.parseVCardsRaw( vcard.data() ).empty() ) {
1557 const TQString vcard = vCardNode->msgPart().bodyToUnicode(
overrideCodec() );
1558 if ( !t.parseVCards( vcard ).empty() ) {
1565 if ( !mRootNode || !mRootNode->isToltecMessage() || mShowRawToltecMail ) {
1570 ObjectTreeParser otp(
this );
1571 otp.setAllowAsync(
true );
1572 otp.setShowRawToltecMail( mShowRawToltecMail );
1573 otp.parseObjectTree( mRootNode );
1577 KMMsgEncryptionState encryptionState = mRootNode->overallEncryptionState();
1578 KMMsgSignatureState signatureState = mRootNode->overallSignatureState();
1588 if ( signatureState != KMMsgNotSigned ||
1593 bool emitReplaceMsgByUnencryptedVersion =
false;
1594 const TDEConfigGroup reader( KMKernel::config(),
"Reader" );
1595 if ( reader.readBoolEntry(
"store-displayed-messages-unencrypted",
false ) ) {
1610 kdDebug(5006) <<
"\n\n\nKMReaderWin::parseMsg() - special post-encryption handling:\n1." << endl;
1611 kdDebug(5006) <<
"(aMsg == msg) = " << (aMsg ==
message()) << endl;
1612 kdDebug(5006) <<
"aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() = " << (aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder()) << endl;
1613 kdDebug(5006) <<
"message_was_saved_decrypted_before( aMsg ) = " << message_was_saved_decrypted_before( aMsg ) << endl;
1614 kdDebug(5006) <<
"this->decryptMessage() = " <<
decryptMessage() << endl;
1615 kdDebug(5006) <<
"otp.hasPendingAsyncJobs() = " << otp.hasPendingAsyncJobs() << endl;
1616 kdDebug(5006) <<
" (KMMsgFullyEncrypted == encryptionState) = " << (KMMsgFullyEncrypted == encryptionState) << endl;
1617 kdDebug(5006) <<
"|| (KMMsgPartiallyEncrypted == encryptionState) = " << (KMMsgPartiallyEncrypted == encryptionState) << endl;
1622 && ( aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() )
1624 && !message_was_saved_decrypted_before( aMsg )
1628 && !otp.hasPendingAsyncJobs()
1630 && ( (KMMsgFullyEncrypted == encryptionState)
1631 || (KMMsgPartiallyEncrypted == encryptionState) ) ) {
1633 kdDebug(5006) <<
"KMReaderWin - calling objectTreeToDecryptedMsg()" << endl;
1635 NewByteArray decryptedData;
1637 objectTreeToDecryptedMsg( mRootNode, decryptedData, *aMsg );
1639 decryptedData.appendNULL();
1640 TQCString resultString( decryptedData.data() );
1641 kdDebug(5006) <<
"KMReaderWin - resulting data:" << resultString << endl;
1643 if( !resultString.isEmpty() ) {
1644 kdDebug(5006) <<
"KMReaderWin - composing unencrypted message" << endl;
1646 aMsg->
setBody( resultString );
1648 unencryptedMessage->setParent( 0 );
1657 kdDebug(5006) <<
"KMReaderWin - attach unencrypted message to aMsg" << endl;
1659 emitReplaceMsgByUnencryptedVersion =
true;
1665 const int rootNodeCntType = mRootNode ? mRootNode->type() : DwMime::kTypeText;
1666 const int rootNodeCntSubtype = mRootNode ? mRootNode->subType() : DwMime::kSubtypePlain;
1671 if( emitReplaceMsgByUnencryptedVersion ) {
1672 kdDebug(5006) <<
"KMReaderWin - invoce saving in decrypted form:" << endl;
1675 kdDebug(5006) <<
"KMReaderWin - finished parsing and displaying of message." << endl;
1677 rootNodeCntSubtype == DwMime::kSubtypePlain );
1680 aMsg->setIsBeingParsed(
false );
1685 void KMReaderWin::updateHeader()
1697 if (currentMessage &&
1698 mHeaderStyle == HeaderStyle::fancy() &&
1699 currentMessage->parent())
1703 DOM::NodeList divs(mViewer->document().documentElement().getElementsByTagName(
"div"));
1704 DOM::NodeList headerDivs(
static_cast<DOM::HTMLDivElement
>(divs.item(0)).getElementsByTagName(
"div"));
1705 for (i=0; i<((int)headerDivs.length()); i++) {
1706 if (
static_cast<DOM::HTMLDivElement
>(headerDivs.item(i)).
id().string() ==
"sendersCurrentTime") {
1712 if (divNumber >= 0) {
1713 DOM::HTMLDivElement elem =
static_cast<DOM::HTMLDivElement
>(headerDivs.item(i));
1717 TQString latestHeader = headerStyle()->format( currentMessage,
headerStrategy(),
"", mPrinting,
false );
1718 int startPos = latestHeader.find(
"<div id=\"sendersCurrentTime\" style=\"");
1719 if (startPos >= 0) {
1720 latestHeader = latestHeader.mid(startPos);
1721 int endPos = latestHeader.find(
"</div>");
1723 endPos = endPos + 6;
1724 latestHeader.truncate(endPos);
1726 TQString divText = latestHeader;
1727 TQString divStyle = latestHeader;
1729 divText = divText.mid(divText.find(
">")+1);
1730 divText.truncate(divText.find(
"</div>"));
1732 divStyle = divStyle.mid(TQString(
"<div id=\"sendersCurrentTime\" style=\"").length());
1733 divStyle.truncate(divStyle.find(
"\""));
1735 elem.setInnerHTML(divText);
1736 elem.setAttribute(
"style", divStyle);
1737 elem.applyChanges();
1747 kdFatal( !headerStyle(), 5006 )
1748 <<
"trying to writeMsgHeader() without a header style set!" << endl;
1750 <<
"trying to writeMsgHeader() without a header strategy set!" << endl;
1753 href = vCardNode->asHREF(
"body" );
1755 return headerStyle()->format( aMsg,
headerStrategy(), href, mPrinting, topLevel );
1764 TQString fileName = aMsgPart->fileName();
1765 if( fileName.isEmpty() )
1766 fileName = aMsgPart->name();
1769 TQString fname =
createTempDir( TQString::number( aPartNum ) );
1770 if ( fname.isEmpty() )
1774 int slashPos = fileName.findRev(
'/' );
1775 if( -1 != slashPos )
1776 fileName = fileName.mid( slashPos + 1 );
1777 if( fileName.isEmpty() ) {
1778 fileName =
"unnamed";
1780 if ( aMsgPart->subtype() == DwMime::kSubtypeHtml )
1781 fileName +=
".html";
1783 fname +=
"/" + fileName;
1785 TQByteArray data = aMsgPart->bodyDecodedBinary();
1786 size_t size = data.size();
1787 if ( aMsgPart->type() == DwMime::kTypeText && size) {
1791 if( !KPIM::kBytesToFile( data.data(), size, fname,
false,
false,
false ) )
1794 mTempFiles.append( fname );
1797 ::chmod( TQFile::encodeName( fname ), S_IRUSR );
1804 KTempFile *tempFile =
new KTempFile( TQString(),
"." + param );
1805 tempFile->setAutoDelete(
true );
1806 TQString fname = tempFile->name();
1809 if( ::access( TQFile::encodeName( fname ), W_OK ) != 0 )
1811 if( ::mkdir( TQFile::encodeName( fname ), 0 ) != 0
1812 || ::chmod( TQFile::encodeName( fname ), S_IRWXU ) != 0 )
1815 assert( !fname.isNull() );
1817 mTempDirs.append( fname );
1824 #if defined(KABC_VCARD_ENCODING_FIX)
1825 const TQByteArray vCard = msgPart->bodyDecodedBinary();
1827 const TQString vCard = msgPart->bodyToUnicode(
overrideCodec() );
1829 VCardViewer *vcv =
new VCardViewer(
this, vCard,
"vCardDialog" );
1837 mViewer->view()->print();
1844 if (aUrl.isEmpty())
return -1;
1845 if (!aUrl.isLocalFile())
return -1;
1847 TQString path = aUrl.path();
1848 uint right = path.findRev(
'/');
1849 uint left = path.findRev(
'.', right);
1852 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
1853 return (ok) ? res : -1;
1858 void KMReaderWin::resizeEvent(TQResizeEvent *)
1860 if( !mResizeTimer.isActive() )
1866 mResizeTimer.start( 100,
true );
1872 void KMReaderWin::slotDelayedResize()
1874 mSplitter->setGeometry(0, 0, width(), height());
1879 void KMReaderWin::slotTouchMessage()
1888 serNums.append(
message()->getMsgSerNum() );
1889 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
1893 if ( mNoMDNsWhenEncrypted &&
1894 message()->encryptionState() != KMMsgNotEncrypted &&
1895 message()->encryptionState() != KMMsgEncryptionStateUnknown )
1907 if ( !kmkernel->msgSender()->send( receipt ) )
1908 KMessageBox::error(
this, i18n(
"Could not send MDN.") );
1915 TQWidget::closeEvent(e);
1920 bool foundSMIMEData(
const TQString aUrl,
1921 TQString& displayName,
1925 static TQString showCertMan(
"showCertificate#");
1929 int i1 = aUrl.find( showCertMan );
1931 i1 += showCertMan.length();
1932 int i2 = aUrl.find(
" ### ", i1);
1935 displayName = aUrl.mid( i1, i2-i1 );
1937 i2 = aUrl.find(
" ### ", i1);
1940 libName = aUrl.mid( i1, i2-i1 );
1943 keyId = aUrl.mid( i2 );
1959 return !keyId.isEmpty();
1966 const KURL url(aUrl);
1968 if ( url.protocol() ==
"kmail" || url.protocol() ==
"x-kmail" || url.protocol() ==
"attachment"
1969 || (url.protocol().isEmpty() && url.path().isEmpty()) ) {
1970 mViewer->setDNDEnabled(
false );
1972 mViewer->setDNDEnabled(
true );
1975 if ( aUrl.stripWhiteSpace().isEmpty() ) {
1976 KPIM::BroadcastStatus::instance()->reset();
1977 mHoveredUrl = KURL();
1978 mLastClickImagePath = TQString();
1984 const TQString msg = URLHandlerManager::instance()->statusBarMessage( url,
this );
1986 kdWarning( msg.isEmpty(), 5006 ) <<
"KMReaderWin::slotUrlOn(): Unhandled URL hover!" << endl;
1987 KPIM::BroadcastStatus::instance()->setTransienStatusMsg( msg );
1996 if ( URLHandlerManager::instance()->handleClick( aUrl,
this ) )
1999 kdWarning( 5006 ) <<
"KMReaderWin::slotOpenUrl(): Unhandled URL click!" << endl;
2006 const KURL url( aUrl );
2009 if ( url.protocol() ==
"mailto" ) {
2010 mCopyURLAction->setText( i18n(
"Copy Email Address" ) );
2012 mCopyURLAction->setText( i18n(
"Copy Link Address" ) );
2015 if ( URLHandlerManager::instance()->handleContextMenuRequest( url, aPos,
this ) )
2019 kdWarning( 5006 ) <<
"KMReaderWin::slotUrlPopup(): Unhandled URL right-click!" << endl;
2020 emitPopupMenu( url, aPos );
2026 static bool hasParentDivWithId(
const DOM::Node &start,
const TQString &
id )
2028 if ( start.isNull() )
2031 if ( start.nodeName().string() ==
"div" ) {
2032 for (
unsigned int i = 0; i < start.attributes().length(); i++ ) {
2033 if ( start.attributes().item( i ).nodeName().string() ==
"id" &&
2034 start.attributes().item( i ).nodeValue().string() ==
id )
2039 if ( !start.parentNode().isNull() )
2040 return hasParentDivWithId( start.parentNode(),
id );
2045 void KMReaderWin::showAttachmentPopup(
int id,
const TQString & name,
const TQPoint & p )
2048 mAtmCurrentName = name;
2049 TDEPopupMenu *menu =
new TDEPopupMenu();
2050 menu->insertItem(SmallIcon(
"document-open"),i18n(
"to open",
"Open"), 1);
2051 menu->insertItem(i18n(
"Open With..."), 2);
2052 menu->insertItem(i18n(
"to view something",
"View"), 3);
2053 menu->insertItem(SmallIcon(
"document-save-as"),i18n(
"Save As..."), 4);
2054 menu->insertItem(SmallIcon(
"edit-copy"), i18n(
"Copy"), 9 );
2055 const bool canChange =
message()->parent() ? !
message()->parent()->isReadOnly() :
false;
2056 if ( GlobalSettings::self()->allowAttachmentEditing() && canChange )
2057 menu->insertItem(SmallIcon(
"edit"), i18n(
"Edit Attachment"), 8 );
2058 if ( GlobalSettings::self()->allowAttachmentDeletion() && canChange )
2059 menu->insertItem(SmallIcon(
"edit-delete"), i18n(
"Delete Attachment"), 7 );
2060 if ( name.endsWith(
".xia",
false ) &&
2061 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) )
2062 menu->insertItem( i18n(
"Decrypt With Chiasmus..." ), 6 );
2063 menu->insertItem(i18n(
"Properties"), 5);
2065 const bool attachmentInHeader = hasParentDivWithId( mViewer->nodeUnderMouse(),
"attachmentInjectionPoint" );
2066 const bool hasScrollbar = mViewer->view()->verticalScrollBar()->isVisible();
2067 if ( attachmentInHeader && hasScrollbar ) {
2068 menu->insertItem( i18n(
"Scroll To"), 10 );
2071 connect(menu, TQ_SIGNAL(activated(
int)),
this, TQ_SLOT(slotHandleAttachment(
int)));
2083 if( style().isA(
"KeramikStyle") )
2084 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
2086 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
2087 if ( frameWidth < 0 )
2089 if ( frameWidth != mBox->lineWidth() )
2090 mBox->setLineWidth( frameWidth );
2097 TQWidget::styleChange( oldStyle );
2101 void KMReaderWin::slotHandleAttachment(
int choice )
2104 partNode* node = mRootNode ? mRootNode->findId( mAtmCurrent ) : 0;
2105 if ( mAtmCurrentName.isEmpty() && node )
2106 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2108 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand(
2109 node,
message(), mAtmCurrent, mAtmCurrentName,
2110 KMHandleAttachmentCommand::AttachmentAction( choice ), 0,
this );
2111 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2112 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2114 }
else if ( choice == 7 ) {
2115 slotDeleteAttachment( node );
2116 }
else if ( choice == 8 ) {
2117 slotEditAttachment( node );
2118 }
else if ( choice == 9 ) {
2119 if ( !node )
return;
2121 KURL url = tempFileUrlFromPartNode( node );
2122 if (!url.isValid() )
return;
2124 KURLDrag* drag =
new KURLDrag( urls,
this );
2125 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
2126 }
else if ( choice == 10 ) {
2134 mViewer->findText();
2140 mViewer->findTextNext();
2146 mUseFixedFont = !mUseFixedFont;
2155 if ( mToggleMimePartTreeAction->isChecked() ) {
2156 mMimeTreeModeOverride = 2;
2158 mMimeTreeModeOverride = 0;
2166 kapp->clipboard()->setText( mViewer->selectedText() );
2173 assert(aMsgPart!=0);
2175 msg->fromString(aMsgPart->bodyDecoded());
2179 msg->setParent(
message()->parent() );
2180 msg->setUID(
message()->UID());
2182 KMReaderMainWin *win =
new KMReaderMainWin();
2191 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2192 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2195 ObjectTreeParser otp(
this, 0,
true );
2196 otp.parseObjectTree( node );
2205 const TQString& aFileName,
const TQString& pname )
2208 if (kasciistricmp(aMsgPart->typeStr(),
"message")==0) {
2211 assert(aMsgPart!=0);
2212 msg->fromString(aMsgPart->bodyDecoded());
2213 mMainWindow->setCaption(msg->
subject());
2215 setAutoDelete(
true);
2216 }
else if (kasciistricmp(aMsgPart->typeStr(),
"text")==0) {
2217 if (kasciistricmp(aMsgPart->subtypeStr(),
"x-vcard") == 0) {
2221 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2222 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2224 if (aHTML && (kasciistricmp(aMsgPart->subtypeStr(),
"html")==0)) {
2229 const TQCString str = aMsgPart->bodyDecoded();
2230 ObjectTreeParser otp(
this );
2231 otp.writeBodyStr( str,
2237 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2238 }
else if (kasciistricmp(aMsgPart->typeStr(),
"image")==0 ||
2239 (kasciistricmp(aMsgPart->typeStr(),
"application")==0 &&
2240 kasciistricmp(aMsgPart->subtypeStr(),
"postscript")==0))
2242 if (aFileName.isEmpty())
return;
2244 TQImageIO *iio =
new TQImageIO();
2245 iio->setFileName(aFileName);
2247 TQImage img = iio->image();
2248 TQRect desk = TDEGlobalSettings::desktopGeometry(mMainWindow);
2251 if( img.width() < 50 )
2253 else if( img.width()+20 < desk.width() )
2254 width = img.width()+20;
2256 width = desk.width();
2257 if( img.height() < 50 )
2259 else if( img.height()+20 < desk.height() )
2260 height = img.height()+20;
2262 height = desk.height();
2263 mMainWindow->resize( width, height );
2266 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2267 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2269 KURL::encode_string( aFileName ) +
2270 "\" border=\"0\">\n"
2271 "</body></html>\n" );
2273 setCaption( i18n(
"View Attachment: %1").arg( pname ) );
2277 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2278 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2281 TQString str = aMsgPart->bodyDecoded();
2284 if( str.length() < (
unsigned) aMsgPart->decodedSize() ) {
2285 str.prepend( i18n(
"[KMail: Attachment contains binary data. Trying to show first character.]",
2286 "[KMail: Attachment contains binary data. Trying to show first %n characters.]",
2287 str.length()) + TQChar(
'\n') );
2289 htmlWriter()->queue( TQStyleSheet::escape( str ) );
2293 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2302 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2305 mAtmCurrentName = name;
2306 if ( mAtmCurrentName.isEmpty() )
2307 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2309 KMMessagePart& msgPart = node->msgPart();
2310 TQString pname = msgPart.fileName();
2311 if (pname.isEmpty()) pname=msgPart.name();
2312 if (pname.isEmpty()) pname=msgPart.contentDescription();
2313 if (pname.isEmpty()) pname=
"unnamed";
2315 if (kasciistricmp(msgPart.typeStr(),
"message")==0) {
2317 }
else if ((kasciistricmp(msgPart.typeStr(),
"text")==0) &&
2318 (kasciistricmp(msgPart.subtypeStr(),
"x-vcard")==0)) {
2321 KMReaderMainWin *win =
new KMReaderMainWin(&msgPart,
htmlMail(),
2329 void KMReaderWin::openAttachment(
int id,
const TQString & name )
2331 mAtmCurrentName = name;
2334 TQString str, pname, cmd, fileName;
2336 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2338 kdWarning(5006) <<
"KMReaderWin::openAttachment - could not find node " <<
id << endl;
2341 if ( mAtmCurrentName.isEmpty() )
2342 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2344 KMMessagePart& msgPart = node->msgPart();
2345 if (kasciistricmp(msgPart.typeStr(),
"message")==0)
2351 TQCString contentTypeStr( msgPart.typeStr() +
'/' + msgPart.subtypeStr() );
2352 kasciitolower( contentTypeStr.data() );
2354 if ( qstrcmp( contentTypeStr,
"text/x-vcard" ) == 0 ) {
2360 KMimeType::Ptr mimetype;
2362 mimetype = KMimeType::mimeType( TQString::fromLatin1( contentTypeStr ) );
2363 if ( mimetype->name() ==
"application/octet-stream" ) {
2365 mimetype = KMimeType::findByPath( name, 0,
true );
2367 if ( ( mimetype->name() ==
"application/octet-stream" )
2368 && msgPart.isComplete() ) {
2371 mimetype = KMimeType::findByFileContent( name );
2374 KService::Ptr offer =
2375 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
2378 TQString filenameText = msgPart.fileName();
2379 if ( filenameText.isEmpty() )
2380 filenameText = msgPart.name();
2382 open_text = i18n(
"&Open with '%1'").arg( offer->name() );
2384 open_text = i18n(
"&Open With...");
2386 const TQString text = i18n(
"Open attachment '%1'?\n"
2387 "Note that opening an attachment may compromise "
2388 "your system's security.")
2389 .arg( filenameText );
2390 const int choice = KMessageBox::questionYesNoCancel(
this, text,
2391 i18n(
"Open Attachment?"), KStdGuiItem::saveAs(), open_text,
2392 TQString::fromLatin1(
"askSave") + mimetype->name() );
2394 if( choice == KMessageBox::Yes ) {
2396 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2397 message(), mAtmCurrent, mAtmCurrentName, KMHandleAttachmentCommand::Save,
2399 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2400 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2403 else if( choice == KMessageBox::No ) {
2404 KMHandleAttachmentCommand::AttachmentAction action = ( offer ?
2405 KMHandleAttachmentCommand::Open : KMHandleAttachmentCommand::OpenWith );
2407 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2408 message(), mAtmCurrent, mAtmCurrentName, action, offer,
this );
2409 connect( command, TQ_SIGNAL( showAttachment(
int,
const TQString& ) ),
2410 this, TQ_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2413 kdDebug(5006) <<
"Canceled opening attachment" << endl;
2420 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -10);
2425 void KMReaderWin::slotScrollDown()
2427 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, 10);
2430 bool KMReaderWin::atBottom()
const
2432 const TQScrollView *view =
static_cast<const TQScrollView *
>(mViewer->widget());
2433 return view->contentsY() + view->visibleHeight() >= view->contentsHeight();
2437 void KMReaderWin::slotJumpDown()
2439 TQScrollView *view =
static_cast<TQScrollView *
>(mViewer->widget());
2440 int offs = (view->clipper()->height() < 30) ? view->clipper()->height() : 30;
2441 view->scrollBy( 0, view->clipper()->height() - offs );
2445 void KMReaderWin::slotScrollPrior()
2447 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -(
int)(height()*0.8));
2452 void KMReaderWin::slotScrollNext()
2454 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, (
int)(height()*0.8));
2458 void KMReaderWin::slotDocumentChanged()
2465 void KMReaderWin::slotTextSelected(
bool)
2467 TQString temp = mViewer->selectedText();
2468 kapp->clipboard()->setText(temp);
2474 mViewer->selectAll();
2480 TQString temp = mViewer->selectedText();
2486 void KMReaderWin::slotDocumentDone()
2493 void KMReaderWin::setHtmlOverride(
bool override)
2495 mHtmlOverride =
override;
2504 mHtmlLoadExtDefault = loadExtDefault;
2509 mHtmlLoadExtOverride = loadExtOverride;
2516 return ((mHtmlMail && !mHtmlOverride) || (!mHtmlMail && mHtmlOverride));
2525 return mHtmlLoadExtOverride;
2529 if (mRootNode->overallEncryptionState() != KMMsgNotEncrypted)
2531 return mHtmlLoadExtOverride;
2534 return ((mHtmlLoadExtDefault && !mHtmlLoadExtOverride) ||
2535 (!mHtmlLoadExtDefault && mHtmlLoadExtOverride));
2542 const TQScrollView * scrollview =
static_cast<TQScrollView *
>( mViewer->widget() );
2543 mSavedRelativePosition =
2544 static_cast<float>( scrollview->contentsY() ) / scrollview->contentsHeight();
2553 setMsg( msg, force,
true );
2561 KMFolder*& folder = aFolder ? *aFolder : tmpFolder;
2572 kdWarning(5006) <<
"Attempt to reference invalid serial number " << mLastSerNum <<
"\n" << endl;
2581 void KMReaderWin::slotUrlClicked()
2583 KMMainWidget *mainWidget =
dynamic_cast<KMMainWidget*
>(mMainWindow);
2586 identity =
message()->parent()->identity();
2589 KMCommand *command =
new KMUrlClickedCommand( mClickedUrl, identity,
this,
2590 false, mainWidget );
2595 void KMReaderWin::slotMailtoCompose()
2597 KMCommand *command =
new KMMailtoComposeCommand( mClickedUrl,
message() );
2602 void KMReaderWin::slotMailtoForward()
2604 KMCommand *command =
new KMMailtoForwardCommand( mMainWindow, mClickedUrl,
2610 void KMReaderWin::slotMailtoAddAddrBook()
2612 KMCommand *command =
new KMMailtoAddAddrBookCommand( mClickedUrl,
2618 void KMReaderWin::slotMailtoOpenAddrBook()
2620 KMCommand *command =
new KMMailtoOpenAddrBookCommand( mClickedUrl,
2630 KMCommand *command =
2631 new KMUrlCopyCommand( mClickedUrl,
2632 dynamic_cast<KMMainWidget*
>( mMainWindow ) );
2639 if ( !url.isEmpty() )
2641 KMCommand *command =
new KMUrlOpenCommand( mClickedUrl,
this );
2646 void KMReaderWin::slotAddBookmarks()
2648 KMCommand *command =
new KMAddBookmarksCommand( mClickedUrl,
this );
2655 KMCommand *command =
new KMUrlSaveCommand( mClickedUrl, mMainWindow );
2662 KMCommand *command =
new KMMailtoReplyCommand( mMainWindow, mClickedUrl,
2669 return mRootNode ? mRootNode->findId(
msgPartFromUrl( url ) ) : 0 ;
2672 partNode * KMReaderWin::partNodeForId(
int id ) {
2673 return mRootNode ? mRootNode->findId(
id ) : 0 ;
2677 KURL KMReaderWin::tempFileUrlFromPartNode(
const partNode * node )
2679 if (!node)
return KURL();
2680 TQStringList::const_iterator it = mTempFiles.begin();
2681 TQStringList::const_iterator end = mTempFiles.end();
2683 while ( it != end ) {
2684 TQString path = *it;
2686 uint right = path.findRev(
'/');
2687 uint left = path.findRev(
'.', right);
2690 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
2691 if ( res == node->nodeId() )
2692 return KURL::fromPathOrURL( path );
2698 void KMReaderWin::slotSaveAttachments()
2701 KMSaveAttachmentsCommand *saveCommand =
new KMSaveAttachmentsCommand( mMainWindow,
2703 saveCommand->start();
2707 void KMReaderWin::saveAttachment(
const KURL &tempFileName )
2710 mAtmCurrentName = mClickedUrl.path();
2711 slotHandleAttachment( KMHandleAttachmentCommand::Save );
2715 void KMReaderWin::slotSaveMsg()
2717 KMSaveMsgCommand *saveCommand =
new KMSaveMsgCommand( mMainWindow,
message() );
2719 if (saveCommand->url().isEmpty())
2722 saveCommand->start();
2727 KMCommand *command =
new KMIMChatCommand( mClickedUrl,
message() );
2732 static TQString linkForNode(
const DOM::Node &node )
2735 if ( node.isNull() )
2738 const DOM::NamedNodeMap attributes = node.attributes();
2739 if ( !attributes.isNull() ) {
2740 const DOM::Node href = attributes.getNamedItem( DOM::DOMString(
"href" ) );
2741 if ( !href.isNull() ) {
2742 return href.nodeValue().string();
2745 if ( !node.parentNode().isNull() ) {
2746 return linkForNode( node.parentNode() );
2750 }
catch ( DOM::DOMException &e ) {
2751 kdWarning(5006) <<
"Got an exception when trying to determine link under cursor!" << endl;
2759 if ( e->type() == TQEvent::MouseButtonPress ) {
2760 TQMouseEvent* me =
static_cast<TQMouseEvent*
>(e);
2761 if ( me->button() == TQt::LeftButton && ( me->state() & ShiftButton ) ) {
2763 URLHandlerManager::instance()->handleShiftClick( mHoveredUrl,
this );
2767 if ( me->button() == TQt::LeftButton ) {
2770 const DOM::Node nodeUnderMouse = mViewer->nodeUnderMouse();
2771 if ( !nodeUnderMouse.isNull() ) {
2772 const DOM::NamedNodeMap attributes = nodeUnderMouse.attributes();
2773 if ( !attributes.isNull() ) {
2774 const DOM::Node src = attributes.getNamedItem( DOM::DOMString(
"src" ) );
2775 if ( !src.isNull() ) {
2776 imagePath = src.nodeValue().string();
2781 mCanStartDrag = URLHandlerManager::instance()->willHandleDrag( mHoveredUrl, imagePath,
this );
2782 mLastClickPosition = me->pos();
2783 mLastClickImagePath = imagePath;
2787 if ( e->type() == TQEvent::MouseButtonRelease ) {
2788 mCanStartDrag =
false;
2791 if ( e->type() == TQEvent::MouseMove ) {
2792 TQMouseEvent* me =
static_cast<TQMouseEvent*
>( e );
2796 slotUrlOn( linkForNode( mViewer->nodeUnderMouse() ) );
2798 if ( ( mLastClickPosition - me->pos() ).manhattanLength() > TDEGlobalSettings::dndEventDelay() ) {
2799 if ( mCanStartDrag && ( !( mHoveredUrl.isEmpty() && mLastClickImagePath.isEmpty() ) ) ) {
2800 if ( URLHandlerManager::instance()->handleDrag( mHoveredUrl, mLastClickImagePath,
this ) ) {
2801 mCanStartDrag =
false;
2807 TQMouseEvent mouseEvent( TQEvent::MouseButtonRelease, me->pos(), TQt::NoButton, TQt::NoButton );
2808 static_cast<TQObject*
>(mViewer->view())->
eventFilter( mViewer->view()->viewport(),
2822 Q_ASSERT( msg && nodeId );
2824 if ( mSerNumOfOriginalMessage != 0 ) {
2828 if ( folder && index != -1 )
2829 *msg = folder->
getMsg( index );
2832 kdWarning( 5006 ) <<
"Unable to find the original message, aborting attachment deletion!" << endl;
2836 *nodeId = node->nodeId() + mNodeIdOffset;
2839 *nodeId = node->nodeId();
2844 void KMReaderWin::slotDeleteAttachment(partNode * node)
2846 if ( KMessageBox::warningContinueCancel(
this,
2847 i18n(
"Deleting an attachment might invalidate any digital signature on this message."),
2848 i18n(
"Delete Attachment"), KStdGuiItem::del(),
"DeleteAttachmentSignatureWarning" )
2849 != KMessageBox::Continue ) {
2856 if ( msg && nodeId != -1 ) {
2857 KMDeleteAttachmentCommand* command =
new KMDeleteAttachmentCommand( nodeId, msg,
this );
2859 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
2861 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
2870 connect( headers, TQ_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2871 this, TQ_SLOT( msgAdded( TQListViewItem* ) ) );
2875 if ( mSerNumOfOriginalMessage != 0 &&
message() ) {
2881 void KMReaderWin::msgAdded( TQListViewItem *item )
2888 headers->setCurrentItem( item );
2889 headers->clearSelection();
2896 disconnect( headers, TQ_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2897 this, TQ_SLOT( msgAdded( TQListViewItem* ) ) );
2900 void KMReaderWin::slotEditAttachment(partNode * node)
2902 if ( KMessageBox::warningContinueCancel(
this,
2903 i18n(
"Modifying an attachment might invalidate any digital signature on this message."),
2904 i18n(
"Edit Attachment"), KGuiItem( i18n(
"Edit"),
"edit" ),
"EditAttachmentSignatureWarning" )
2905 != KMessageBox::Continue ) {
2912 if ( msg && nodeId != -1 ) {
2913 KMEditAttachmentCommand* command =
new KMEditAttachmentCommand( nodeId, msg,
this );
2920 KMail::CSSHelper* KMReaderWin::cssHelper()
2927 if ( !GlobalSettings::self()->alwaysDecrypt() )
2928 return mDecrytMessageOverwrite;
2934 DOM::Document doc = mViewer->htmlDocument();
2937 mViewer->gotoAnchor( TQString::fromLatin1(
"att%1" ).arg( node->nodeId() ) );
2940 const partNode *root = node->topLevelParent();
2941 for (
int i = 0; i <= root->totalChildCount() + 1; i++ ) {
2942 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( i + 1 ) );
2943 if ( !attachmentDiv.isNull() )
2944 attachmentDiv.removeAttribute(
"style" );
2948 if ( node->isDisplayedHidden() )
2954 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( node->nodeId() ) );
2955 if ( attachmentDiv.isNull() ) {
2956 kdWarning( 5006 ) <<
"Could not find attachment div for attachment " << node->nodeId() << endl;
2960 attachmentDiv.setAttribute(
"style", TQString(
"border:2px solid %1" )
2961 .arg( cssHelper()->pgpWarnColor().name() ) );
2965 doc.updateRendering();
2968 void KMReaderWin::injectAttachments()
2972 DOM::Document doc = mViewer->htmlDocument();
2973 DOM::Element injectionPoint = doc.getElementById(
"attachmentInjectionPoint" );
2974 if ( injectionPoint.isNull() )
2977 TQString imgpath( locate(
"data",
"kmail/pics/") );
2978 TQString visibility;
2981 if( !showAttachmentQuicklist() ) {
2982 urlHandle.append(
"kmail:showAttachmentQuicklist" );
2983 imgSrc.append(
"attachmentQuicklistClosed.png" );
2985 urlHandle.append(
"kmail:hideAttachmentQuicklist" );
2986 imgSrc.append(
"attachmentQuicklistOpened.png" );
2989 TQString html = renderAttachments( mRootNode, TQApplication::palette().active().background() );
2990 if ( html.isEmpty() )
2994 if ( headerStyle() == HeaderStyle::fancy() ) {
2995 link +=
"<div style=\"text-align: left;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2996 imgpath + imgSrc +
"\"/></a></div>";
2997 html.prepend( link );
2998 html.prepend( TQString::fromLatin1(
"<div style=\"float:left;\">%1 </div>" ).
2999 arg( i18n(
"Attachments:" ) ) );
3001 link +=
"<div style=\"text-align: right;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
3002 imgpath + imgSrc +
"\"/></a></div>";
3003 html.prepend( link );
3006 assert( injectionPoint.tagName() ==
"div" );
3007 static_cast<DOM::HTMLElement
>( injectionPoint ).setInnerHTML( html );
3010 static TQColor nextColor(
const TQColor & c )
3013 c.hsv( &h, &s, &v );
3014 return TQColor( (h + 50) % 360, TQMAX(s, 64), v, TQColor::Hsv );
3017 TQString KMReaderWin::renderAttachments(partNode * node,
const TQColor &bgColor )
3023 if ( node->firstChild() ) {
3024 TQString subHtml = renderAttachments( node->firstChild(), nextColor( bgColor ) );
3025 if ( !subHtml.isEmpty() ) {
3027 TQString visibility;
3028 if ( !showAttachmentQuicklist() ) {
3029 visibility.append(
"display:none;" );
3033 if ( node != mRootNode || headerStyle() != HeaderStyle::enterprise() )
3034 margin =
"padding:2px; margin:2px; ";
3035 TQString align =
"left";
3036 if ( headerStyle() == HeaderStyle::enterprise() )
3038 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3039 html += TQString::fromLatin1(
"<div style=\"background:%1; %2"
3040 "vertical-align:middle; float:%3; %4\">").arg( bgColor.name() ).arg( margin )
3041 .arg( align ).arg( visibility );
3043 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
3047 partNode::AttachmentDisplayInfo info = node->attachmentDisplayInfo();
3050 bool writePartToDisk = info.displayInHeader || node->msgPart().subtype() == DwMime::kSubtypeHtml;
3051 if ( writePartToDisk )
3054 if ( info.displayInHeader ) {
3055 html +=
"<div style=\"float:left;\">";
3056 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() );
3057 TQString href = node->asHREF(
"header" );
3058 html += TQString::fromLatin1(
"<a href=\"" ) + href +
3059 TQString::fromLatin1(
"\">" );
3060 html +=
"<img style=\"vertical-align:middle;\" src=\"" + info.icon +
"\"/> ";
3061 if ( headerStyle() == HeaderStyle::enterprise() ) {
3062 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3063 TQFontMetrics fm( bodyFont );
3064 html += KStringHandler::rPixelSqueeze( info.label, fm, 140 );
3065 }
else if ( headerStyle() == HeaderStyle::fancy() ) {
3066 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
3067 TQFontMetrics fm( bodyFont );
3068 html += KStringHandler::rPixelSqueeze( info.label, fm, 640 );
3072 html +=
"</a></span></div> ";
3076 html += renderAttachments( node->nextSibling(), nextColor ( bgColor ) );
3082 void KMReaderWin::setBodyPartMemento(
const partNode * node,
const TQCString & which,
BodyPartMemento * memento )
3084 const TQCString index = node->path() +
':' + which.lower();
3086 const std::map<TQCString,BodyPartMemento*>::iterator it = mBodyPartMementoMap.lower_bound( index );
3087 if ( it != mBodyPartMementoMap.end() && it->first == index ) {
3089 if ( memento && memento == it->second )
3095 it->second = memento;
3098 mBodyPartMementoMap.erase( it );
3103 mBodyPartMementoMap.insert( it, std::make_pair( index, memento ) );
3111 BodyPartMemento * KMReaderWin::bodyPartMemento(
const partNode * node,
const TQCString & which )
const
3113 const TQCString index = node->path() +
':' + which.lower();
3114 const std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.find( index );
3115 if ( it == mBodyPartMementoMap.end() ) {
3129 void KMReaderWin::clearBodyPartMementos()
3131 for ( std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.begin(), end = mBodyPartMementoMap.end() ; it != end ; ++it )
3136 detach_and_delete( it->second,
this );
3138 mBodyPartMementoMap.clear();
3141 #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...