10#include "kmreaderwin.h"
12#include "globalsettings.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"
21using KMail::MailSourceViewer;
24#include "messagesender.h"
25#include "kcursorsaver.h"
27#include "vcardviewer.h"
28using KMail::VCardViewer;
29#include "objecttreeparser.h"
30using KMail::ObjectTreeParser;
31#include "partmetadata.h"
32using KMail::PartMetaData;
33#include "attachmentstrategy.h"
34using KMail::AttachmentStrategy;
35#include "headerstrategy.h"
36using KMail::HeaderStrategy;
37#include "headerstyle.h"
39#include "tdehtmlparthtmlwriter.h"
41using KMail::KHtmlPartHtmlWriter;
42#include "htmlstatusbar.h"
45using KMail::FolderJob;
47using KMail::CSSHelper;
50#include "urlhandlermanager.h"
52#include "interfaces/observable.h"
56#include "broadcaststatus.h"
60#ifdef KMAIL_READER_HTML_DEBUG
61#include "filehtmlwriter.h"
62using 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>
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>
107#include <tdeaction.h>
108#include <kiconloader.h>
110#include <kasciistricmp.h>
113#include <tqclipboard.h>
115#include <tqtextcodec.h>
116#include <tqpaintdevicemetrics.h>
119#include <tqsplitter.h>
138class NewByteArray :
public TQByteArray
141 NewByteArray &appendNULL();
142 NewByteArray &operator+=(
const char * );
143 NewByteArray &operator+=(
const TQByteArray & );
144 NewByteArray &operator+=(
const TQCString & );
145 TQByteArray& qByteArray();
148NewByteArray& NewByteArray::appendNULL()
150 TQByteArray::detach();
152 if ( !TQByteArray::resize( len1 + 1 ) )
154 *(data() + len1) =
'\0';
157NewByteArray& 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 );
169NewByteArray& 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 );
181NewByteArray& 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 );
193TQByteArray& NewByteArray::qByteArray()
195 return *((TQByteArray*)
this);
202void 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 ) {
280kdDebug(5006) <<
"dataNode == curNode: Save curNode without replacing it." << endl;
286 if( dataNode->parentNode() && !weAreReplacingTheRootNode ) {
287kdDebug(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() ){
290kdDebug(5006) <<
"dataNode replace the root node: Do NOT store the headers but change" << endl;
291kdDebug(5006) <<
" the Message's headers accordingly." << endl;
292kdDebug(5006) <<
" old Content-Type = " << rootHeaders.ContentType().AsString().c_str() << endl;
293kdDebug(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() ) {
311kdDebug(5006) <<
"is valid Multipart, processing children:" << endl;
312 TQCString boundary = headers->ContentType().Boundary().c_str();
313 curNode = dataNode->firstChild();
316kdDebug(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();
334kdDebug(5006) <<
"--boundary--" << endl;
335 resultingData +=
"\n--";
336 resultingData += boundary;
337 resultingData +=
"--\n\n";
338kdDebug(5006) <<
"Multipart processing children - DONE" << endl;
341kdDebug(5006) <<
"is Simple part or invalid Multipart, storing body data .. DONE" << endl;
342 resultingData += part->Body().AsString().c_str();
346kdDebug(5006) <<
"dataNode != curNode: Replace curNode by dataNode." << endl;
347 bool rootNodeReplaceFlag = weAreReplacingTheRootNode || !curNode->parentNode();
348 if( rootNodeReplaceFlag ) {
349kdDebug(5006) <<
" Root node will be replaced." << endl;
351kdDebug(5006) <<
" Root node will NOT be replaced." << endl;
355 objectTreeToDecryptedMsg( dataNode,
362 kdDebug(5006) << TQString(
"\nKMReaderWin::objectTreeToDecryptedMsg( %1 ) END").arg( recCount ) << endl;
386void 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" );
393 mBox->setFrameStyle( mMimePartTree->frameStyle() );
395 mViewer =
new TDEHTMLPart( mBox,
"mViewer" );
396 mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
397 mSplitter->setResizeMode( mMimePartTree, TQSplitter::KeepSize );
400const int KMReaderWin::delay = 150;
403KMReaderWin::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()) );
483void 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,
633TDERadioAction *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));
657TDERadioAction *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));
678void KMReaderWin::slotEnterpriseHeaders() {
680 HeaderStrategy::rich() );
681 if( !mExternalWindow )
685void KMReaderWin::slotFancyHeaders() {
687 HeaderStrategy::rich() );
688 if( !mExternalWindow )
692void KMReaderWin::slotBriefHeaders() {
694 HeaderStrategy::brief() );
695 if( !mExternalWindow )
699void KMReaderWin::slotStandardHeaders() {
701 HeaderStrategy::standard());
705void KMReaderWin::slotLongHeaders() {
707 HeaderStrategy::rich() );
708 if( !mExternalWindow )
712void KMReaderWin::slotAllHeaders() {
714 HeaderStrategy::all() );
715 if( !mExternalWindow )
719void KMReaderWin::slotLevelQuote(
int l )
726void 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 );
759void KMReaderWin::slotIconicAttachments() {
760 setAttachmentStrategy( AttachmentStrategy::iconic() );
763void KMReaderWin::slotSmartAttachments() {
764 setAttachmentStrategy( AttachmentStrategy::smart() );
767void KMReaderWin::slotInlineAttachments() {
768 setAttachmentStrategy( AttachmentStrategy::inlined() );
771void KMReaderWin::slotHideAttachments() {
772 setAttachmentStrategy( AttachmentStrategy::hidden() );
775void KMReaderWin::slotHeaderOnlyAttachments() {
776 setAttachmentStrategy( AttachmentStrategy::headerOnly() );
779void KMReaderWin::slotCycleAttachmentStrategy() {
783 action->setChecked(
true );
788KMReaderWin::~KMReaderWin()
793 clearBodyPartMementos();
794 delete mHtmlWriter; mHtmlWriter = 0;
796 if (mAutoDelete)
delete message();
797 delete mRootNode; mRootNode = 0;
803void 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();
953void 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 )
972void 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() ),
1037void 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 );
1056void 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();
1111void KMReaderWin::setPrintFont(
const TQFont& font )
1114 mCSSHelper->setPrintFont( font );
1120 if ( mOverrideEncoding.isEmpty() || mOverrideEncoding ==
"Auto" )
1123 return KMMsgBase::codecForName( mOverrideEncoding.latin1() );
1127void KMReaderWin::slotSetEncoding()
1129 if ( mSelectEncodingAction->currentItem() == 0 )
1130 mOverrideEncoding = TQString();
1132 mOverrideEncoding = TDEGlobal::charsets()->encodingForName( mSelectEncodingAction->currentText() );
1137void 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;
1256static const char *
const kmailChanges[] = {
1259static const int numKMailChanges =
1260 sizeof kmailChanges /
sizeof *kmailChanges;
1266static 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")
1275static 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()) );
1503static 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 ) ) {
1611kdDebug(5006) <<
"\n\n\nKMReaderWin::parseMsg() - special post-encryption handling:\n1." << endl;
1612kdDebug(5006) <<
"(aMsg == msg) = " << (aMsg ==
message()) << endl;
1613kdDebug(5006) <<
"aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() = " << (aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder()) << endl;
1614kdDebug(5006) <<
"message_was_saved_decrypted_before( aMsg ) = " << message_was_saved_decrypted_before( aMsg ) << endl;
1615kdDebug(5006) <<
"this->decryptMessage() = " <<
decryptMessage() << endl;
1616kdDebug(5006) <<
"otp.hasPendingAsyncJobs() = " << otp.hasPendingAsyncJobs() << endl;
1617kdDebug(5006) <<
" (KMMsgFullyEncrypted == encryptionState) = " << (KMMsgFullyEncrypted == encryptionState) << endl;
1618kdDebug(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) ) ) {
1634kdDebug(5006) <<
"KMReaderWin - calling objectTreeToDecryptedMsg()" << endl;
1636 NewByteArray decryptedData;
1638 objectTreeToDecryptedMsg( mRootNode, decryptedData, *aMsg );
1640 decryptedData.appendNULL();
1641 TQCString resultString( decryptedData.data() );
1642kdDebug(5006) <<
"KMReaderWin - resulting data:" << resultString << endl;
1644 if( !resultString.isEmpty() ) {
1645kdDebug(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 );
1686void 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;
1859void KMReaderWin::resizeEvent(TQResizeEvent *)
1861 if( !mResizeTimer.isActive() )
1867 mResizeTimer.start( 100,
true );
1873void KMReaderWin::slotDelayedResize()
1875 mSplitter->setGeometry(0, 0, width(), height());
1880void 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);
1921bool 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 );
2027static 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 );
2046void 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 );
2102void 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(),
2330void 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);
2426void KMReaderWin::slotScrollDown()
2428 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, 10);
2431bool KMReaderWin::atBottom()
const
2433 const TQScrollView *view =
static_cast<const TQScrollView *
>(mViewer->widget());
2434 return view->contentsY() + view->visibleHeight() >= view->contentsHeight();
2438void 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 );
2446void KMReaderWin::slotScrollPrior()
2448 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -(
int)(height()*0.8));
2453void KMReaderWin::slotScrollNext()
2455 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, (
int)(height()*0.8));
2459void KMReaderWin::slotDocumentChanged()
2466void KMReaderWin::slotTextSelected(
bool)
2468 TQString temp = mViewer->selectedText();
2469 kapp->clipboard()->setText(temp);
2475 mViewer->selectAll();
2481 TQString temp = mViewer->selectedText();
2487void KMReaderWin::slotDocumentDone()
2494void 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;
2582void 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 );
2596void KMReaderWin::slotMailtoCompose()
2598 KMCommand *command =
new KMMailtoComposeCommand( mClickedUrl,
message() );
2603void KMReaderWin::slotMailtoForward()
2605 KMCommand *command =
new KMMailtoForwardCommand( mMainWindow, mClickedUrl,
2611void KMReaderWin::slotMailtoAddAddrBook()
2613 KMCommand *command =
new KMMailtoAddAddrBookCommand( mClickedUrl,
2619void 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 );
2647void 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 ;
2673partNode * KMReaderWin::partNodeForId(
int id ) {
2674 return mRootNode ? mRootNode->findId(
id ) : 0 ;
2678KURL 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::fromPathOrURL( path );
2699void KMReaderWin::slotSaveAttachments()
2702 KMSaveAttachmentsCommand *saveCommand =
new KMSaveAttachmentsCommand( mMainWindow,
2704 saveCommand->start();
2708void KMReaderWin::saveAttachment(
const KURL &tempFileName )
2711 mAtmCurrentName = mClickedUrl.path();
2712 slotHandleAttachment( KMHandleAttachmentCommand::Save );
2716void KMReaderWin::slotSaveMsg()
2718 KMSaveMsgCommand *saveCommand =
new KMSaveMsgCommand( mMainWindow,
message() );
2720 if (saveCommand->url().isEmpty())
2723 saveCommand->start();
2728 KMCommand *command =
new KMIMChatCommand( mClickedUrl,
message() );
2733static 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();
2845void 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() ) {
2882void KMReaderWin::msgAdded( TQListViewItem *item )
2889 headers->setCurrentItem( item );
2890 headers->clearSelection();
2897 disconnect( headers, TQ_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2898 this, TQ_SLOT( msgAdded( TQListViewItem* ) ) );
2901void 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 );
2921KMail::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();
2969void 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 );
3011static TQColor nextColor(
const TQColor & c )
3014 c.hsv( &h, &s, &v );
3015 return TQColor( (h + 50) % 360, TQMAX(s, 64), v, TQColor::Hsv );
3018TQString 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 ) );
3083void 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 ) );
3112BodyPartMemento * 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() ) {
3130void 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"
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.
DwBodyPart * lastUpdatedPart()
Returns the last DwBodyPart that was updated.
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.
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.
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.
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.
KMail::HtmlWriter * htmlWriter()
Return the HtmlWriter connected to the TDEHTMLPart we use.
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.
const KMail::AttachmentStrategy * attachmentStrategy() const
Get/set the message attachment strategy.
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 ...
const KMail::HeaderStrategy * headerStrategy() const
Getthe message header strategy.
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.
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...